Показать сообщение отдельно
Старый 17.02.2005, 09:40   #104
Vam

AGFC
Гость
 
Сообщений: n/a

По умолчанию Re: Уроки скриптологии

7. Описание обработчиков состояний НПС.

Все имена функций состояний должны начинаться с ZS_.
Каждый процесс обработки соответствующего состояния состоит из 3х функций: ZS_xxx, ZS_xxx-Loop, ZS_xxx_End, где ххх - имя соответствующего состояния.
Этим функциям соответствуют 3 фазы одного состояния НПС.
1 фаза - Begin: инициализация состояния НПС.
2 фаза - Loop: цикл выполнения последовательности действий НПС. Функция 2 фазы должна возвращать или LOOP_CONTINUE - продолжение фазы или LOOP_END - конец фазы.
3 фаза - End: завершение состояния НПС.

Системная функция AI_StartState может управлять последовательностью выполнения фаз состояний, за это отвечает параметр stateBehaviour, если он = 0, то выполняются все фазы состояния последовательно, если он = 1, то выполняется только заключительная фаза 3.
Эта функция подробно описана в соответствующей теме.

8. Функции состояний людей.

Все файлы состояний людей расположены в директории ..AI\Human\ZS_Human

// ******************************
// Состояние атаки
// ******************************

// Функция обработки вспомогательного восприятия PERC_ASSESSSURPRISE
// Вызывается ядром системы когда ГГ превращается в человека из животного
func void B_AssessSurprise()
{
* *// self - наблюдатель, other - ГГ
* *// целью наблюдателя становится ГГ
* *Npc_SetTarget(self,other);
* *// причина нападения наблюдателя на ГГ - ГГ враг гильдии
* *self.aivar[AIV_ATTACKREASON] = AR_GuildEnemy;
};

// Функция инициализации состояния атаки
func void ZS_Attack()
{
* *// установить минимальный набор восприятий НПС
* *Perception_Set_Minimal();
* *// установить дополнительное восприятие на превращение
* *Npc_PercEnable(self,PERC_ASSESSSURPRISE,B_AssessS urprise);
* *// инициализировать переменную other (последняя цель)
* *B_ValidateOther();
* *// записать НПС id последней цели
* *self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
* *// если НПС должен убегать от цели
* *if(C_WantToFlee(self,other)) * * * * * * * * * *
* *{
* * * *// очистка очереди AI состояний НПС
* * * *Npc_ClearAIQueue(self);
* * * *// очистка восприятий НПС
* * * *B_ClearPerceptions(self);
* * * *// установка цели для НПС
* * * *Npc_SetTarget(self,other);
* * * *// НПС убегает от цели
* * * *AI_StartState(self,ZS_Flee,0,"");
* * * *return;
* *};
* *// если загрузки игры во время атаки не было
* *if(self.aivar[AIV_LOADGAME] == FALSE)
* *{
* * * *// НПС называет причину атаки
* * * *B_Say_AttackReason();
* *};
* *// если режим сражения у НПС выключен
* *if(Npc_IsInFightMode(self,FMODE_NONE))
* *{
* * * *// НПС достает лучшее оружие дальнего радиуса поражения
* * * *AI_EquipBestRangedWeapon(self);
* * * *// НПС достает лучшее оружие ближнего радиуса поражения
* * * *AI_EquipBestMeleeWeapon(self);
* *};
* *// НПС встает
* *AI_StandUp(self);
* *// перестает смотреть на других
* *B_StopLookAt(self);
* *// поворачивается к цели
* *B_TurnToNpc(self,other);
* *// бежит к цели
* *AI_SetWalkmode(self,NPC_RUN);
* *// сброс статуса предупреждений охраной
* *self.aivar[AIV_Guardpassage_Status] = GP_NONE;
* *// получить репутацию ГГ для конкретной локации
* *self.aivar[AIV_LastAbsolutionLevel] = B_GetCurrentAbsolutionLevel(self);
* *// сброс флага окончания преследования
* *self.aivar[AIV_PursuitEnd] = FALSE;
* *// сброс времени нахождения в состоянии
* *self.aivar[AIV_StateTime] = 0;
* *// сброс переменной вызова охраны (переменная AIV_TAPOSITION переопределена в этом состоянии)
* *self.aivar[AIV_TAPOSITION] = 0;
* *// сброс флага первого удара
* *self.aivar[AIV_HitByOtherNpc] = 0;
* *// сброс выбранного заклинания
* *self.aivar[AIV_SelectSpell] = 0;
};

// Функция цикла атаки
func int ZS_Attack_Loop()
{
* *// Грег идет к Декстеру
* *B_Greg_ComesToDexter();
* *// повторно инициализировать other целью
* *Npc_GetTarget(self);
* *// если расстояние между НПС и целью > дистанции прекращения сражения
* *if(Npc_GetDistToNpc(self,other) > self.aivar[AIV_FightDistCancel])
* *{
* * * *// очистка очереди AI состояний НПС
* * * *Npc_ClearAIQueue(self);
* * * *// НПС встает
* * * *AI_StandUp(self);
* * * *// НПС закончил преследование
* * * *self.aivar[AIV_PursuitEnd] = TRUE;
* * * *return LOOP_END;
* *};
* *// если время преследования превышает допустимое и НПС преследует
* *if(Npc_GetStateTime(self) > self.aivar[AIV_MM_FollowTime]) && (self.aivar[AIV_PursuitEnd] == FALSE)
* *{
* * * *Npc_ClearAIQueue(self);
* * * *AI_StandUp(self);
* * * *// НПС закончил преследование
* * * *self.aivar[AIV_PursuitEnd] = TRUE;
* * * *// получить дистанцию до цели
* * * *self.aivar[AIV_Dist] = Npc_GetDistToNpc(self,other);
* * * *// обновить время состояния НПС
* * * *self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
* * * *// если цель человек
* * * *if(other.guild < GIL_SEPERATOR_HUM)
* * * *{
* * * * * *// НПС говорит цели "Беги, трус!" (SVM фраза)
* * * * * *B_Say(self,other,"$RUNCOWARD");
* * * *};
* *};
* *// если НПС завершил преследование цели
* *if(self.aivar[AIV_PursuitEnd] == TRUE)
* *{
* * * *// если расстояние между НПС и целью > диапазона чувствительности НПС
* * * *if(Npc_GetDistToNpc(self,other) > (self.senses_range))
* * * *{
* * * * * *return LOOP_END;
* * * *};
* * * *// если текущее время > предыдущего времени (прошла как минимум секунда)
* * * *if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime])
* * * *{
* * * * * *// если расстояние между НПС и целью меньше дистанции, когда НПС прекратил преследование
* * * * * *if(Npc_GetDistToNpc(self,other) < self.aivar[AIV_Dist])
* * * * * *// или (цель не бежит и не прыгает)
* * * * * *¦¦ ((!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP)))
* * * * * *{
* * * * * * * *// сброс флага окончания преследования
* * * * * * * *self.aivar[AIV_PursuitEnd] = FALSE;
* * * * * * * *// сброс времени нахождения НПС в этом состоянии
* * * * * * * *Npc_SetStateTime(self,0);
* * * * * * * *// сброс времени нахождения в состоянии
* * * * * * * *self.aivar[AIV_StateTime] = 0;
* * * * * *}
* * * * * *else
* * * * * *{
* * * * * * * *// НПС поворачивается к цели
* * * * * * * *B_TurnToNpc(self,other);
* * * * * * * *// получить дистанцию до цели
* * * * * * * *self.aivar[AIV_Dist] = Npc_GetDistToNpc(self,other);
* * * * * * * *// обновить время состояния НПС
* * * * * * * *self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
* * * * * *};
* * * *};
* * * *return LOOP_CONTINUE;
* *};
* *// если уровень достигнутый ГГ в сражении > первоначального уровня
* *if(B_GetCurrentAbsolutionLevel(self) > self.aivar[AIV_LastAbsolutionLevel])
* *{
* * * *// очистка очереди AI состояний НПС
* * * *Npc_ClearAIQueue(self);
* * * *// НПС встает
* * * *AI_StandUp(self);
* * * *// прекращение атаки
* * * *return LOOP_END;
* *};
* *// если (цель плывет или ныряет) и НПС не преследует цель в воде
* *if(C_BodyStateContains(other,BS_SWIM) ¦¦ C_BodyStateContains(other,BS_DIVE)) && (self.aivar[AIV_MM_FollowInWater] == FALSE)
* *{
* * * *Npc_ClearAIQueue(self);
* * * *AI_StandUp(self);
* * * *// НПС закончил преследование
* * * *self.aivar[AIV_PursuitEnd] = TRUE;
* * * *return LOOP_END;
* *};
* *// если НПС выжидает перед атакой
* *if(self.aivar[AIV_WaitBeforeAttack] >= 1)
* *{
* * * *// ожидание 0.8 сек
* * * *AI_Wait(self,0.8 );
* * * *// сброс флага задержки
* * * *self.aivar[AIV_WaitBeforeAttack] = 0;
* *};
* *// если дистанция атаки > 0
* *if(self.aivar[AIV_MaxDistToWp] > 0)
* *{
* * * *// если расстояние между НПС и вайпоинтом НПС > дистанции атаки и расстояние между целью и вайпоинтом НПС > дистанции акаки
* * * *if(Npc_GetDistToWP(self,self.wp) > self.aivar[AIV_MaxDistToWp]) && (Npc_GetDistToWP(other,self.wp) > self.aivar[AIV_MaxDistToWp])
* * * *{
* * * * * *// установить НПС тактику защитников крепостных стен
* * * * * *self.fight_tactic = FAI_NAILED;
* * * *}
* * * *else // иначе (если НПС или цель близка к вайпоинту НПС)
* * * *{
* * * * * *// установить НПС родную тактику сражения
* * * * * *self.fight_tactic = self.aivar[AIV_OriginalFightTactic];
* * * *};
* *};
* *// если цель не бежит и не прыгает
* *if((!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP)))
* *{
* * * *// сброс времени текущего состояния
* * * *Npc_SetStateTime(self,0);
* *};
* *// если время в состоянии > 2 сек (от последнего сброса) и охрана не вызывалась
* *if(Npc_GetStateTime(self) > 2) && (self.aivar[AIV_TAPOSITION] == 0)
* *{
* * * *// вызов охраны
* * * *B_CallGuards();
* * * *// установка следующей фазы вызова охраны
* * * *self.aivar[AIV_TAPOSITION] = 1;
* *};
* *// если время в состоянии > 8 сек и охрана вызывалась
* *if(Npc_GetStateTime(self) > 8 ) && (self.aivar[AIV_TAPOSITION] == 1)
* *{
* * * *// вызов охраны
* * * *B_CallGuards();
* * * *// установка следующей фазы вызова охраны (было 2 вызова)
* * * *self.aivar[AIV_TAPOSITION] = 2;
* *};
* *// подготовка НПС боезапаса
* *B_CreateAmmo(self);
* *// выбор соответствующего цели оружия
* *B_SelectWeapon(self,other);
* *// если цель существует и не обездвижена
* *if((Hlp_IsValidNpc(other)) && (C_NpcIsDown(other) == FALSE))
* *{
* * * *// если цель не в состоянии разговора
* * * *if(other.aivar[AIV_INVINCIBLE] == FALSE)
* * * *{
* * * * * *// НПС атакует цель (Примечание: функция AI_Attack работает только когда очередь AI состояний НПС пуста)
* * * * * *AI_Attack(self);
* * * *}
* * * *else
* * * *{
* * * * * *// очистка очереди AI состояний НПС
* * * * * *Npc_ClearAIQueue(self);
* * * *};
* * * *// запись НПС id последней цели
* * * *self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
* * * *return LOOP_CONTINUE;
* *}
* *else // иначе (если цель отсутствует или обездвижена)
* *{
* * * *// очистка очереди AI состояний НПС
* * * *Npc_ClearAIQueue(self);
* * * *// если цель существует и цель ГГ и ГГ обездвижен
* * * *if(Hlp_IsValidNpc(other)) && (Npc_IsPlayer(other)) && (C_NpcIsDown(other))
* * * *{
* * * * * *// замена временного отношения НПС к ГГ на постоянное
* * * * * *Npc_SetTempAttitude(self,Npc_GetPermAttitude(self ,hero));
* * * *};
* * * *// если причина атаки НПС не убийство цели
* * * *if(self.aivar[AIV_ATTACKREASON] != AR_KILL)
* * * *{
* * * * * *// НПС разрешено воспринимать все объекты
* * * * * *Npc_PerceiveAll(self);
* * * * * *// НПС ищет новую цель other
* * * * * *Npc_GetNextTarget(self);
* * * *};
* * * *// если цель существует и она не обездвижена
* * * *if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other))
* * * *// и (расстояние от НПС до цели < дистанции восприятия или цель ГГ)
* * * *&& ((Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT) ¦¦ (Npc_IsPlayer(other)))
* * * *// и расстояние между НПС и целью по высоте < дистанции восприятия по высоте
* * * *&& (Npc_GetHeightToNpc(self,other) < PERC_DIST_HEIGHT)
* * * *// и цель не в разговоре
* * * *&& (other.aivar[AIV_INVINCIBLE] == FALSE)
* * * *// и цель ГГ не является переодетым бандитом и НПС бандит
* * * *&& (!(C_PlayerIsFakeBandit(self,other) && (self.guild == GIL_BDT)))
* * * *{
* * * * * *// если гильдии НПС и цели враждебны
* * * * * *if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_HOSTILE)
* * * * * *{
* * * * * * * *// причина атаки - враждебная гильдия
* * * * * * * *self.aivar[AIV_ATTACKREASON] = AR_GuildEnemy;
* * * * * * * *// если цель ГГ
* * * * * * * *if(Npc_IsPlayer(other))
* * * * * * * *{
* * * * * * * * * *// установить причину последнего нападения на ГГ
* * * * * * * * * *self.aivar[AIV_LastPlayerAR] = AR_GuildEnemy;
* * * * * * * * * *// параметр последнего сражения с ГГ - прервано
* * * * * * * * * *self.aivar[AIV_LastFightAgainstPlayer] = FIGHT_CANCEL;
* * * * * * * * * *// сброс комментария сражения
* * * * * * * * * *self.aivar[AIV_LastFightComment] = FALSE;
* * * * * * * *};
* * * * * *}
* * * * * *// иначе, если сам НПС является врагом цели
* * * * * *else if(Npc_GetAttitude(self,other) == ATT_HOSTILE)
* * * * * *{
* * * * * * * *// причина атаки = причину последнего нападения на ГГ
* * * * * * * *self.aivar[AIV_ATTACKREASON] = self.aivar[AIV_LastPlayerAR];
* * * * * *};
* * * * * *return LOOP_CONTINUE;
* * * *}
* * * *else
* * * *{
* * * * * *// очистка очереди AI состояний НПС
* * * * * *Npc_ClearAIQueue(self);
* * * * * *// если последнее сражение с ГГ прервано и последняя цель не ГГ
* * * * * *if(self.aivar[AIV_LastFightAgainstPlayer] == FIGHT_CANCEL) && (self.aivar[AIV_LASTTARGET] != Hlp_GetInstanceID(hero))
* * * * * *{
* * * * * * * *// комментировать сражение не нужно
* * * * * * * *self.aivar[AIV_LastFightComment] = TRUE;
* * * * * *};
* * * * * *return LOOP_END;
* * * *};
* *};
};

//Функция завершения состояния атаки
func void ZS_Attack_End()
{
* *// установить other на последнюю цель
* *other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
* *// усли преследование было прекращено
* *if(self.aivar[AIV_PursuitEnd] == TRUE)
* *{ * * *
* * * *// если цель существует и цель ГГ и НПС не друг цели
* * * *if(Hlp_IsValidNpc(other)) && (Npc_IsPlayer(other)) && (self.npctype != NPCTYPE_FRIEND)
* * * *{
* * * * * *// установить временное отношение НПС к ГГ на враждебное
* * * * * *Npc_SetTempAttitude(self,ATT_HOSTILE);
* * * *};
* * * *// если НПС сражался на арене (состояние - в процессе сражения)
* * * *if(self.aivar[AIV_ArenaFight] == AF_RUNNING)
* * * *{
* * * * * *// установить состояние после сражения
* * * * * *self.aivar[AIV_ArenaFight] = AF_AFTER;
* * * *};
* *};
* *// если преследования не было
* *if(self.aivar[AIV_PursuitEnd] == FALSE)
* *{
* * * *// если уровень достигнутый ГГ в сражении > первоначального уровня
* * * *if(B_GetCurrentAbsolutionLevel(self) > self.aivar[AIV_LastAbsolutionLevel])
* * * *{
* * * * * *// НПС говорит цели "Умный малый!" (SVM фраза)
* * * * * *B_Say(self,other,"$WISEMOVE");
* * * *}
* * * *else
* * * *{
* * * * * *// обычная фраза завершения атаки
* * * * * *B_Say_AttackEnd();
* * * *};
* *};
* *// если цель убита ГГ и отношения гильдий НПС и ГГ не враждебные
* *if(other.aivar[AIV_KilledByPlayer] == TRUE) && (Wld_GetGuildAttitude(self.guild,hero.guild) != ATT_HOSTILE)
* *{
* * * *// НПС становится другом ГГ
* * * *B_SetAttitude(self,ATT_FRIENDLY);
* *};
* *// если цель находится безсознания и причиной атаки было убийство цели
* *if(Npc_IsInState(other,ZS_Unconscious)) && (C_NpcHasAttackReasonToKill(self))
* *{
* * * *// НПС добивает цель
* * * *B_FinishingMove(self,other);
* *};
* *// НПС прячет оружие
* *AI_RemoveWeapon(self);
* *// если цель обездвижена и НПС может обыскать цель и (цель не обыскивалась или должна быть обыскана)
* *if(C_NpcIsDown(other)) && (C_WantToRansack(self)) && ((other.aivar[AIV_RANSACKED] == FALSE) ¦¦ C_NpcRansacksAlways(self))
* *// и расстояние между НПС и целью < дистанции восприятия
* *&& (Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT)
* *{
* * * *// установка флага, что цель обыскана
* * * *other.aivar[AIV_RANSACKED] = TRUE;
* * * *// цель человек
* * * *if(other.guild < GIL_SEPERATOR_HUM)
* * * *{
* * * * * *// переход НПС в состояние грабежа цели
* * * * * *AI_StartState(self,ZS_RansackBody,0,"");
* * * * * *return;
* * * *}
* * * *else // (не человек)
* * * *{
* * * * * *// если НПС "Аллигатор Джек" и цель имеет "Сырое мясо"
* * * * * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(AlligatorJack)) && (Npc_HasItems(other,ItFoMuttonRaw) > 0)
* * * * * *{ *
* * * * * * * *// Джек ест мясо
* * * * * * * *AI_StartState(self,ZS_GetMeat,0,"");
* * * * * * * *return;
* * * * * *};
* * * *};
* *};
* *// если жизнь НПС меньше половинной
* *if(self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
* *{
* * * *// НПС лечит себя
* * * *AI_StartState(self,ZS_HealSelf,0,"");
* * * *return;
* *};
};

Ответить с цитированием