|
Re: Уроки скриптологии
// ***************************************** // Обработчик состояния смерти НПС // Примечание: НПС в это состояние переводит также и ядро системы, когда НПС добивают! // ----------------------------------------- // self - мертвый НПС, other - убийца // *****************************************
// Инициализация состояния смерти func void ZS_Dead() { * * *// сброс флага, что тело обыскивалось * *self.aivar[AIV_RANSACKED] = FALSE; * *// сброс флага, что НПС член партии * *self.aivar[AIV_PARTYMEMBER] = FALSE; * *// НПС перестает смотреть на кого-либо * *B_StopLookAt(self); * *// НПС прекращает на что-либо указывать * *AI_StopPointAt(self); * *// если (убийца ГГ или убийца член партии ГГ) и начисления экспы ГГ за убийство НПС не было * *if(Npc_IsPlayer(other) ¦¦ (other.aivar[AIV_PARTYMEMBER] == TRUE)) && (self.aivar[AIV_VictoryXPGiven] == FALSE) * *{ * * * *// начисление ГГ экспы (уровень НПС * 10) * * * *B_GivePlayerXP (self.level * XP_PER_VICTORY); * * * *// установить НПС флаг начисления экспы * * * *self.aivar[AIV_VictoryXPGiven] = TRUE; * *}; * *// если убит "Расчленитель" в каньоне * *if(C_IAmCanyonRazor(self) == TRUE) * *{ * * * *// счетчик убитых расчленителей ++ * * * *CanyonRazorBodyCount = CanyonRazorBodyCount + 1; * * * *// если квест Грега об очистке каньона в стадии выполнения * * * *if(MIS_Addon_Greg_ClearCanyon == LOG_RUNNING) * * * *{ * * * * * *// выдача на экран информации об убитых расчленителях * * * * * *B_CountCanyonRazor(); * * * *}; * *}; * *// если убита "Болотная вонючка" * *if(self.aivar[AIV_MM_REAL_ID] == ID_SWAMPDRONE) * *{ * * * *// если расстояние между НПС и убийцей < 3 метров * * * *if(Npc_GetDistToNpc(self,other) < 300) * * * *{ * * * * * *// жизнь убийцы уменьшается на 50 пунктов * * * * * *other.attribute[ATR_HITPOINTS] -= 50; * * * *}; * *}; * *// если Диего убит в Рудниковой долине * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(DiegoOW)) * *{ * * * *// установить флаг "воскрешения" Диего в Хоринисе * * * *Diego_IsDead = TRUE; * *}; * *// если убийца ГГ * *if(Npc_IsPlayer(other)) * *{ * * * *// установить флаг, что НПС убит ГГ * * * *self.aivar[AIV_KilledByPlayer] = TRUE; * * * *// если этого НПС не разрешалось убивать * * * *if(C_DropUnconscious()) * * * *{ * * * * * *// счетчик невинно убитых ++ * * * * * *MadKillerCount = (MadKillerCount + 1); * * * *}; * * * * * * *// если убит "Полевой жук" и квест Фестера в стадии выполнения * * * *if(self.guild == GIL_GIANT_BUG) && (MIS_Fester_KillBugs == LOG_RUNNING) * * * *{ * * * * * *// увеличить счетчик убитых Полевых жуков * * * * * *Festers_Giant_Bug_Killed = Festers_Giant_Bug_Killed + 1; * * * *}; * * * *// если убита "Болотная крыса" и квест охоты с Аллигатором Джеком в стадии выполнения * * * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Swamprat)) && (MIS_KrokoJagd == LOG_Running) * * * *{ * * * * * *// увеличить счетчик убитых Болотных крыс * * * * * *AlligatorJack_KrokosKilled = AlligatorJack_KrokosKilled + 1; * * * *}; * * * *// если убит "Рамон" * * * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Ramon)) * * * *{ * * * * * *// установка флага, что ГГ может разговаривать с бандитами * * * * * *Player_HasTalkedToBanditCamp = TRUE; * * * *}; * * * *// если убит "Франко" * * * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Franco)) * * * *{ * * * * * *// если квест "Охота на болотожоров с Логаном" в стадии выполнения * * * * * *if(MIS_HlpLogan == LOG_RUNNING) * * * * * *{ * * * * * * * *// квест завершается * * * * * * * *MIS_HlpLogan = LOG_OBSOLETE; * * * * * *}; * * * * * *// если квест "Найти Эдгора с каменной плиткой" в стадии выполнения * * * * * *if(MIS_HlpEdgor == LOG_RUNNING) * * * * * *{ * * * * * * * *// квест завершается * * * * * * * *MIS_HlpEdgor = LOG_OBSOLETE; * * * * * *}; * * * *}; * * * *// если убит "Фортуно" * * * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Fortuno)) * * * *{ * * * * * *// квест по "Поиску зеленого послушника" завершается * * * * * *Log_SetTopicStatus(Topic_Addon_Fortuno,LOG_OBSOLE TE); * * * *}; * *}; * *// если убит "Ползун" в пещере (где должен появиться Блудвин) * *if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Goldminecrawler)) * *{ * * * *// если убито более 8 ползунов и Блудвина нет * * * *if(Minecrawler_Killed >= 9) && (Bloodwyn_Spawn == FALSE) * * * *{ * * * * * * *// Блудвин появляется в точке ADW_MINE_TO_MC_03 * * * * * *AI_Teleport(Bloodwyn,"ADW_MINE_TO_MC_03"); * * * * * *// установить Блудвину распорядок дня * * * * * *B_StartOtherRoutine(Bloodwyn,"MINE"); * * * * * *// начислить ГГ 500 экспы * * * * * *B_GivePlayerXP(XP_Addon_Bloodywyn); * * * * * *// установить флаг появления Блудвина * * * * * *Bloodwyn_Spawn = TRUE; * * * *} * * * *else // иначе * * * *{ * * * * * *// счетчик убитых ползунов ++ * * * * * *Minecrawler_Killed = (Minecrawler_Killed + 1); * * * *}; * *}; * *// удаление продаваемых предметов у торговцев * *B_GiveTradeInv(self); * *// создать в инвентаре монстров добываемые предметы (в зависимости от способностей ГГ) * *B_GiveDeathInv(self); * *// удаление рун у НПС * *B_ClearRuneInv(self); * *// оставить счетчики криминала ГГ по локациям в старом состоянии * *B_DeletePetzCrime(self); * *// сброс флага криминала у НПС * *self.aivar[AIV_NpcSawPlayerCommit] = CRIME_NONE; * *// убрать оружие * *AI_UnequipWeapons(self); * *// сброс флага показа видео * *self.aivar[AIV_TAPOSITION] = FALSE; };
// Цикл смерти (выхода из него нет) func int ZS_Dead_loop() { * *// если показа видео не было * *if(self.aivar[AIV_TAPOSITION] == FALSE) * *{ * * * *// показать видео соответствующее смерти НПС * * * *B_DragonKillCounter(self); * * * *// установить флаг показа видео * * * *self.aivar[AIV_TAPOSITION] = TRUE; * *}; * *return LOOP_CONTINUE; };
Добавление от 26 февраля 2005, 10:57 9. Функции состояний монстров.
Все обработчики основных состояний монстров находятся в директории ..\AI\Monster\ZS_Monster\ Имена файлов соответствуют именам обработчиков.
// ************************************** // Обработчик состояния атаки // -------------------------------------- // self - НПС агрессор, other - НПС цель // **************************************
// Функция обработки вспомогательного восприятия PERC_ASSESSSURPRISE // Вызывается ядром системы когда ГГ превращается в человека из животного func void B_MM_AssessSurprise() { * *// целью агрессора становится ГГ * *Npc_SetTarget(self,other); };
// Мнициализация состояния атаки func void ZS_MM_Attack() { * *// установка времени реакции на восприятия 1 сек * *Npc_SetPercTime(self,1); * *// разрешить восприятие мертвого тела * *Npc_PercEnable(self,PERC_ASSESSBODY,B_MM_AssessBo dy); * *// разрешить восприятие магии * *Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagi c); * *// разрешить восприятие повреждения * *Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_Assess Damage); * *// разрешить восприятие предупреждения * *Npc_PercEnable(self,PERC_ASSESSWARN,B_MM_AssessWa rn); * *// разрешить вспомогательное восприятие превращения * *Npc_PercEnable(self,PERC_ASSESSSURPRISE,B_MM_Asse ssSurprise); * *// инициализировать переменную other (последняя цель) * *B_ValidateOther(); * *// если агрессор овца * *if(self.guild == GIL_SHEEP) * *{ * * * *// очистка очереди AI состояний НПС * * * *Npc_ClearAIQueue(self); * * * *// очистка восприятий * * * *B_ClearPerceptions(self); * * * *// установка цели * * * *Npc_SetTarget(self,other); * * * *// НПС убегает от цели * * * *AI_StartState(self,ZS_MM_Flee,0,""); * * * *return; * *}; * *// НПС встает * *AI_StandUp(self); * *// включается режим передвижения - бег * *AI_SetWalkmode(self,NPC_RUN); * *// агрессору посылается предупреждение от цели * *Npc_SendPassivePerc(self,PERC_ASSESSWARN,other,se lf); * *// сброс флага окончания преследования * *self.aivar[AIV_PursuitEnd] = FALSE; * *// сброс счетчика времени нахождения в состоянии * *self.aivar[AIV_StateTime] = 0; * *// сброс флага первого удара * *self.aivar[AIV_HitByOtherNpc] = 0; * *// сброс выбранного заклинания * *self.aivar[AIV_SelectSpell] = 0; * *// сброс счетчика регенерации * *self.aivar[AIV_TAPOSITION] = 0; };
// Цикл состояния атаки func int ZS_MM_Attack_Loop() { * *// повторно инициализировать other целью * *Npc_GetTarget(self); * *// если НПС дракон * *if(self.guild == GIL_DRAGON) * *{ * * * *// счетчик регенерации ++ * * * *self.aivar[AIV_TAPOSITION] += 1; * * * *// если жизнь НПС < максимальной и счетчик регенерации >= 2 cек * * * *if (self.attribute[ATR_HITPOINTS] < self.attribute[ATR_HITPOINTS_MAX]) && (self.aivar[AIV_TAPOSITION] >= 2) * * * *{ * * * * * *// жизнь ++ * * * * * *self.attribute[ATR_HITPOINTS] += 1; * * * * * *// сброс счетчика * * * * * *self.aivar[AIV_TAPOSITION] = 0; * * * *}; * *}; * *// если Равен убит и агрессор Каменный сторож * *if(RavenIsDead == TRUE) && (self.guild == GIL_STONEGUARDIAN) * *{ * * * * *// агрессор умирает * * * *B_KillNpc(self); * *}; * *// если текущий уровень - Миненталь * *if(CurrentLevel == OLDWORLD_ZEN) * *{ * * * *// если расстояние от агрессора до точки OC_RAMP_07 <= 5 метров * * * *if(Npc_GetDistToWP(self,"OC_RAMP_07") <= 500) * * * *{ * * * * * *// очистка очереди AI состояний НПС * * * * * *Npc_ClearAIQueue(self); * * * * * *// НПС встает * * * * * *AI_StandUp(self); * * * * * *// проигрывается анимация T_WARN * * * * * *AI_PlayAni(self,"T_WARN"); * * * * * *// установка флага окончания преследования * * * * * *self.aivar[AIV_PursuitEnd] = TRUE; * * * * * *return LOOP_END; * * * *}; * *}; * * * * *// если расстояние между НПС и целью > дистанции сражения * *if(Npc_GetDistToNpc(self,other) > FIGHT_DIST_CANCEL) * *{ * * * *// очистка очереди 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); * * * *// проиграть анимацию T_WARN * * * *AI_PlayAni(self,"T_WARN"); * *}; * *// если НПС завершил преследование цели * *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 * * * * * *{ * * * * * * * *// НПС поворачивается к цели * * * * * * * *AI_TurnToNpc(self,other); * * * * * * * *// получить дистанцию до цели * * * * * * * *self.aivar[AIV_Dist] = Npc_GetDistToNpc(self,other); * * * * * * * *// обновить время состояния НПС * * * * * * * *self.aivar[AIV_StateTime] = Npc_GetStateTime(self); * * * * * *}; * * * *}; * * * *return LOOP_CONTINUE; * *}; * *// если (цель плывет или ныряет) и НПС не преследует цель в воде * *if(C_BodyStateContains(other,BS_SWIM) ¦¦ C_BodyStateContains(other,BS_DIVE)) && (self.aivar[AIV_MM_FollowInWater] == FALSE) * *{ * * * *// очистка очереди AI состояний НПС * * * *Npc_ClearAIQueue(self); * * * *// НПС встает * * * *AI_StandUp(self); * * * *return LOOP_END; * *}; * *// если НПС выжидает перед атакой * *if(self.aivar[AIV_WaitBeforeAttack] == 1) * *{ * * * *// ожидание 0.8 сек * * * *AI_Wait(self,0.8 ); * * * *// сброс флага задержки * * * *self.aivar[AIV_WaitBeforeAttack] = 0; * *}; * *// если уровень НПС == 0 (вызванный монстр) * *if(self.level == 0) * *{ * * * *// если текущее время > предыдущего времени (прошла как минимум секунда) * * * *if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime]) * * * *{ * * * * * *// время от начала вызова монстра ++ * * * * * *self.aivar[AIV_SummonTime] = (self.aivar[AIV_SummonTime] + 1); * * * * * *// запомнить текущее время * * * * * *self.aivar[AIV_StateTime] = Npc_GetStateTime(self); * * * *}; * * * *// если время от начала вызова монстра >= времени жизни вызванных монстров * * * *if(self.aivar[AIV_SummonTime] >= MONSTER_SUMMON_TIME) * * * *{ * * * * * *// вызванный монстр умирает * * * * * *Npc_ChangeAttribute(self,ATR_HITPOINTS,-self.attribute[ATR_HITPOINTS_MAX]); * * * *}; * *}; * *// если цель не бежит и не прыгает и время в состоянии > 0 * *if((!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP))) && (Npc_GetStateTime(self) > 0) * *{ * * * *// сброс времени текущего состояния * * * *Npc_SetStateTime(self,0); * * * *// сброс счетчика времени нахождения в состоянии * * * *self.aivar[AIV_StateTime] = 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_NpcIsMonsterMage(self)) * *¦¦ (self.guild == GIL_SKELETON) * * * * * * // скелет * *¦¦ (self.guild == GIL_SUMMONED_SKELETON) * *// или вызванный скелет * *¦¦ (self.guild > GIL_SEPERATOR_ORC) * * * * // или орк * *{ * * * *// создать боеприпасы * * * *B_CreateAmmo(self); * * * *// установить полную ману * * * *Npc_ChangeAttribute(self,ATR_MANA,ATR_MANA_MAX); * * * *// выбрать оружие, сответствующее цели * * * *B_SelectWeapon(self,other); * *}; * *// если цель существует и не обездвижена * *if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other)) * *{ * * * *// если цель не в состоянии разговора * * * *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 // иначе (если цель отсутствует или обездвижена) * *{ * * * *// если приоритет агрессора на пожирание падали и агрессор может есть цель * * * *if(self.aivar[AIV_MM_PRIORITY] == PRIO_EAT) && (C_WantToEat(self,other)) * * * *{ * * * * * *// очистка очереди AI состояний НПС * * * * * *Npc_ClearAIQueue(self); * * * * * *// НПС встает * * * * * *AI_StandUp(self); * * * * * *return LOOP_END; * * * *}; * * * *// разрешение воспринимать все объекты в зоне действия восприятий * * * *Npc_PerceiveAll(self); * * * *// поиск новой цели * * * *Npc_GetNextTarget(self); * * * *// если цель найдена и она не обездвижена * * * *if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other)) * * * *// и (расстояние между НПС и целью < дистанции действия восприятий или цель ГГ) * * * *&& ((Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT) ¦¦ (Npc_IsPlayer(other))) * * * *// и цель не в состоянии разговора * * * *&& (other.aivar[AIV_INVINCIBLE] == FALSE) * * * *{ * * * * * *// запись НПС id последней цели * * * * * *self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other); * * * * * *return LOOP_CONTINUE; * * * *} * * * *else // иначе * * * *{ * * * * * *// очистка очереди AI состояний НПС * * * * * *Npc_ClearAIQueue(self); * * * * * *// НПС встает * * * * * *AI_StandUp(self); * * * * * *return LOOP_END; * * * *}; * *}; };
// Завершение состояния атаки func void ZS_MM_Attack_End() { * *// установить other на последнюю цель * *other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]); * *// если агрессор маг или * *if(C_NpcIsMonsterMage(self)) * *¦¦ (self.guild == GIL_SKELETON) * * * * * * // скелет * *¦¦ (self.guild == GIL_SUMMONED_SKELETON) * *// или вызванный скелет * *¦¦ (self.guild > GIL_SEPERATOR_ORC) * * * * // или орк * *{ * * * *// НПС убирает оружие * * * *AI_RemoveWeapon(self); * *}; * *// если цель убита и агрессор может пожирать цель * *if(Npc_IsDead(other)) && (C_WantToEat(self,other)) * * * * * * * * * * *{ * * * *// очистка очереди AI состояний НПС * * * *Npc_ClearAIQueue(self); * * * *// переход в состояние пожирания добычи * * * *AI_StartState(self,ZS_MM_EatBody,0,""); * * * *return; * *}; };
|