• Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
  • Друзья, доброго времени суток! Спешите принять участие в конкурсе "Таинственные миры" 2024!
    Ждем именно вас!

    Ссылка на конкурсную тему - тык

Важно Уроки скриптологии by VAM

Статус
В этой теме нельзя размещать новые ответы.

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
  • Первое сообщение
  • #1
Тема первая: Типы переменных.

В скриптах используется всего несколько типов переменных:
void - пустой тип
int - целое число
float - число с плавающей точкой
string - строка текста
class - структура с внутренними типами и функциями
prototype - обычно инициализация класса, но возможно и другое использование
instance - пока сказать нечего.
вот, кажется, и все типы.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
// **************************************************************
// НПС slf называет НПС oth сумму денежного выражения goldAmount
// **************************************************************


func void B_Say_Gold(var c_npc slf,var c_npc oth,var int goldAmount)
{
if(goldAmount == 1000) { B_Say(slf,oth,"$GOLD_1000"); };
if(goldAmount == 950) { B_Say(slf,oth,"$GOLD_950"); };
if(goldAmount == 900) { B_Say(slf,oth,"$GOLD_900"); };
if(goldAmount == 850) { B_Say(slf,oth,"$GOLD_850"); };
if(goldAmount == 800) { B_Say(slf,oth,"$GOLD_800"); };
if(goldAmount == 750) { B_Say(slf,oth,"$GOLD_750"); };
if(goldAmount == 700) { B_Say(slf,oth,"$GOLD_700"); };
if(goldAmount == 650) { B_Say(slf,oth,"$GOLD_650"); };
if(goldAmount == 600) { B_Say(slf,oth,"$GOLD_600"); };
if(goldAmount == 550) { B_Say(slf,oth,"$GOLD_550"); };
if(goldAmount == 500) { B_Say(slf,oth,"$GOLD_500"); };
if(goldAmount == 450) { B_Say(slf,oth,"$GOLD_450"); };
if(goldAmount == 400) { B_Say(slf,oth,"$GOLD_400"); };
if(goldAmount == 350) { B_Say(slf,oth,"$GOLD_350"); };
if(goldAmount == 300) { B_Say(slf,oth,"$GOLD_300"); };
if(goldAmount == 250) { B_Say(slf,oth,"$GOLD_250"); };
if(goldAmount == 200) { B_Say(slf,oth,"$GOLD_200"); };
if(goldAmount == 150) { B_Say(slf,oth,"$GOLD_150"); };
if(goldAmount == 100) { B_Say(slf,oth,"$GOLD_100"); };
if(goldAmount == 90) { B_Say(slf,oth,"$GOLD_90"); };
if(goldAmount == 80) { B_Say(slf,oth,"$GOLD_80"); };
if(goldAmount == 70) { B_Say(slf,oth,"$GOLD_70"); };
if(goldAmount == 60) { B_Say(slf,oth,"$GOLD_60"); };
if(goldAmount == 50) { B_Say(slf,oth,"$GOLD_50"); };
if(goldAmount == 40) { B_Say(slf,oth,"$GOLD_40"); };
if(goldAmount == 30) { B_Say(slf,oth,"$GOLD_30"); };
if(goldAmount == 20) { B_Say(slf,oth,"$GOLD_20"); };
if(goldAmount == 10) { B_Say(slf,oth,"$GOLD_10"); };
};
// *******************************
// НПС slf преветствует НПС oth
// *******************************


func void B_Say_GuildGreetings(var c_npc slf,var c_npc oth)
{
// если милиция приветствует милицию или паладина
if(slf.guild == GIL_MIL) && ((oth.guild == GIL_MIL) || (oth.guild == GIL_PAL))
{
// звучит SVM фраза "За короля!"
B_Say_Overlay(slf,oth,"$MILGREETINGS");
return;
};
// если паладин приветствует паладина или милицию или магов огня
if(slf.guild == GIL_PAL) && ((oth.guild == GIL_PAL) || (oth.guild == GIL_MIL) || (oth.guild == GIL_KDF))
{
// звучит SVM фраза "За Инноса!"
B_Say_Overlay (slf,oth,"$PALGREETINGS");
return;
};
// если маг огня приветствует паладина или мага послушника или мага огня
if(slf.guild == GIL_KDF) && ((oth.guild == GIL_PAL) || (oth.guild == GIL_NOV) || (oth.guild == GIL_KDF))
{
// звучит SVM фраза "За Инноса!"
B_Say_Overlay (slf,oth,"$PALGREETINGS");
return;
};
// если приветствующий Барток и он сообщал об одиноком орке перед Хоринисом
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Bartok)) && (Bartok_OrkGesagt == TRUE)
{
// Барток говорит об одиноком орке перед Хоринисом
B_Bartok_ShitAnOrc();
return;
};
// если приветствующий Кок
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Koch))
{
// Кок говорит о топоре
B_Koch_Hackebeil();
return;
};
var int zufall;
zufall = Hlp_Random(100);
// с вероятностью 0.1 и если идет дождь
if((zufall <= 10) && Wld_IsRaining())
{
// звучит SVM фраза "Ну и скверная же погода!"
B_Say_Overlay(slf,oth,"$WEATHER");
return;

};
};
// ************************************************
// Мини реплики НПС
// ************************************************


func void B_Say_Smalltalk()
{
var int random;
random = Hlp_Random (120);
var int Choice;
Choice = Hlp_Random(1);
// с вероятностью 0.04
if(random < 5)
{
// НПС произносит SVM фразу "... ты, правда, так думаешь..."
B_Say(self,self,"$SMALLTALK01");
}
// с вероятностью 0.04
else if(random < 10)
{
// НПС произносит SVM фразу "... все возможно..."
B_Say(self,self,"$SMALLTALK02");
}
// с вероятностью 0.04
else if(random < 15)
{
// НПС произносит SVM фразу "... он должен больше знать об этом..."
B_Say(self,self,"$SMALLTALK03");
}
// с вероятностью 0.04
else if(random < 20)
{
// НПС произносит SVM фразу "... как будто у меня и так мало проблем..."
B_Say(self,self,"$SMALLTALK04");
}
// с вероятностью 0.04
else if(random < 25)
{
// НПС произносит SVM фразу "... кто мог рассказать такое..."
B_Say(self,self,"$SMALLTALK05");
}
// с вероятностью 0.04
else if(random < 30)
{
// НПС произносит SVM фразу "... все же я еще очень зол..."
B_Say(self,self,"$SMALLTALK06");
}
// с вероятностью 0.04
else if(random < 35)
{
// НПС произносит SVM фразу "... кое-что болтают..."
B_Say(self,self,"$SMALLTALK07");
}
// с вероятностью 0.04
else if(random < 40)
{
// НПС произносит SVM фразу "... я бы не делал этого..."
B_Say(self,self,"$SMALLTALK08");
}
// с вероятностью 0.04
else if(random < 45)
{
// НПС произносит SVM фразу "... это всего лишь запах..."
B_Say(self,self,"$SMALLTALK09");
}
// с вероятностью 0.04
else if(random < 50)
{
// НПС произносит SVM фразу "... нужно узнать, что они там замышляют..."
B_Say(self,self,"$SMALLTALK10");
}
// с вероятностью 0.04
else if(random < 55)
{
// НПС произносит SVM фразу "... а я тебе что говорил..."
B_Say(self,self,"$SMALLTALK11");
}
// с вероятностью 0.04
else if(random < 60)
{
// НПС произносит SVM фразу "... меня никто не спрашивал..."
B_Say(self,self,"$SMALLTALK12");
}
// с вероятностью 0.04
else if(random < 65)
{
// НПС произносит SVM фразу "... бедный малый может и обидеть кого-нибудь..."
B_Say(self,self,"$SMALLTALK13");
}
// с вероятностью 0.04
else if(random < 70)
{
// НПС произносит SVM фразу "... ничего нового..."
B_Say(self,self,"$SMALLTALK14");
}
// с вероятностью 0.04
else if(random < 75)
{
// НПС произносит SVM фразу "... все ясно..."
B_Say(self,self,"$SMALLTALK15");
}
// с вероятностью 0.04
else if(random < 80)
{
// НПС произносит SVM фразу "... меня не нужно спрашивать..."
B_Say(self,self,"$SMALLTALK16");
}
// с вероятностью 0.04
else if(random < 85)
{
// НПС произносит SVM фразу "... так не может дальше продолжаться..."
B_Say(self,self,"$SMALLTALK17");
}
// с вероятностью 0.04
else if(random < 90)
{
// НПС произносит SVM фразу "... мое мнение ты уже знаешь..."
B_Say(self,self,"$SMALLTALK18");
}
// с вероятностью 0.04
else if(random < 95)
{
// НПС произносит SVM фразу "... я сказал то же самое..."
B_Say(self,self,"$SMALLTALK19");
}
// с вероятностью 0.04
else if(random < 100)
{
// НПС произносит SVM фразу "... вряд ли что-нибудь изменится из-за этого..."
B_Say(self,self,"$SMALLTALK20");
}
// с вероятностью 0.04
else if(random < 105)
{
// НПС произносит SVM фразу "... почему я узнаю об этом только сейчас..."
B_Say(self,self,"$SMALLTALK21");
}
// с вероятностью 0.04
else if(random < 110)
{
// если НПС маг послушник или паладин или маг огня
if(Npc_GetTrueGuild(self) == GIL_NOV) || (Npc_GetTrueGuild(self) == GIL_PAL) || (Npc_GetTrueGuild(self) == GIL_KDF)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... так написано в священных книгах..."
B_Say(self,self,"$SMALLTALK28");
}
else
{
// НПС произносит SVM фразу "... давайте посмотрим, что из этого выйдет..."
B_Say(self,self,"$SMALLTALK22");
};
}
// если НПС бандит или наемник или охотник на драконов или пират
else if(Npc_GetTrueGuild(self) == GIL_BDT) || (Npc_GetTrueGuild(self) == GIL_SLD) || (Npc_GetTrueGuild(self) == GIL_DJG)
|| (Npc_GetTrueGuild(self) == GIL_PIR)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... он был пьянючий..."
B_Say(self,self,"$SMALLTALK25");
}
else
{
// НПС произносит SVM фразу "... давайте посмотрим, что из этого выйдет..."
B_Say(self,self,"$SMALLTALK22");
};
}
else // остальные гильдии
{
// НПС произносит SVM фразу "... давайте посмотрим, что из этого выйдет..."
B_Say(self,self,"$SMALLTALK22");
};
}
// с вероятностью 0.04
else if(random < 115)
{
// если НПС маг послушник или паладин или маг огня
if(Npc_GetTrueGuild(self) == GIL_NOV) || (Npc_GetTrueGuild(self) == GIL_PAL) || (Npc_GetTrueGuild(self) == GIL_KDF)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... я действую по приказу Инноса..."
B_Say(self,self,"$SMALLTALK29");
}
else
{
// НПС произносит SVM фразу "... некоторые проблемы решаются сами собой..."
B_Say(self,self,"$SMALLTALK23");
};
}
// если НПС бандит или наемник или охотник на драконов или пират
else if(Npc_GetTrueGuild(self) == GIL_BDT) || (Npc_GetTrueGuild(self) == GIL_SLD) || (Npc_GetTrueGuild(self) == GIL_DJG)
|| (Npc_GetTrueGuild(self) == GIL_PIR)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... со мной бы этот номер не прошел..."
B_Say(self,self,"$SMALLTALK26");
}
else
{
// НПС произносит SVM фразу "... некоторые проблемы решаются сами собой..."
B_Say(self,self,"$SMALLTALK23");
};
}
else // остальные гильдии
{
// НПС произносит SVM фразу "... некоторые проблемы решаются сами собой..."
B_Say(self,self,"$SMALLTALK23");
};
}
// с вероятностью 0.04
else if(random <= 120)
{
// если НПС маг послушник или паладин или маг огня
if(Npc_GetTrueGuild(self) == GIL_NOV) || (Npc_GetTrueGuild(self) == GIL_PAL) || (Npc_GetTrueGuild(self) == GIL_KDF)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... никому не позволено нарушать указания богов..."
B_Say(self,self,"$SMALLTALK30");
}
else
{
// НПС произносит SVM фразу "... я не могу больше это слушать..."
B_Say(self,self,"$SMALLTALK24");
};
}
// если НПС бандит или наемник или охотник на драконов или пират
else if(Npc_GetTrueGuild(self) == GIL_BDT) || (Npc_GetTrueGuild(self) == GIL_SLD) || (Npc_GetTrueGuild(self) == GIL_DJG)
|| (Npc_GetTrueGuild (self) == GIL_PIR)
{
// с вероятностью 0.5
if(Choice == 0)
{
// НПС произносит SVM фразу "... все убежали словно зайцы, я остался один..."
B_Say(self,self,"$SMALLTALK27");
}
else
{
// НПС произносит SVM фразу "... я не могу больше это слушать..."
B_Say(self,self,"$SMALLTALK24");
};
}
else // остальные гильдии
{
// НПС произносит SVM фразу "... я не могу больше это слушать..."
B_Say(self,self,"$SMALLTALK24");
};
};
};
// ****************************************************************
// НПС slf произносит для НПС oth быструю SVM фразу text
// ----------------------------------------------------------------
// От B_Say() отличается только тем, что следующие AI команды будут
// выполняться не ожидая окончания фразы
// ****************************************************************


func void B_Say_Overlay(var c_npc slf,var c_npc oth,var string text)
{
AI_OutputSVM_Overlay(slf,oth,text);
};


// *******************************************
// Выбор НПС оружия соответствующего цели
// *******************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС агрессор
// oth - НПС цель
// ======================================


func void B_SelectWeapon(var c_npc slf,var c_npc oth)
{
// если агрессор падает или плывет или ныряет
if(C_BodyStateContains(slf,BS_FALL)) || (C_BodyStateContains(slf,BS_SWIM)) || (C_BodyStateContains(slf,BS_DIVE))
{
return;
};
// если агрессор выбрал для использования магию
if(B_SelectSpell(slf,oth))
{
return;
};
// если агрессор находится в режиме сражения магией
if(Npc_IsInFightMode(slf,FMODE_MAGIC))
{
// если агрессор находится в боевом режиме (Примечание: не мой взгляд этот блок лишний, была проверка, что НПС использует магию)
if(!Npc_IsInFightMode(slf,FMODE_NONE))
{
// агрессор прячет оружие
AI_RemoveWeapon(slf);
};
// подготовка оружия ближнего радиуса поражения к бою
AI_ReadyMeleeWeapon (slf);
return;
};
// если агрессор находится в режиме сражения оружием дальнего радиуса поражения
if(Npc_IsInFightMode(slf,FMODE_FAR))
{
// если расстояние от агрессора до цели > дистанции, ближе которой НПС выбирает оружие ближнего радиуса поражения или агрессор не экипирован оружием ближнего радиуса поражения
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_RANGED_INNER) || (!Npc_HasEquippedMeleeWeapon(slf))
{
return;
};
};
// если агрессор находится в режиме сражения оружием ближнего радиуса поражения
if(Npc_IsInFightMode(slf,FMODE_MELEE))
{
// если расстояние от агрессора до цели > дистанции, дальше которой НПС выбирает оружие дальнего радиуса поражения или агрессор не экипирован оружием дальнего радиуса поражения
if(Npc_GetDistToNpc(slf,oth) <= FIGHT_DIST_RANGED_OUTER) || (!Npc_HasEquippedRangedWeapon(slf))
{
return;
};
};
// если агрессор экипирован оружием ближнего радиуса поражения и расстояние от агрессора до цели <= дистанции, дальше которой НПС выбирает оружие дальнего радиуса поражения
if(Npc_HasEquippedMeleeWeapon(slf)) && (Npc_GetDistToNpc(slf,oth) <= FIGHT_DIST_RANGED_OUTER)
{
// если агрессор находится в боевом режиме
if(!Npc_IsInFightMode(slf,FMODE_NONE))
{
// агрессор прячет оружие
AI_RemoveWeapon(slf);
};
// подготовка оружия ближнего радиуса поражения к бою
AI_ReadyMeleeWeapon (slf);
return;
};
// если агрессор экипирован оружием дальнего радиуса поражения и расстояние от агрессора до цели > дистанции, ближе которой НПС выбирает оружие ближнего радиуса поражения и причина атаки агрессора - убийство жертвы
if(Npc_HasEquippedRangedWeapon(oth) > FIGHT_DIST_RANGED_INNER) && (C_NpcHasAttackReasonToKill(slf))
{
// если агрессор находится в боевом режиме
if(!Npc_IsInFightMode(slf,FMODE_NONE))
{
// агрессор прячет оружие
AI_RemoveWeapon(slf);
};
// подготовка оружия дальнего радиуса поражения к бою
AI_ReadyRangedWeapon(slf);
return;
};
// если агрессор не в боевом режиме
if(Npc_IsInFightMode(slf,FMODE_NONE))
{
// если агрессор экипирован оружием ближнего радиуса поражения
if(Npc_HasEquippedMeleeWeapon(slf))
{
// подготовка оружия к бою
AI_ReadyMeleeWeapon(slf);
return;
};
// если агрессор экипирован оружием дальнего радиуса поражения
if(Npc_HasEquippedRangedWeapon(slf))
{
// подготовка оружия к бою
AI_ReadyRangedWeapon(slf);
return;
};
// подготовка к бою кулаками
AI_ReadyMeleeWeapon(slf);
return;
};
return;
};




// *********************************
// Устанавливает отношение НПС к ГГ
// *********************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС
// att - отношение
// ======================================


func void B_SetAttitude(var c_npc slf,var int att)
{
// установить временное отношение НПС к ГГ
Npc_SetAttitude(slf,att);
// установить постояное отношение НПС к ГГ
Npc_SetTempAttitude(slf,att);
};




// ********************************************
// Инициализация переменной other для НПС self
// ********************************************


func void B_ValidateOther()
{
// если other отсутсвует (загрузка игры)
if(!Hlp_IsValidNpc(other))
{
// other = последней цели НПС
other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
// для НПС установить цель other
Npc_SetTarget(self,other);
// установить флаг загрузки игры
self.aivar[AIV_LOADGAME] = TRUE;
}
else // иначе (other существует)
{
// повторно инициализировать other целью
Npc_GetTarget(self);
// сохранить последнюю цель
self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
// сброс флага загрузки игры
self.aivar[AIV_LOADGAME] = FALSE;
};
};



Добавление от 26 марта 2005, 09:56
Криминал ГГ

// *******************************
// Запоминание новостей
// *******************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС, запоминающий новость
// taeter - НПС преступник
// crime - криминальная новость
// ======================================


func void B_MemorizePlayerCrime(var c_npc slf,var c_npc taeter,var int crime)
{
// если преступник не ГГ
if(!Npc_IsPlayer(taeter))
{
return;
};
// если НПС черный маг
if(slf.guild == GIL_DMT)
{
return;
};
// если новость более значима чем предыдущие новости
if(crime > B_GetPlayerCrime(slf))
{
// удалить предыдущую новость
B_DeletePetzCrime(slf);
// добавить новость
B_AddPetzCrime(slf,crime);
};
// если новость одного порядка с предыдущей новостью (Примечание: можно оставить ==, > было ранее)
if(crime >= B_GetPlayerCrime(slf))
{
// НПС запоминает новость
slf.aivar[AIV_NpcSawPlayerCommit] = crime;
// НПС запоминает день преступления
slf.aivar[AIV_NpcSawPlayerCommitDay] = Wld_GetDay();
// НПС запоминает уровень криминала ГГ
slf.aivar[AIV_CrimeAbsolutionLevel] = B_GetCurrentAbsolutionLevel(slf);
};
};




// ************************************************************
// Получить последнюю новость, запомненную НПС о криминале ГГ
// ************************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС имеющий новость
// --------------------------------------
// Возвращаемое значение: последняя запомненная новость
// ======================================


func int B_GetPlayerCrime(var c_npc slf)
{
// если уровень криминала ГГ меньше воровства
if(slf.aivar[AIV_NpcSawPlayerCommit] <= CRIME_ATTACK)
{
// если с момента запоминания новости прошло более двух дней
if(slf.aivar[AIV_NpcSawPlayerCommitDay] < (Wld_GetDay()-2))
{
// криминала не было
return CRIME_NONE;
};
};
// если уровень криминала, запомненный НПС, < уровня криминала ГГ по локациям
if(slf.aivar[AIV_CrimeAbsolutionLevel] < B_GetCurrentAbsolutionLevel(slf))
{
// криминала не было
return CRIME_NONE;
};
// последний запомненный криминал
return slf.aivar[AIV_NpcSawPlayerCommit];
};




// **************************************************
// Добавить новость для соответствующей локации
// **************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС свидетель, проживающий в локации
// crime - криминальная новость
// ======================================


func void B_AddPetzCrime(var c_npc slf,var int crime)
{
// если НПС из Миненталя
if(C_NpcBelongsToOldCamp(slf))
{
// если убийство
if(crime == CRIME_MURDER)
{
// увеличить счетчик убийств
PETZCOUNTER_OldCamp_Murder = PETZCOUNTER_OldCamp_Murder + 1;
};
// если воровство
if(crime == CRIME_THEFT)
{
// увеличить счетчик воровства
PETZCOUNTER_OldCamp_Theft = PETZCOUNTER_OldCamp_Theft + 1;
};
// если нападение
if(crime == CRIME_ATTACK)
{
// увеличить счетчик нападений
PETZCOUNTER_OldCamp_Attack = PETZCOUNTER_OldCamp_Attack + 1;
};
// если убийство овец
if(crime == CRIME_SHEEPKILLER)
{
// увеличить счетчик убитых овец
PETZCOUNTER_OldCamp_Sheepkiller = PETZCOUNTER_OldCamp_Sheepkiller + 1;
};
};
// если НПС из Хориниса
if(C_NpcBelongsToCity(slf))
{
if(crime == CRIME_MURDER)
{
PETZCOUNTER_City_Murder = PETZCOUNTER_City_Murder + 1;
};
if(crime == CRIME_THEFT)
{
PETZCOUNTER_City_Theft = PETZCOUNTER_City_Theft + 1;
};
if(crime == CRIME_ATTACK)
{
PETZCOUNTER_City_Attack = PETZCOUNTER_City_Attack + 1;
};
if(crime == CRIME_SHEEPKILLER)
{
PETZCOUNTER_City_Sheepkiller = PETZCOUNTER_City_Sheepkiller + 1;
};
};
// если НПС из Монастыря
if(C_NpcBelongsToMonastery(slf))
{
if(crime == CRIME_MURDER)
{
PETZCOUNTER_Monastery_Murder = PETZCOUNTER_Monastery_Murder + 1;
};
if(crime == CRIME_THEFT)
{
PETZCOUNTER_Monastery_Theft = PETZCOUNTER_Monastery_Theft + 1;
};
if(crime == CRIME_ATTACK)
{
PETZCOUNTER_Monastery_Attack = PETZCOUNTER_Monastery_Attack + 1;
};
if(crime == CRIME_SHEEPKILLER)
{
PETZCOUNTER_Monastery_Sheepkiller = PETZCOUNTER_Monastery_Sheepkiller + 1;
};
};
// если НПС с Фермы наемников
if(C_NpcBelongsToFarm(slf))
{
if(crime == CRIME_MURDER)
{
PETZCOUNTER_Farm_Murder = PETZCOUNTER_Farm_Murder + 1;
};
if(crime == CRIME_THEFT)
{
PETZCOUNTER_Farm_Theft = PETZCOUNTER_Farm_Theft + 1;
};
if(crime == CRIME_ATTACK)
{
PETZCOUNTER_Farm_Attack = PETZCOUNTER_Farm_Attack + 1;
};
if(crime == CRIME_SHEEPKILLER)
{
PETZCOUNTER_Farm_Sheepkiller = PETZCOUNTER_Farm_Sheepkiller + 1;
};
};
// если НПС из Лагеря бандитов
if(C_NpcBelongsToBL(slf))
{
if(crime == CRIME_MURDER)
{
PETZCOUNTER_BL_Murder = PETZCOUNTER_BL_Murder + 1;
};
if(crime == CRIME_THEFT)
{
PETZCOUNTER_BL_Theft = PETZCOUNTER_BL_Theft + 1;
};
if(crime == CRIME_ATTACK)
{
PETZCOUNTER_BL_Attack = PETZCOUNTER_BL_Attack + 1;
};
};
};




// *************************************************************
// Удалить новость для соответствующей локации
// *************************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС свидетель, проживающий в локации
// ======================================


func void B_DeletePetzCrime(var c_npc slf)
{
// если НПС из Миненталя
if(C_NpcBelongsToOldCamp(slf))
{
// если последняя запомненная новость - убийство
if(B_GetPlayerCrime(slf) == CRIME_MURDER)
{
// уменьшить счетчик убийств
PETZCOUNTER_OldCamp_Murder = PETZCOUNTER_OldCamp_Murder - 1;
};
// если последняя запомненная новость - воровство
if(B_GetPlayerCrime(slf) == CRIME_THEFT)
{
// уменьшить счетчик воровства
PETZCOUNTER_OldCamp_Theft = PETZCOUNTER_OldCamp_Theft - 1;
};
// если последняя запомненная новость - нападение
if(B_GetPlayerCrime(slf) == CRIME_ATTACK)
{
// уменьшить счетчик нападений
PETZCOUNTER_OldCamp_Attack = PETZCOUNTER_OldCamp_Attack - 1;
};
// если последняя запомненная новость - убийство овец
if(B_GetPlayerCrime(slf) == CRIME_SHEEPKILLER)
{
// уменьшить счетчик убитых овец
PETZCOUNTER_OldCamp_Sheepkiller = PETZCOUNTER_OldCamp_Sheepkiller - 1;
};
};
// если НПС из Хориниса
if(C_NpcBelongsToCity(slf))
{
if(B_GetPlayerCrime(slf) == CRIME_MURDER)
{
PETZCOUNTER_City_Murder = PETZCOUNTER_City_Murder - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_THEFT)
{
PETZCOUNTER_City_Theft = PETZCOUNTER_City_Theft - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_ATTACK)
{
PETZCOUNTER_City_Attack = PETZCOUNTER_City_Attack - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_SHEEPKILLER)
{
PETZCOUNTER_City_Sheepkiller = PETZCOUNTER_City_Sheepkiller - 1;
};
};
// если НПС из Монастыря
if(C_NpcBelongsToMonastery(slf))
{
if(B_GetPlayerCrime(slf) == CRIME_MURDER)
{
PETZCOUNTER_Monastery_Murder = PETZCOUNTER_Monastery_Murder - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_THEFT)
{
PETZCOUNTER_Monastery_Theft = PETZCOUNTER_Monastery_Theft - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_ATTACK)
{
PETZCOUNTER_Monastery_Attack = PETZCOUNTER_Monastery_Attack - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_SHEEPKILLER)
{
PETZCOUNTER_Monastery_Sheepkiller = PETZCOUNTER_Monastery_Sheepkiller - 1;
};
};
// если НПС с Фермы наемников
if(C_NpcBelongsToFarm(slf))
{
if(B_GetPlayerCrime(slf) == CRIME_MURDER)
{
PETZCOUNTER_Farm_Murder = PETZCOUNTER_Farm_Murder - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_THEFT)
{
PETZCOUNTER_Farm_Theft = PETZCOUNTER_Farm_Theft - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_ATTACK)
{
PETZCOUNTER_Farm_Attack = PETZCOUNTER_Farm_Attack - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_SHEEPKILLER)
{
PETZCOUNTER_Farm_Sheepkiller = PETZCOUNTER_Farm_Sheepkiller - 1;
};
};
// если НПС из Лагеря бандитов
if(C_NpcBelongsToBL(slf))
{
if(B_GetPlayerCrime(slf) == CRIME_MURDER)
{
PETZCOUNTER_BL_Murder = PETZCOUNTER_BL_Murder - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_THEFT)
{
PETZCOUNTER_BL_Theft = PETZCOUNTER_BL_Theft - 1;
};
if(B_GetPlayerCrime(slf) == CRIME_ATTACK)
{
PETZCOUNTER_BL_Attack = PETZCOUNTER_BL_Attack - 1;
};
};
};


// *************************************************
// Подсчет абсолютного уровня криминала по локациям
// *************************************************


func void B_GrantAbsolution(var int location)
{
// если Миненталь или все локации
if(location == LOC_OLDCAMP) || (location == LOC_ALL)
{
// абсолютный уровень по локации++
ABSOLUTIONLEVEL_OldCamp = ABSOLUTIONLEVEL_OldCamp + 1;
// сброс счетчиков криминала по локации
PETZCOUNTER_OldCamp_Murder = 0;
PETZCOUNTER_OldCamp_Theft = 0;
PETZCOUNTER_OldCamp_Attack = 0;
PETZCOUNTER_OldCamp_Sheepkiller = 0;
};
// если Хоринис или все локации
if(location == LOC_CITY) || (location == LOC_ALL)
{
ABSOLUTIONLEVEL_City = ABSOLUTIONLEVEL_City + 1;
PETZCOUNTER_City_Murder = 0;
PETZCOUNTER_City_Theft = 0;
PETZCOUNTER_City_Attack = 0;
PETZCOUNTER_City_Sheepkiller = 0;
};
// если Монастырь или все локации
if(location == LOC_MONASTERY) || (location == LOC_ALL)
{
ABSOLUTIONLEVEL_Monastery = ABSOLUTIONLEVEL_Monastery + 1;
PETZCOUNTER_Monastery_Murder = 0;
PETZCOUNTER_Monastery_Theft = 0;
PETZCOUNTER_Monastery_Attack = 0;
PETZCOUNTER_Monastery_Sheepkiller = 0;
};
// если Ферма наемников или все локации
if(location == LOC_FARM) || (location == LOC_ALL)
{
ABSOLUTIONLEVEL_Farm = ABSOLUTIONLEVEL_Farm + 1;
PETZCOUNTER_Farm_Murder = 0;
PETZCOUNTER_Farm_Theft = 0;
PETZCOUNTER_Farm_Attack = 0;
PETZCOUNTER_Farm_Sheepkiller = 0;
};
// если Лагерь бандитов
if(location == LOC_BL)
{
ABSOLUTIONLEVEL_BL = ABSOLUTIONLEVEL_BL + 1;
PETZCOUNTER_BL_Murder = 0;
PETZCOUNTER_BL_Theft = 0;
PETZCOUNTER_BL_Attack = 0;
};
};




// ***********************************************************************
// Получить абсолютный уровень криминала для локации
// ***********************************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС, проживающий в локации
// --------------------------------------
// Возвращаемое значение - абсолютный уровень криминала
// ======================================


func int B_GetCurrentAbsolutionLevel(var c_npc slf)
{
// если НПС из Миненталя
if(C_NpcBelongsToOldCamp(slf))
{
return ABSOLUTIONLEVEL_OldCamp;
};
// если НПС из Хориниса
if(C_NpcBelongsToCity(slf))
{
return ABSOLUTIONLEVEL_City;
};
// если НПС из Монастыря
if(C_NpcBelongsToMonastery(slf))
{
return ABSOLUTIONLEVEL_Monastery;
};
// если НПС с Фермы наемников
if(C_NpcBelongsToFarm(slf))
{
return ABSOLUTIONLEVEL_Farm;
};
// если НПС из Лагеря бандитов
if(C_NpcBelongsToBL(slf))
{
return ABSOLUTIONLEVEL_BL;
};
return 0;
};




// *************************************************
// Получить суммарный уровень криминала по локациям
// *************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС, проживающий в локации
// --------------------------------------
// Возвращаемое значение - суммарный уровень криминала ГГ для локации
// ======================================


func int B_GetTotalPetzCounter(var c_npc slf)
{
// если НПС из Миненталя
if (C_NpcBelongsToOldCamp(slf))
{
// суммарный уровень криминала для локации
return (PETZCOUNTER_OldCamp_Murder + PETZCOUNTER_OldCamp_Theft + PETZCOUNTER_OldCamp_Attack + PETZCOUNTER_OldCamp_Sheepkiller);
};
// если НПС из Хориниса
if (C_NpcBelongsToCity(slf))
{
return (PETZCOUNTER_City_Murder + PETZCOUNTER_City_Theft + PETZCOUNTER_City_Attack + PETZCOUNTER_City_Sheepkiller);
};
// если НПС из Монастыря
if (C_NpcBelongsToMonastery(slf))
{
return (PETZCOUNTER_Monastery_Murder + PETZCOUNTER_Monastery_Theft + PETZCOUNTER_Monastery_Attack + PETZCOUNTER_Monastery_Sheepkiller);
};
// если НПС с Фермы наемников
if (C_NpcBelongsToFarm(slf))
{
return (PETZCOUNTER_Farm_Murder + PETZCOUNTER_Farm_Theft + PETZCOUNTER_Farm_Attack + PETZCOUNTER_Farm_Sheepkiller);
};
// если НПС из Лагеря бандитов
if (C_NpcBelongsToBL(slf))
{
return (PETZCOUNTER_BL_Murder + PETZCOUNTER_BL_Theft + PETZCOUNTER_BL_Attack);
};
return 0;
};




// *********************************************************
// Получить криминал ГГ по локациям и в порядке приоритетов
// *********************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - НПС, проживающий в локации
// --------------------------------------
// Возвращаемое значение - приоритетный криминал для локации
// ======================================


func int B_GetGreatestPetzCrime(var c_npc slf)
{
// если НПС из Миненталя
if(C_NpcBelongsToOldCamp(slf))
{
// если счетчик убийств > 0
if(PETZCOUNTER_OldCamp_Murder > 0)
{
// криминал - убийство
return CRIME_MURDER;
};
// если счетчик воровства > 0
if(PETZCOUNTER_OldCamp_Theft > 0)
{
// криминал - воровство
return CRIME_THEFT;
};
// если счетчик нападений > 0
if(PETZCOUNTER_OldCamp_Attack > 0)
{
// криминал - нападение
return CRIME_ATTACK;
};
// если счетчик убийств овец > 0
if(PETZCOUNTER_OldCamp_Sheepkiller > 0)
{
// криминал - убийство овец
return CRIME_SHEEPKILLER;
};
};
// если НПС из Хориниса
if(C_NpcBelongsToCity(slf))
{
if(PETZCOUNTER_City_Murder > 0)
{
return CRIME_MURDER;
};
if(PETZCOUNTER_City_Theft > 0)
{
return CRIME_THEFT;
};
if(PETZCOUNTER_City_Attack > 0)
{
return CRIME_ATTACK;
};
if(PETZCOUNTER_City_Sheepkiller > 0)
{
return CRIME_SHEEPKILLER;
};
};
// если НПС из Монастыря
if(C_NpcBelongsToMonastery(slf))
{
if(PETZCOUNTER_Monastery_Murder > 0)
{
return CRIME_MURDER;
};
if(PETZCOUNTER_Monastery_Theft > 0)
{
return CRIME_THEFT;
};
if(PETZCOUNTER_Monastery_Attack > 0)
{
return CRIME_ATTACK;
};
if(PETZCOUNTER_Monastery_Sheepkiller > 0)
{
return CRIME_SHEEPKILLER;
};
};
// если НПС с Фермы наемников
if(C_NpcBelongsToFarm(slf))
{
if(PETZCOUNTER_Farm_Murder > 0)
{
return CRIME_MURDER;
};
if(PETZCOUNTER_Farm_Theft > 0)
{
return CRIME_THEFT;
};
if(PETZCOUNTER_Farm_Attack > 0)
{
return CRIME_ATTACK;
};
if(PETZCOUNTER_Farm_Sheepkiller > 0)
{
return CRIME_SHEEPKILLER;
};
};
// если НПС из Лагеря бандитов
if(C_NpcBelongsToBL(slf))
{
if(PETZCOUNTER_BL_Murder > 0)
{
return CRIME_MURDER;
};
if(PETZCOUNTER_BL_Theft > 0)
{
return CRIME_THEFT;
};
if(PETZCOUNTER_BL_Attack > 0)
{
return CRIME_ATTACK;
};
};
return CRIME_NONE;
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
13. Вспомогательные С_ функции для людей (compare функции).

Все С_ функции расположены в директории ..\AI\Human\С_Human\
Следующие два файла можно удалить по причине их бесполезности: C_BanditAttackBandit.d и C_BanditHelpsStoryBandit.d
// ********************************************************************
// Проверка состояния тела НПС
// --------------------------------------------------------------------
// Примечание автора: Никогда не используйте встроенную функцию Npc_GetBodyState
// напрямую, т.к. сравнение всегда будет ложно, если установлены дополнительные
// флаги состояния тела. Все запросы на состояние тела выполняйте только
// через эту функцию.
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС, состояние тела которого проверяется
// bodystate - проверяемое состояние тела
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - состояние тела НПС совпадает с проверяемым, FALSE - не совпадает
// ====================================================================


func int C_BodyStateContains(var c_npc slf,var int bodystate)
{
// Примечание автора: Руки прочь от этой формулы!!! Я знаю точно что я делаю! (Мое примечание: с точки зрения логического анализа формула неправильна).
// если фактическое состояние тела НПС без учета допфлагов равно запрошенному состоянию без учета допфлагов
if((Npc_GetBodyState(slf)&(BS_MAX|BS_FLAG_INTERRUPTABLE|BS_FLAG_FREEHANDS)) == (bodystate&(BS_MAX|BS_FLAG_INTERRUPTABLE|BS_FLAG_FREEHANDS)))
{
return TRUE;
};
return FALSE;
};




// ********************************************************************************
// Убивается ли НПС по окончании жизни или переводится в бессознательное состояние
// ********************************************************************************


// ====================================================================
// self - проверяемый НПС
// other - преступник, убивающий НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - НПС не убивается преступником, FALSE - убивается.
// ====================================================================


func int C_DropUnconscious()
{
// если преступник монстр или Черный маг (Ищущий) или бандит или преступнику разрешено убить НПС
if(other.guild > GIL_SEPERATOR_HUM) || (other.guild == GIL_DMT) || (other.guild == GIL_BDT) || (other.aivar[AIV_DropDeadAndKill] == TRUE)
{
// НПС будет убит
return FALSE;
};
// если НПС человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// если НПС не Черный маг и не бандит и его не разрешено убивать преступнику
if(self.guild != GIL_DMT) && (self.guild != GIL_BDT) && (self.aivar[AIV_DropDeadAndKill] == FALSE)
{
// НПС будет безсознания
return TRUE;
};
};
// НПС будет убит
return FALSE;
};




// *****************************************************************
// Может ли быть взят предмет, принадлежащий одному НПС, другим НПС
// *****************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС, которому может принадлежать предмет
// oth - НПС берущий предмет (ГГ)
// itm - предмет
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - предмет взять нельзя, FALSE - взять можно.
// ====================================================================


func int C_IsTakenItemMyPossession(var c_npc slf,var c_npc oth,var c_item itm)
{
var int portalguild;
// получить номер гильдии, которой принадлежит помещение (-1 помещение никому не принадлежит)
portalguild = Wld_GetPlayerPortalGuild();
// Моё примечание: предыдущие две строки лишние и могут быть удалены.
// если предмет принадлежит НПС владельцу
if(Npc_OwnedByNpc(itm,slf))
{
// если предмет Святой молот
if(Hlp_IsItem(itm,Holy_Hammer_MIS))
{
// Святой молот взят
Hammer_Taken = TRUE;
};
// брать нельзя
return TRUE;
};
// если предмет выброшен (просто валяется)
if((itm.flags & ITEM_DROPPED) == ITEM_DROPPED)
{
// брать можно
return FALSE;
};
// если ГГ находится в помещении, принадлежащем НПС или помещение публично
// Моё примечание: правильнее вместо self написать slf, а то в некоторых случаях может быть ошибка.
if(C_NpcIsBotheredByPlayerRoomGuild(self)) || (Wld_GetPlayerPortalGuild() == GIL_PUBLIC)
{
// брать нельзя
return TRUE;
};
// если отношения между гильдиями НПС и гильдией, владеющей предметом, дружественные
if(Wld_GetGuildAttitude(slf.guild,itm.ownerguild) == ATT_FRIENDLY)
{
// брать нельзя
return TRUE;
};
// брать можно
return FALSE;
};




// ****************************************************************
// Можно ли импользовать MOB, принадлежащий одному НПС, другим НПС
// ****************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС, которому может принадлежать MOB
// oth - НПС использующий MOB (ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - MOB использовать нельзя, FALSE - можно.
// ====================================================================


func int C_IsUsedMobMyPossession(var c_npc slf,var c_npc oth)
{
// Моё примечание: правильнее вместо self и other внутри функции написать slf и oth, а то в некоторых случаях может быть ошибка.
// если MOB, используемый ГГ, принадлежит НПС
if(Npc_IsDetectedMobOwnedByNpc(other,self))
{
// нельзя
return TRUE;
};
// если ГГ находится в помещении, принадлежащем НПС или помещение публично
if(C_NpcIsBotheredByPlayerRoomGuild(self)) || (Wld_GetPlayerPortalGuild() == GIL_PUBLIC)
{
// нельзя
return TRUE;
};
// можно
return FALSE;
};


// ********************************************************************
// Функции проверяющие принадлежность НПС к определенной локации
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - принадлежит, FALSE - нет.
// ====================================================================


// Проверка принадлежности к Миненталю
// --------------------------------------------------------------------

func int C_NpcBelongsToOldCamp(var c_npc slf)
{
// если НПС значим или из окружающего народа в Минентале
if(slf.npctype == NPCTYPE_OCMAIN) || (slf.npctype == NPCTYPE_OCAMBIENT)
{
// если НПС Горожанин или Милиционер или Паладин
if(slf.guild == GIL_VLK) || (slf.guild == GIL_MIL) || (slf.guild == GIL_PAL)
{
return TRUE;
};
};
return FALSE;
};

// Проверка принадлежности к Хоринису
// --------------------------------------------------------------------

func int C_NpcBelongsToCity(var c_npc slf)
{
// если НПС не из Миненталя
if(!C_NpcBelongsToOldCamp(slf))
{
// если НПС Горожанин или Милиционер или Паладин
if(slf.guild == GIL_VLK) || (slf.guild == GIL_MIL) || (slf.guild == GIL_PAL)
{
return TRUE;
};
};
return FALSE;
};

// Проверка принадлежности к Монастырю
// ---------------------------------------------------------------------

func int C_NpcBelongsToMonastery(var c_npc slf)
{
// если НПС Маг огня или Маг послушник
if(slf.guild == GIL_KDF) || (slf.guild == GIL_NOV)
{
return TRUE;
};
return FALSE;
};

// Проверка принадлежности к Ферме наемников
// ---------------------------------------------------------------------

func int C_NpcBelongsToFarm(var c_npc slf)
{
// если НПС Крестьянин или Наемник
if(slf.guild == GIL_BAU) || (slf.guild == GIL_SLD)
{
return TRUE;
};
return FALSE;
};

// Проверка принадлежности к Лагерю бандитов
// ---------------------------------------------------------------------

func int C_NpcBelongsToBL(var c_npc slf)
{
// если НПС из окружающего народа в Лагере или Долине бандитов
if(slf.npctype == NPCTYPE_BL_AMBIENT) || (slf.npctype == NPCTYPE_BL_MAIN)
{
return TRUE;
};
return FALSE;
};




// ******************************************
// Имеет ли НПС новости об окружающей жизни
// ******************************************


// ==========================================
// Аргументы:
// ------------------------------------------
// slf - проверяемый НПС
// ------------------------------------------
// Возвращаемое значение:
// TRUE - новости есть, FALSE - нет.
// ==========================================


func int C_NpcHasAmbientNews(var c_npc slf)
{
// если НПС не знает никаких новостей
if(slf.aivar[AIV_NewsOverride] == TRUE)
{
return FALSE;
};
// если ГГ не имеет криминала
if(B_GetPlayerCrime(slf) == CRIME_NONE)
{
return FALSE;
};
// новости есть (по умолчанию)
return TRUE;
};




// *****************************************
// Является ли причиной атаки убийство цели
// *****************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС агрессор
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - причина атаки - убийство, FALSE - нет.
// ====================================================================


func int C_NpcHasAttackReasonToKill(var c_npc slf)
{
// если
if (slf.aivar[AIV_ATTACKREASON] == AR_KILL) // ГГ убил НПС
|| (slf.aivar[AIV_ATTACKREASON] == AR_GuildEnemy) // или НПС является врагом гильдии
|| (slf.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman) // или Человек убил человека
|| (slf.aivar[AIV_ATTACKREASON] == AR_GuardStopsIntruder) // или Охрана ворот атакует незваного гостя
|| (slf.aivar[AIV_ATTACKREASON] == AR_GuardCalledToKill) // или Вызвана охрана по факту убийства
{
return TRUE;
};
return FALSE;
};




// ************************************
// Находится ли ГГ в частном помещении
// ************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС, которому может принадлежать помещение
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - ГГ в частном помещении, FALSE - нет.
// ====================================================================


func int C_NpcIsBotheredByPlayerRoomGuild(var c_npc slf)
{
var int portalguild;
// получить номер гильдии, которой принадлежит помещение (-1 помещение никому не принадлежит)
portalguild = Wld_GetPlayerPortalGuild();
// если помещение принадлежит гильдии и (НПС из этой гильдии или гильдия НПС и гильдия, владеющая помещением, дружественны)
if(portalguild > GIL_NONE) && ((slf.guild == portalguild) || (Wld_GetGuildAttitude(slf.guild,portalguild) == ATT_FRIENDLY))
{
return TRUE;
};
return FALSE;
};




// *****************************************************************
// Реагирует ли цель на оружие, направленное против нее агрессором
// *****************************************************************


// =================================================================
// Аргументы:
// -----------------------------------------------------------------
// slf - НПС цель
// oth - НПС агрессор
// -----------------------------------------------------------------
// Возвращаемое значение:
// TRUE - цель реагирует, FALSE - нет.
// =================================================================


func int C_NpcIsBotheredByWeapon(var c_npc slf,var c_npc oth)
{
// если цель член партии ГГ
if(slf.aivar[AIV_PARTYMEMBER] == TRUE)
{
return FALSE;
};
// если цель друг ГГ и агрессор ГГ (Примечание: правильней вместо other написать oth)
if(slf.npctype == NPCTYPE_FRIEND) && (Npc_IsPlayer(other))
{
return FALSE;
};
// если НПС имеет дело с "крутым парнем" и агрессор сражается оружием ближнего радиуса поражения
if(C_NpcIsToughGuy(slf)) && (Npc_IsInFightMode(oth,FMODE_MELEE))
{
return FALSE;
};
// если отношения между агрессором и целью дружественны
if(Npc_GetAttitude(slf,oth) == ATT_FRIENDLY)
{
return FALSE;
};
// если цель является охранником ворот
if(C_NpcIsGateGuard(slf))
{
return FALSE;
};
// если агрессор сражается кулаками
if(Npc_IsInFightMode(oth,FMODE_FIST))
{
return FALSE;
};
// если агрессор использует магию и категория используемого заклинания безвредна
if(Npc_IsInFightMode(oth,FMODE_MAGIC) && (Npc_GetActiveSpellCat(oth) != SPELL_BAD))
{
return FALSE;
};
// если цель Черный маг или орк
if((slf.guild == GIL_DMT) || (slf.guild == GIL_ORC))
{
return FALSE;
};
return TRUE;
};


// **********************************************
// Находится ли НПС в бессознательном состоянии
// **********************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - НПС в бессознательном состоянии (обездвижен), FALSE - нет.
// ====================================================================


func int C_NpcIsDown(var c_npc slf)
{
// если НПС безсознания или в магическом сне или убит
if(Npc_IsInState(slf,ZS_Unconscious) || Npc_IsInState(slf,ZS_MagicSleep) || Npc_IsDead(slf))
{
return TRUE;
};
return FALSE;
};




// ***********************************
// Является ли НПС источником зла
// ***********************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - НПС - источник зла, FALSE - нет.
// ====================================================================


func int C_NpcIsEvil(var c_npc slf)
{
// если НПС
if (slf.guild == GIL_DMT) // Черный маг
|| (slf.guild == GIL_DRAGON) // или дракон
|| (slf.guild == GIL_ORC) // или орк
|| (slf.guild == GIL_DRACONIAN) // или ящер
|| (slf.guild == GIL_DEMON) // или демон
|| (slf.guild == GIL_SUMMONED_DEMON) // или вызванный демон
|| (slf.aivar[AIV_MM_REAL_ID] == ID_TROLL_BLACK) // или Черный троль
|| (C_NpcIsUndead(slf)) // или НПС является нежитью
{
return TRUE;
};
return FALSE;
};




// *************************************
// Является ли НПС охранником ворот
// *************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_NpcIsGateGuard(var c_npc slf)
{
// если НПС находится в состоянии охраны ворот
if(Npc_IsInState(slf,ZS_Guard_Passage))
{
return TRUE;
};
return FALSE;
};




// *************************************
// Является ли НПС ГГ
// *************************************


// =====================================
// Аргументы:
// -------------------------------------
// slf - проверяемый НПС
// -------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// =====================================


func int C_NpcIsHero(var c_npc slf)
{
var c_npc her;
// получить ссылку на ГГ
her = Hlp_GetNpc(PC_Hero);
// если идентификаторы НПС и ГГ равны
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(her))
{
return TRUE;
};
return FALSE;
};




// ***********************************************
// Является ли НПС "крутым парнем"
// ***********************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_NpcIsToughGuy(var c_npc slf)
{
// если установлен признак "крутого парня"
if(slf.aivar[AIV_ToughGuy] == TRUE)
{
return TRUE;
};
// если НПС наемник или охотник на драконов или бандит или пират
if(slf.guild == GIL_SLD) || (slf.guild == GIL_DJG) || (slf.guild == GIL_BDT) || (slf.guild == GIL_PIR)
{
return TRUE;
};
return FALSE;
};




// ***************************************
// Является ли НПС нежитью
// ***************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_NpcIsUndead(var c_npc slf)
{
// если НПС
if (slf.guild == GIL_GOBBO_SKELETON) // Скелет гоблина
|| (slf.guild == GIL_SUMMONED_GOBBO_SKELETON) // или Вызванный скелет гоблина
|| (slf.guild == GIL_SKELETON) // или Скелет
|| (slf.guild == GIL_SUMMONED_SKELETON) // или Вызванный скелет
|| (slf.guild == GIL_SKELETON_MAGE) // или Скелет маг
|| (slf.guild == GIL_ZOMBIE) // или Зомби
|| (slf.guild == GIL_SHADOWBEAST_SKELETON) // или Скелет мракориса
|| (slf.guild == GIL_UNDEADORC) // или Орк нежить
|| (slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_UNDEAD) // или Дракон нежить
{
return TRUE;
};
return FALSE;
};


// ************************************************
// Должен ли НПС обыскать тело
// ************************************************


// ================================================
// Аргументы:
// ------------------------------------------------
// slf - обыскивающий НПС
// неявно: other - обыскиваемый НПС (цель)
// ------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ================================================


func int C_NpcRansacksAlways(var c_npc slf)
{
// если НПС Гарвиг и цель имеет "Святой молот"
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Garwig)) && (Npc_HasItems(other,Holy_Hammer_MIS) > 0)
{
return TRUE;
};
// если НПС Род и цель имеет "Меч Рода"
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Rod)) && (Npc_HasItems(other,ItMw_2h_Rod) > 0)
{
return TRUE;
};
return FALSE;
};




// ********************************************************************
// Является ли НПС членом подставной гильдии
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС определяющий подставу
// oth - проверяемый НПС (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да (определяется что ГГ переодет), FALSE - нет.
// ====================================================================


func int C_PlayerHasFakeGuild(var c_npc slf,var c_npc oth)
{
var c_item itm;
// получить доспехи ГГ
itm = Npc_GetEquippedArmor(oth);
// Примечание: следующие две строки не нужны при условии коррекции функции ниже
var int NSC_CommentRangerArmor;
NSC_CommentRangerArmor = TRUE;
// если НПС игнорирует доспехи, в которые одет ГГ
if(slf.aivar[AIV_IgnoresArmor] == TRUE)
{
return FALSE;
};
// если НПС игнорирует подставную гильдию
if(slf.aivar[AIV_IgnoresFakeGuild] == TRUE)
{
return FALSE;
};
// если НПС является охранником ворот (Примечание: правильнее вместо self написать slf)
if(C_NpcIsGateGuard(self) == TRUE)
{
return FALSE;
};
// если НПС бандит и ГГ переодетый в бандита
if(slf.guild == GIL_BDT) && C_PlayerIsFakeBandit(slf,oth)
{
// если ГГ без брони
if(Npc_HasEquippedArmor(oth) == FALSE)
{
return TRUE;
}
else
{
return FALSE;
};
};
// если ГГ без брони
if(Npc_HasEquippedArmor(oth) == FALSE)
{
return FALSE;
}
// если гильдии НПС и ГГ одинаковы (Примечание: else здесь лишнее)
else if(slf.guild == oth.guild)
{
// если доспехи ГГ "Кольчуга 'Кольца Воды'"
if(Hlp_IsItem(itm,ITAR_RANGER_Addon) == TRUE)
{
// Примечание: выполняется всегда, поэтому условие if можно удалить, оставив только return TRUE;
if(NSC_CommentRangerArmor == TRUE)
{
return TRUE;
}
// Примечание: блок else можно удалить
else
{
return FALSE;
};
};
// если ГГ не принадлежит к гильдии и одет в
if(oth.guild == GIL_NONE)
&& ((Hlp_IsItem(itm,ITAR_VLK_L) == TRUE) // "Одежду горожанина"
|| (Hlp_IsItem(itm,ITAR_VLK_M) == TRUE) // или "Одежду горожанина"
|| (Hlp_IsItem(itm,ITAR_VLK_H) == TRUE) // или "Одежду горожанина" (Примечание: кто может пояснить, чем отличаются эти одежды?)
|| (Hlp_IsItem(itm,ITAR_BAU_L) == TRUE) // или "Одежду крестьянина"
|| (Hlp_IsItem(itm,ITAR_BAU_M) == TRUE) // или "Одежду крестьянина 2"
|| (Hlp_IsItem(itm,ITAR_Leather_L) == TRUE)) // или "Кожаные доспехи"
{
return FALSE;
}
// Примечание: далее до конца блока все else можно удалить
// если ГГ милиционер и одет в
else if(oth.guild == GIL_MIL)
&& ((Hlp_IsItem(itm,ITAR_MIL_L) == TRUE) // "Легкие доспехи ополчения"
|| (Hlp_IsItem(itm,ITAR_MIL_M) == TRUE)) // или "Тяжелые доспехи ополчения"
{
return FALSE;
}
// если ГГ паладин и одет в
else if(oth.guild == GIL_PAL)
&& ((Hlp_IsItem(itm,ITAR_PAL_M) == TRUE) // "Доспехи паладина"
|| (Hlp_IsItem(itm,ITAR_PAL_H) == TRUE)) // или "Доспехи паладина" (улучшенные)
{
return FALSE;
}
// если ГГ наемник и одет в
else if(oth.guild == GIL_SLD)
&& ((Hlp_IsItem(itm,ITAR_SLD_L) == TRUE) // "Легкие доспехи наемника"
|| (Hlp_IsItem(itm,ITAR_SLD_M) == TRUE) // или "Средние доспехи наемника"
|| (Hlp_IsItem(itm,ITAR_SLD_H) == TRUE)) // или "Тяжелые доспехи наемника"
{
return FALSE;
}
// если ГГ охотник на драконов и одет в
else if(oth.guild == GIL_DJG)
&& ((Hlp_IsItem(itm,ITAR_SLD_L) == TRUE) // "Легкие доспехи наемника"
|| (Hlp_IsItem(itm,ITAR_SLD_M) == TRUE) // или "Средние доспехи наемника"
|| (Hlp_IsItem(itm,ITAR_SLD_H) == TRUE) // или "Тяжелые доспехи наемника"
|| (Hlp_IsItem(itm,ITAR_DJG_L) == TRUE) // или "Легкие доспехи охотника на драконов"
|| (Hlp_IsItem(itm,ITAR_DJG_M) == TRUE) // или "Средние доспехи охотника на драконов"
|| (Hlp_IsItem(itm,ITAR_DJG_H) == TRUE) // или "Тяжелые доспехи охотника на драконов"
|| (Hlp_IsItem(itm,ITAR_DJG_Crawler) == TRUE)) // или "Доспехи из панцирей ползунов"
{
return FALSE;
}
// если ГГ маг послушник и одет в "Робу послушника"
else if(oth.guild == GIL_NOV) && (Hlp_IsItem(itm,ITAR_NOV_L) == TRUE)
{
return FALSE;
}
// если ГГ маг огня и одет в
else if(oth.guild == GIL_KDF)
&& ((Hlp_IsItem(itm,ITAR_KDF_L) == TRUE) // "Робу мага огня"
|| (Hlp_IsItem(itm,ITAR_KDF_H) == TRUE)) // или "Тяжелую робу огня"
{
return FALSE;
}
else
{
return TRUE;
};
};
return FALSE;
};




// ********************************************************************
// Является ли НПС членом гильдии бандитов
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС определяющий подставу
// oth - проверяемый НПС (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да (ГГ "принадлежит" к бандитам), FALSE - нет.
// ====================================================================


func int C_PlayerIsFakeBandit(var c_npc slf,var c_npc oth)
{
var c_item itm;
// если НПС игнорирует доспехи, в которые одет ГГ
if(slf.aivar[AIV_IgnoresArmor] == TRUE)
{
return FALSE;
};
// если НПС игнорирует подставную гильдию
if(slf.aivar[AIV_IgnoresFakeGuild] == TRUE)
{
return FALSE;
};
// если НПС пират
if(slf.guild == GIL_PIR)
{
return FALSE;
};
// если ГГ одет в броню
if(Npc_HasEquippedArmor(oth) == TRUE)
{
// получить доспехи ГГ
itm = Npc_GetEquippedArmor(oth);
// если доспехи ГГ
if((Hlp_IsItem(itm,ITAR_BDT_M) == TRUE) // "Средняя бандитская кольчуга"
|| (Hlp_IsItem(itm,ItAR_Thorus_Addon) == TRUE) // или "Тяжелая кольчуга гардиста"
|| (Hlp_IsItem(itm,ITAR_BDT_H) == TRUE)) // или "Тяжелая бандитская кольчуга"
{
return TRUE;
};
return FALSE;
}
// если НПС бандит и текущий уровень - Яркендар и ГГ может разговаривать с бандитами (Равен убит)
if(slf.guild == GIL_BDT) && (CurrentLevel == ADDONWORLD_ZEN) && (Player_HasTalkedToBanditCamp == TRUE)
{
return TRUE;
};
return FALSE;
};




// ********************************************************************
// Является ли НПС членом гильдии пиратов
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС определяющий подставу
// oth - проверяемый НПС (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да (ГГ "принадлежит" к пиратам), FALSE - нет.
// ====================================================================


func int C_PlayerIsFakePirate(var c_npc slf,var c_npc oth)
{
var c_item itm;
// если НПС игнорирует доспехи, в которые одет ГГ
if(slf.aivar[AIV_IgnoresArmor] == TRUE)
{
return FALSE;
};
// если НПС игнорирует подставную гильдию
if(slf.aivar[AIV_IgnoresFakeGuild] == TRUE)
{
return FALSE;
};
// если ГГ одет в броню (Примечание: правильнее вместо other написать oth)
if(Npc_HasEquippedArmor(other) == TRUE)
{
// получить доспехи ГГ
itm = Npc_GetEquippedArmor(oth);
// если доспехи ГГ
if((Hlp_IsItem(itm,ITAR_PIR_L_Addon) == TRUE) // "Одежда пирата"
|| (Hlp_IsItem(itm,ItAR_PIR_M_Addon) == TRUE) // или "Доспехи пирата"
|| (Hlp_IsItem(itm,ITAR_PIR_H_Addon) == TRUE)) // или "Одежда капитана"
{
return TRUE;
};
};
return FALSE;
};


// *************************************************
// Отказывается ли НПС от предлагаемого разговора
// *************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС, которому предложили разговор
// oth - инициатор разговора (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_RefuseTalk(var c_npc slf,var c_npc oth)
{
// если НПС не может говорить и он охраняет ворота и он не выдавал предупреждений
if(Npc_RefuseTalk(slf) == TRUE) && (C_NpcIsGateGuard(slf)) && (slf.aivar[AIV_Guardpassage_Status] == GP_NONE)
{
return TRUE;
};

// если НПС с ГГ не разговаривал и НПС находится от своего вайпоинта далее 5м
if(slf.aivar[AIV_TalkedToPlayer] == FALSE) && (Npc_GetDistToWP(slf,slf.wp) > 500)
{
// если НПС Лотар
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Lothar))
{
return TRUE;
};
};
// если НПС определил, что ГГ член подставной гильдии и НПС неуязвимый (Примечание: необходимо self заменить на slf)
if(C_PlayerHasFakeGuild(slf,oth) && (self.flags != NPC_FLAG_IMMORTAL)
{
return TRUE;
};
return FALSE;
};




// *************************************
// Должен ли НПС атаковать убийцу
// *************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// oth - НПС убийца (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToAttackMurder(var c_npc slf,var c_npc oth)
{
// если НПС Черный маг или Заключенный или Охотник на драконов или Бандит
if(slf.guild == GIL_DMT) || (slf.guild == GIL_STRF) || (slf.guild == GIL_DJG) || (slf.guild == GIL_BDT)
{
return FALSE;
};
// если НПС игнорирует убийство
if(slf.aivar[AIV_IGNORE_Murder] == TRUE)
{
return FALSE;
};
// если убийца ГГ и НПС ему друг
if(Npc_IsPlayer(oth) && (slf.npctype == NPCTYPE_FRIEND))
{
return FALSE;
};
// если НПС убийца должен быть убить цель
if(C_NpcHasAttackReasonToKill(oth))
{
return FALSE;
};
// если НПС охраняет ворота
if(C_NpcIsGateGuard(slf))
{
return FALSE;
};
return TRUE;
};




// ********************************************************
// Должен ли НПС напасть на незваного гостя
// ********************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToAttackRoomIntruder(var c_npc slf)
{
// Примечание: необходимо во всей функции self заменить на slf.
// если НПС Милиционер или Паладин или Наемник или Охотник на драконов или ГГ имеет совершенный криминал
if(self.guild == GIL_MIL) || (self.guild == GIL_PAL) || (self.guild == GIL_SLD) || (self.guild == GIL_DJG) || (B_GetPlayerCrime(self) != CRIME_NONE)
{
return TRUE;
};
return FALSE;
};




// **************************************
// Должен ли НПС атаковать убийцу овец
// **************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// oth - НПС убийца (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToAttackSheepKiller(var c_npc slf,var c_npc oth)
{
// если НПС Черный маг или Заключенный или Бандит или Охотник на драконов
if(slf.guild == GIL_DMT) || (slf.guild == GIL_STRF) || (slf.guild == GIL_BDT) || (slf.guild == GIL_DJG)
{
return FALSE;
};
// если НРС игнорирует убийство овец
if(slf.aivar[AIV_IGNORE_Sheepkiller] == TRUE)
{
return FALSE;
};
// если убийца ГГ и НПС ему друг
if(Npc_IsPlayer(oth) && (slf.npctype == NPCTYPE_FRIEND))
{
return FALSE;
};
// если убийца должен был убить овцу
if(C_NpcHasAttackReasonToKill(oth))
{
return FALSE;
};
// если убийца человек и у него была причина нападения (Примечание: необходимо other заменить на oth)
if(other.guild < GIL_SEPERATOR_HUM) && (other.aivar[AIV_ATTACKREASON] != AR_NONE)
{
return FALSE;
};
// если НПС охраняет ворота
if(C_NpcIsGateGuard(slf))
{
return FALSE;
};
return TRUE;
};




// ******************************************
// Должен ли НПС атаковать вора
// ******************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// oth - НПС вор (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToAttackThief(var c_npc slf,var c_npc oth)
{
// если НПС Черный ман или Заключенный или Охотник на драконов
if(slf.guild == GIL_DMT) || (slf.guild == GIL_STRF) || (slf.guild == GIL_DJG)
{
return FALSE;
};
// если НПС не реагирует на воровство
if(slf.aivar[AIV_IGNORE_Theft] == TRUE)
{
return FALSE;
};
// если НПС проиграл последнее сражение с ГГ
if(slf.aivar[AIV_LastFightAgainstPlayer] == FIGHT_LOST)
{
return FALSE;
};
// если вор ГГ и НПС ему друг
if(Npc_IsPlayer(oth) && (slf.npctype == NPCTYPE_FRIEND))
{
return FALSE;
};
// если НПС охраняет ворота
if(C_NpcIsGateGuard(slf))
{
return FALSE;
};
return TRUE;
};




// *********************************
// Должен ли НПС убежать от цели
// *********************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// oth - цель (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToFlee(var c_npc slf,var c_npc oth)
{
// никогда не убегает!!!
return FALSE;
};




// *********************************
// Должен ли НПС обыскать тело
// *********************************


// =================================
// Аргументы:
// ---------------------------------
// slf - проверяемый НПС
// other - тело (задано неявно)
// ---------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// =================================


func int C_WantToRansack(var c_npc slf)
{
// если НРС друг ГГ и тело есть ГГ
if(slf.npctype == NPCTYPE_FRIEND) && (Npc_IsPlayer(other))
{
return FALSE;
};
// если НПС Равен
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(Raven))
{
return FALSE;
};
// если НПС Черный маг или Орк или Паладин или Маг огня или Послушник или Маг воды
if(slf.guild == GIL_DMT) || (slf.guild == GIL_ORC) || (slf.guild == GIL_PAL) || (slf.guild == GIL_KDF) || (slf.guild == GIL_NOV) || (slf.guild == GIL_KDW)
{
return FALSE;
};
return TRUE;
};




// **********************************************
// Должен ли НПС реагировать на крадущегося ГГ
// **********************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый НПС
// oth - крадущийся НПС (обычно ГГ)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToReactToSneaker(var c_npc slf,var c_npc oth)
{
// если расстояние между НПС и ГГ > 7м
if(Npc_GetDistToNpc(slf,oth) > 700)
{
return FALSE;
};
// если НПС Черный маг или Заключенный или Бандит и НПС не принадлежит к Лагерю бандитов
if(slf.guild == GIL_DMT) || (slf.guild == GIL_STRF) || ((slf.guild == GIL_BDT) && !C_NpcBelongsToBL(slf))
{
return FALSE;
};
// если НПС друг ГГ и ГГ крадется
if(slf.npctype == NPCTYPE_FRIEND) && (Npc_IsPlayer(oth))
{
return FALSE;
};
// если отношения между НПС и крадущимся НПС дружеские
if(Npc_GetAttitude(slf,oth) == ATT_FRIENDLY)
{
return FALSE;
};
// если НПС охраняет ворота (Примечание: необходимо self заменить на slf)
if(C_NpcIsGateGuard(self))
{
return FALSE;
};
return TRUE;
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
14. Отношения между гильдиями.

Отношения между гильдиями людей задаются в файле AI\Human\Guilds.d в виде таблицы. Ссылки в скриптах на эту таблицу вы не найдете, она используется только экзешником.
Примечание: Таблицу необходимо смотреть в широкоформатном редакторе.
// размер таблицы
const int TAB_ANZAHL = 16 * 16;

// таблица отношений между гильдиями людей
const int GIL_ATTITUDES[TAB_ANZAHL] =
{
// ***Гильдии*** Отсутствует Паладин Милиционер Горожанин Маг огня Послушник Охотник драк. Наемник Крестьянин Бандит Заключенный Черный маг Чузеземец Пират Маг воды Публичная
/* Отсутствует */
ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/*******************************************************************************
********************************************************************************
********************************************************************************
/* Паладин */
ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Милиционер */ ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Горожанин */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/*******************************************************************************
********************************************************************************
********************************************************************************
/* Маг огня */
ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Послушник */ ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/*******************************************************************************
********************************************************************************
********************************************************************************
/* Охотник драк.*/
ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Наемник */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Крестьянин */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/*******************************************************************************
********************************************************************************
********************************************************************************
/* Бандит */
ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Заключенный */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/* Черный маг */ ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_HOSTILE, ATT_NEUTRAL, ATT_HOSTILE, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL,
/*******************************************************************************
********************************************************************************
********************************************************************************
/* Чужеземец */
ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL,
/* Пират */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL,
/* Маг воды */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_HOSTILE, ATT_NEUTRAL, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL, ATT_FRIENDLY, ATT_NEUTRAL,
/* Публичная */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL
};

Отношения между гильдиями монстров и гильдиями монстров и людей задаются в файле AI\Monster\B_Monster\B_InitMonsterAttitudes.d
Данный файл я приводить не буду, у него очень большой размер (около 160 Кб).
Все отношения задаются через вызов функции B_InitMonsterAttitudes(), эту функцию мы и рассмотрим: она расположена в этой же директории в одноименном файле.
// ********************************************************************
// Устанавливает отношения между гильдиями монстров и всеми остальными
// ********************************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// fromGuild - гильдия для которой устанавливается отношение
// attitude - отношение
// toGuild - гильдия с которой устанавливается отношение
// ====================================================================


func void B_SetMonsterAttitude(var int fromGuild,var int attitude,var int toGuild)
{
// если отношение устанавливается с людьми
if(toGuild == GIL_SEPERATOR_HUM)
{
Wld_SetGuildAttitude(fromGuild,attitude,GIL_NONE);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_PAL);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_MIL);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_VLK);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_KDF);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_NOV);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_DJG);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_SLD);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_BAU);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_BDT);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_STRF);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_OUT);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_PIR);
Wld_SetGuildAttitude(fromGuild,attitude,GIL_KDW);
}
// если отношение устанавливается для людей
else if(fromGuild == GIL_SEPERATOR_HUM)
{
Wld_SetGuildAttitude(GIL_NONE,attitude,toGuild);
Wld_SetGuildAttitude(GIL_PAL, attitude,toGuild);
Wld_SetGuildAttitude(GIL_MIL, attitude,toGuild);
Wld_SetGuildAttitude(GIL_VLK, attitude,toGuild);
Wld_SetGuildAttitude(GIL_KDF, attitude,toGuild);
Wld_SetGuildAttitude(GIL_NOV, attitude,toGuild);
Wld_SetGuildAttitude(GIL_DJG, attitude,toGuild);
Wld_SetGuildAttitude(GIL_SLD, attitude,toGuild);
Wld_SetGuildAttitude(GIL_BAU, attitude,toGuild);
Wld_SetGuildAttitude(GIL_BDT, attitude,toGuild);
Wld_SetGuildAttitude(GIL_STRF,attitude,toGuild);
Wld_SetGuildAttitude(GIL_OUT, attitude,toGuild);
Wld_SetGuildAttitude(GIL_PIR, attitude,toGuild);
Wld_SetGuildAttitude(GIL_KDW, attitude,toGuild);
}
else // устанавливается отношение между монстрами
{
Wld_SetGuildAttitude(fromGuild,attitude,toGuild);
};
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
15. Магия.

Общие магические функции расположены в директории AI\Magic
// ****************************************************
// Регистрация повреждения от магии и начисление экспы
// ****************************************************


// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - НПС кастующий заклинание
// oth - НПС цель
// damage - повреждение, нанесенное заклинанием
// ====================================================================


func void B_MagicHurtNpc(var c_npc slf,var c_npc oth,var int damage)
{
// уменьшить жизнь цели на величину повреждения
Npc_ChangeAttribute(oth,ATR_HITPOINTS,-damage);
// если цель мертва
if(Npc_IsDead(oth))
{
// (если кастующий ГГ или кастующий член партии ГГ) и экспа за цель не была начислена
if(Npc_IsPlayer(slf) || (slf.aivar[AIV_PARTYMEMBER]==TRUE)) && (oth.aivar[AIV_VictoryXPGiven] == FALSE)
{
// начисление ГГ экспы (уровень цели * 10) (Примечание: Ошибка - вместо self.level должно быть oth.level)
B_GivePlayerXP(self.level * XP_PER_VICTORY);
// установить НПС флаг начисления экспы
oth.aivar[AIV_VictoryXPGiven] = TRUE;
};
};
};




// **************************************
// Подготовка заклинания к использованию
// **************************************


// ================================================
// Аргументы:
// ------------------------------------------------
// slf - НПС кастующий заклинание
// spell - заклинание
// mana - требуемое кол-во маны
// ================================================


func void B_ReadySpell(var c_npc slf,var int spell,var int mana)
{
// если макс. мана < требуемой
if(slf.attribute[ATR_MANA_MAX] < mana)
{

// увеличить макс. ману на величину требуемой
Npc_ChangeAttribute(slf,ATR_MANA_MAX,mana);
};
// если мана < требуемой
if(slf.attribute[ATR_MANA] < mana)
{
// увеличить ману на величину требуемой
Npc_ChangeAttribute(slf,ATR_MANA,mana);
};
// если это заклинание уже применяется
if(Npc_IsDrawingSpell(slf) == spell)
{
return;
}
// если это заклинание уже активно
if(Npc_GetActiveSpell(slf) == spell)
{
return;
}
// если активно другое заклинание
else if(Npc_GetActiveSpell(slf) != -1)
{
// убрать старое заклинание
AI_RemoveWeapon(slf);
};
// взять заклинание в руку
AI_ReadySpell(slf,spell,mana);
};


// *************************************************************
// Выбор заклинания кастующим НПС
// *************************************************************


// =============================================================
// Аргументы:
// -------------------------------------------------------------
// slf - НПС кастующий заклинание (агрессор)
// oth - НПС цель
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - заклинание готово, FALSE - нет.
// =============================================================


func int B_SelectSpell(var c_npc slf,var c_npc oth)
{
// если агрессор друг ГГ и цель ГГ и цель человек
if(slf.npctype == NPCTYPE_FRIEND) && Npc_IsPlayer(oth) && (oth.guild < GIL_SEPERATOR_HUM)
{
// если агрессор Маг огня или агрессор всегда использует магию
if(slf.guild == GIL_KDF) || (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS)
{
// если агрессор не имеет руны Сон
if(Npc_HasItems(slf,ItRu_Sleep) == 0)
{
// создать в инвентаре агрессора руну Сон
CreateInvItems(slf,ItRu_Sleep,1);
};
// подготовка заклинания Сон
B_ReadySpell(slf,SPL_Sleep,SPL_Cost_Sleep);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Черный маг и агрессор всегда использует магию
if(slf.guild == GIL_DMT) && (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS)
{
// создать в инвентаре агрессора следующие руны, если он их не имеет
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0) {CreateInvItems(slf,ItRu_InstantFireball,1);}; // "Огненный шар"
if(Npc_HasItems(slf,ItRu_Deathbolt) == 0) {CreateInvItems(slf,ItRu_Deathbolt,1);}; // "Deathbolt" (Примечание: название не переведено)
if(Npc_HasItems(slf,ItRu_Deathball) == 0) {CreateInvItems(slf,ItRu_Deathball,1);}; // "Deathball"
if(Npc_HasItems(slf,ItRu_Firerain) == 0) {CreateInvItems(slf,ItRu_Firerain,1);}; // "Огненный дождь"
if(Npc_HasItems(slf,ItRu_Thunderstorm) == 0) {CreateInvItems(slf,ItRu_Thunderstorm,1);}; // "Шторм"
if(Npc_HasItems(slf,ItRu_LightningFlash) == 0) {CreateInvItems(slf,ItRu_LightningFlash,1);}; // "Удар молнии"
if(Npc_HasItems(slf,ItRu_Firestorm) == 0) {CreateInvItems(slf,ItRu_Firestorm,1);}; // "Малая огненная буря"
if(Npc_HasItems(slf,ItRu_Skull) == 0) {CreateInvItems(slf,ItRu_Skull,1);}; // "Крик мертвых"
// если агрессор "Черный маг" (Примечание: Маг какой-то особенный, хотя в переводе не отражено)
if(Hlp_GetInstanceID(slf) == Hlp_GetInstanceID(DMT_1299_OberDementor_DI))
{
// подготовка заклинания "Крик мертвых"
B_ReadySpell(slf,SPL_Skull,SPL_Cost_Skull);
return TRUE;
}
else // обычные Черные маги
{
// если уже есть оружие готовое к бою
if(Npc_IsDrawingWeapon(slf))
{
return TRUE;
};
// если случайное число не задано
if(slf.aivar[AIV_SelectSpell] <= 0)
{
var int dK_rnd;
dK_rnd = Hlp_Random(10);
// получить случайное число
slf.aivar[AIV_SelectSpell] += dK_rnd;
};
// если случайное число < 10
if(slf.aivar[AIV_SelectSpell] < 10)
{
// если Глава <= 3, то подготовить заклинание "Огненный шар"
if(Kapitel <= 3) {B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball); return TRUE;}
// если Глава <= 4, то подготовить заклинание "Deathbolt"
else if (Kapitel <= 4) {B_ReadySpell(slf,SPL_DeathBolt,SPL_Cost_DeathBolt); return TRUE;}
// иначе подготовить заклинание "Deathbаll"
else /*Kap 5+*/ {B_ReadySpell(slf,SPL_DeathBall,SPL_Cost_DeathBall); return TRUE;};
}
// если случайное число == 10
else if(slf.aivar[AIV_SelectSpell] == 10)
{
// случайное число = 11
slf.aivar[AIV_SelectSpell] = 11;
var int dK_Mega;
dK_Mega = Hlp_Random(100);
// с вероятностью 0.02 подготовить заклинание "Огненный дождь"
if (dK_Mega <= 2) {B_ReadySpell(slf,SPL_Firerain,SPL_Cost_Firerain); return TRUE;}
// с вероятностью 0.03 подготовить заклинание "Шторм"
else if (dK_Mega <= 5) {B_ReadySpell(slf,SPL_Thunderstorm,SPL_Cost_Thunderstorm); return TRUE;}
// с вероятностью 0.05 подготовить заклинание "Удар молнии"
else if (dK_Mega <= 10) {B_ReadySpell(slf,SPL_LightningFlash,SPL_Cost_LightningFlash); return TRUE;}
// с вероятностью 0.9 подготовить заклинание "Малая огненная буря"
else {B_ReadySpell(slf,SPL_Firestorm,SPL_Cost_Firestorm); return TRUE;};
}
// если случайное число == 12
else if (slf.aivar[AIV_SelectSpell] == 12)
{
// случайное число == 0
slf.aivar[AIV_SelectSpell] = 0;
};
};
return TRUE;
};
// если агрессор Маг огня или агрессор всегда использует магию
if(slf.guild == GIL_KDF) || (slf.aivar[AIV_MagicUser] == MAGIC_ALWAYS)
{
// создать в инвентаре агрессора следующие руны, если он их не имеет
if(Npc_HasItems(slf,ItRu_Concussionbolt) == 0)
{
CreateInvItems(slf,ItRu_Concussionbolt,1); // "Concussionbolt" (Название не переведено)
};
if(Npc_HasItems(slf,ItRu_InstantFireBall) == 0)
{
CreateInvItems(slf,ItRu_InstantFireBall,1); // "Огненный шар"
};
if(Npc_HasItems(slf,ItRu_Deathball) == 0)
{
CreateInvItems(slf,ItRu_Deathball,1); // "Deathball" (Название не переведено)
};
if(Npc_HasItems(slf,ItRu_FullHeal) == 0)
{
CreateInvItems(slf,ItRu_FullHeal,1); // "Лечить сильное ранение"
};
// если текущая жизнь агрессора < 100 (Примечание: здесь и далее необходимо self заменить на slf)
if(self.attribute[ATR_HITPOINTS] < 100)
{
// подготовить заклинание "Лечить сильное ранение"
B_ReadySpell(slf,SPL_FullHeal,SPL_Cost_FullHeal);
return TRUE;
}
// если причина атаки агрессора убийство цели
else if(C_NpcHasAttackReasonToKill(self))
{
// если цель неуязвима или цель Равен (Примечание: Ошибка - необходимо self и other заменить на oth)
if(self.flags == NPC_FLAG_IMMORTAL) || (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(Raven))
{
// подготовить заклинание "Deathball"
B_ReadySpell(slf,SPL_Deathball,SPL_Cost_Deathball);
}
else
{
// подготовить заклинание "Огненный шар"
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireBall);
};
return TRUE;
}
else
{
// подготовить заклинание "Concussionbolt"
B_ReadySpell(slf,SPL_Concussionbolt,SPL_Cost_Concussionbolt);
return TRUE;
};
};
// если агрессор Паладин
if(slf.guild == GIL_PAL)
{
// если агрессор применяет тактику сражения охраны крепостных стен
if(slf.fight_tactic == FAI_NAILED)
{
return FALSE;
};
// если агрессор не имеет руны "Святая стрела"
if(Npc_HasItems(slf,ItRu_PalHolyBolt) == 0)
{
// создать в инвентаре агрессора руну "Святая стрела"
CreateInvItems(slf,ItRu_PalHolyBolt,1);
};
// если расстояние между агрессором и целью > дистанции атаки оружием ближнего радиуса действия и цель является источником зла
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE) && (C_NpcIsEvil(oth))
{
// подготовить заклинание "Святая стрела"
B_ReadySpell(slf,SPL_PalHolyBolt,SPL_Cost_PalHolyBolt);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Маг скелетов
if(slf.guild == GIL_SKELETON_MAGE)
{
// создать в инвентаре агрессора следующие руны, если он их не имеет
if(Npc_HasItems(slf,ItRu_SumSkel) == 0)
{
CreateInvItems(slf,ItRu_SumSkel,1); // "Вызвать скелет"
};
if(Npc_HasItems(slf,ItRu_IceCube) == 0)
{
CreateInvItems(slf,ItRu_IceCube,1); // "Ледяная глыба"
};
if(Npc_HasItems(slf,ItRu_Icebolt) == 0)
{
CreateInvItems(slf,ItRu_Icebolt,1); // "Ледяная стрела"
};
// если случайное число >= 6
if(slf.aivar[AIV_SelectSpell] >= 6)
{
// случайное число = 1
slf.aivar[AIV_SelectSpell] = 1;
};
// если цель не заморожена и случайное число == 0
if(!Npc_IsInState(oth,ZS_MagicFreeze)) && (slf.aivar[AIV_SelectSpell] == 0)
{
// подготовить заклинание "Ледяная глыба"
B_ReadySpell(slf,SPL_IceCube,SPL_Cost_IceCube);
return TRUE;
}
// если случайное число == 1
else if (slf.aivar[AIV_SelectSpell] == 1)
{
// подготовить заклинание "Вызвать скелет"
B_ReadySpell(slf,SPL_SummonSkeleton,SPL_Cost_SummonSkeleton);
return TRUE;
}
else
{
// подготовить заклинание "Ледяная стрела"
B_ReadySpell(slf,SPL_Icebolt,SPL_Cost_Icebolt);
return TRUE;
};
};
// если агрессор Ледяной голем
if(slf.guild == GIL_ICEGOLEM)
{
// если агрессор не имеет руны "Ледяная глыба"
if(Npc_HasItems(slf,ItRu_IceCube) == 0)
{
// создать в инвентаре агрессора руну "Ледяная глыба"
CreateInvItems(slf,ItRu_IceCube,1);
};
// если расстояние между агрессором и целью < дистанции атаки оружием ближнего радиуса действия или цель заморожена
if(Npc_GetDistToNpc(slf,oth) < FIGHT_DIST_MELEE) || Npc_IsInState(oth,ZS_MagicFreeze)
{
return FALSE;
}
else
{
// подготовить заклинание "Ледяная глыба"
B_ReadySpell(slf,SPL_IceCube,SPL_Cost_IceCube);
return TRUE;

};
};
// если агрессор Огненный голем
if(slf.guild == GIL_FIREGOLEM)
{
// если агрессор не имеет руны "Огненный шар"
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
// создать в инвентаре агрессора руну "Огненный шар"
CreateInvItems(slf,ItRu_InstantFireball,1);
};
// если расстояние между агрессором и целью > дистанции атаки оружием ближнего радиуса действия
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE)
{
// подготовить заклинание "Огненный шар"
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Болотный дракон
if(slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_SWAMP)
{
// если агрессор не имеет руны "Огненный шар"
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
// создать в инвентаре агрессора руну "Огненный шар"
CreateInvItems(slf,ItRu_InstantFireball,1);
};
// если расстояние между агрессором и целью > дистанции применения драконами магии
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
// подготовить заклинание "Огненный шар"
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Каменный дракон (всё идентично Болотному дракону)
if(slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ROCK)
{
if (Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
CreateInvItems(slf,ItRu_InstantFireball,1);
};
if (Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Огненный дракон (всё идентично Болотному дракону)
if(slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE)
{
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
CreateInvItems(slf,ItRu_InstantFireball,1);
};
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Ледяной дракон (всё идентично Болотному дракону)
if(slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE)
{
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
CreateInvItems(slf,ItRu_InstantFireball,1);
};
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Дракон нежить
if(slf.aivar[AIV_MM_REAL_ID] == ID_DRAGON_UNDEAD)
{
// очистить очередь AI состояний агрессора (Примечание: заменить self на slf)
Npc_ClearAIQueue(self);
// если агрессор не имеет руны "Deathball"
if(Npc_HasItems(slf,ItRu_Deathball) == 0)
{
// создать в инвентаре агрессора руну "Deathball"
CreateInvItems(slf,ItRu_Deathball,1);
};
// если расстояние между агрессором и целью > дистанции применения драконами магии
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_DRAGON_MAGIC)
{
// подготовить заклинание "Deathball"
B_ReadySpell(slf,SPL_Deathball,SPL_Cost_Deathball);
return TRUE;
}
else
{
return FALSE;
};
};
// если агрессор Шаман орков (всё идентично Огненному голему)
if(slf.aivar[AIV_MM_REAL_ID] == ID_ORCSHAMAN)
{
if(Npc_HasItems(slf,ItRu_InstantFireball) == 0)
{
CreateInvItems(slf,ItRu_InstantFireball,1);
};
if(Npc_GetDistToNpc(slf,oth) > FIGHT_DIST_MELEE)
{
B_ReadySpell(slf,SPL_InstantFireball,SPL_Cost_InstantFireball);
return TRUE;
}
else
{
return FALSE;
};
};
return FALSE;
};


// ******************************************************************
// Действия, оказываемые заклинаниями, на НПС
// ------------------------------------------------------------------
// Данная функция вызывается только экзешником в состоянии НПС реакции на магию
// self - НПС, против которого применено заклинание
// other - НПС, применивший заклинание
// ******************************************************************


const int COLL_DONOTHING = 0; // воздействие не оказывается
const int COLL_DOEVERYTHING = 1<<0; // полное воздействие
const int COLL_APPLYDAMAGE = 1<<1; // только физический урон
const int COLL_APPLYHALVEDAMAGE = 1<<2; // половинный урон
const int COLL_APPLYDOUBLEDAMAGE = 1<<3; // удвоенный урон
const int COLL_APPLYVICTIMSTATE = 1<<4; // в зависимости от состояния жертвы
const int COLL_DONTKILL = 1<<5; // не убивает


// =============================================================
// Аргументы:
// -------------------------------------------------------------
// spellType - тип заклинания
// --------------------------------------------------------------------
// Возвращаемое значение:
// Тип оказываемого воздействия на НПС.
// =============================================================


func int C_CanNpcCollideWithSpell(var int spellType)
{
// если заклинание "Смерч"
if(spellType == SPL_Whirlwind)
{
// если НПС обездвижен или
if (C_NpcIsDown(self))
|| (C_BodyStateContains(self,BS_SWIM)) // плывет
|| (C_BodyStateContains(self,BS_DIVE)) // или ныряет
|| (self.guild == GIL_STONEGOLEM) // или Каменный голем
|| (self.guild == GIL_ICEGOLEM) // или Ледяной голем
|| (self.guild == GIL_FIREGOLEM) // или Каменный голем
|| (self.guild == GIL_SUMMONED_GOLEM) // или Вызванный голем
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_SUMMONED_DEMON) // или Вызванный демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_SUMMONED_GOLEM) // повтор (убрать!)
|| (self.guild == GIL_DRAGON) // или Дракон
|| (self.guild == GIL_STONEGUARDIAN) // или Каменный страж
|| (self.flags == NPC_FLAG_IMMORTAL) // или неубиваем
|| (self.guild == GIL_SHADOWBEAST) // или Мракорис
|| (self.guild == GIL_GARGOYLE) // или Огненный дух мракориса
{
return COLL_DONOTHING;
};
// если НПС охраняет ворота
if(C_NpcIsGateGuard(self) == TRUE)
{
return COLL_APPLYDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Ледяное копье"
if(spellType == SPL_Icelance)
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС Ледяной голем или Ледяной волк или Ледяной дракон
if(self.guild == GIL_ICEGOLEM) || (self.aivar[AIV_MM_REAL_ID] == ID_Icewolf) || (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE)
{
return COLL_APPLYHALVEDAMAGE;
};
// если НПС Огненный голем или
if (self.guild == GIL_FIREGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) // Огненная ящерица
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE) // или Огненный дракон
|| (self.guild == GIL_GARGOYLE) // или Огненный дух мракориса
{
return COLL_APPLYDOUBLEDAMAGE;
};
return COLL_APPLYDAMAGE;
};
// если заклинание "Шторм"
if (spellType == SPL_Thunderstorm)
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС Ледяной голем или Ледяной волк или Ледяной дракон
if(self.guild == GIL_ICEGOLEM) || (self.aivar[AIV_MM_REAL_ID] == ID_Icewolf) || (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE)
{
return COLL_APPLYHALVEDAMAGE;
};
// если НПС Огненный голем или
if (self.guild == GIL_FIREGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) // Огненная ящерица
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE) // или Огненный дракон
|| (self.guild == GIL_GARGOYLE) // или Огненный дух мракориса
{
return COLL_APPLYDOUBLEDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Гейзер"
if(spellType == SPL_Geyser)
{
// если НПС обездвижен
if (C_NpcIsDown(self))
|| (C_BodyStateContains(self,BS_SWIM)) // или плывет
|| (C_BodyStateContains(self,BS_DIVE)) // или ныряет
|| (self.guild == GIL_STONEGOLEM) // или Каменный голем
|| (self.guild == GIL_ICEGOLEM) // или Ледяной голем
|| (self.guild == GIL_FIREGOLEM) // или Огненный голем
|| (self.guild == GIL_SUMMONED_GOLEM) // или Вызванный голем
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_SUMMONED_DEMON) // или Вызванный демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_SUMMONED_GOLEM) // повтор (убрать!)
|| (self.guild == GIL_DRAGON) // или Дракон
|| (self.guild == GIL_STONEGUARDIAN) // или Каменный страж
{
return COLL_DONOTHING;
};
return COLL_APPLYDAMAGE | COLL_DONTKILL;
};
// если заклинание "Кулак воды"
if(spellType == SPL_Waterfist)
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС Дракон или Троль
if(self.guild == GIL_DRAGON) || (self.guild == GIL_TROLL)
{
return COLL_APPLYHALVEDAMAGE;
};
// если НПС Огненный голем или Огненная ящерица или Огненный дух мракориса
if(self.guild == GIL_FIREGOLEM) || (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) || (self.guild == GIL_GARGOYLE)
{
return COLL_APPLYDOUBLEDAMAGE;
};
return COLL_APPLYDAMAGE | COLL_DONTKILL;
};
// если заклинание "Шар энергии"
if(spellType == SPL_EnergyBall)
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС нежить
if(C_NpcIsUndead(self))
{
return COLL_APPLYHALVEDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Украсть энергию"
if(spellType == SPL_SuckEnergy)
{
// если НПС обездвижен или
if (C_NpcIsDown(self))
|| (C_BodyStateContains(self,BS_SWIM)) // плывет
|| (C_BodyStateContains(self,BS_DIVE)) // или ныряет
|| (self.guild > GIL_SEPERATOR_HUM) // или монстр
|| (self.flags == NPC_FLAG_IMMORTAL) // или неубиваем
|| (Npc_GetDistToNpc(self,other) > 1000) // или расстояние между НПС > 10м
|| (self.guild == GIL_DMT) // или Черный маг
{
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Зеленые щупальца"
if(spellType == SPL_GreenTentacle)
{
// если НПС обездвижен или
if (C_NpcIsDown(self))
|| (C_BodyStateContains(self,BS_SWIM)) // плывет
|| (C_BodyStateContains(self,BS_DIVE)) // или ныряет
|| (C_NpcIsGateGuard(self)== TRUE) // или охраняет ворота
|| (self.guild == GIL_BLOODFLY) // или Кровяной шершень
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_DRAGON) // или Дракон
|| (self.guild == GIL_HARPY) // или Гарпия
|| (self.aivar[AIV_MM_REAL_ID] == ID_SKELETON_MAGE) // или Маг скелетов
|| (self.guild == GIL_Gargoyle) // или Огненный дух мракориса
{
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Рой"
if(spellType == SPL_Swarm)
{
// если НПС обездвижен или
if (C_NpcIsDown(self))
|| (C_BodyStateContains(self,BS_SWIM)) // плывет
|| (C_BodyStateContains(self,BS_DIVE)) // или ныряет
|| (self.guild == GIL_STONEGOLEM) // или Каменный голем
|| (self.guild == GIL_ICEGOLEM) // или Ледяной голем
|| (self.guild == GIL_FIREGOLEM) // или Огненный голем
|| (self.guild == GIL_SUMMONED_GOLEM) // или Вызванный голем
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_SUMMONED_DEMON) // или Вызванный демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_BLOODFLY) // или Кровяной шершень
|| (self.guild == GIL_DRAGON) // или Дракон
|| (self.guild == GIL_Gargoyle) // или Огненный дух мракориса
|| (self.guild == GIL_DMT) // или Черный маг
|| (self.guild == GIL_STONEGUARDIAN) // или Каменный страж
|| (C_NPCIsUndead(self) == TRUE) // или нежить
{
return COLL_DONOTHING;
};
// если НПС монстр или охраняет ворота
if(self.guild > GIL_SEPERATOR_HUM) || (C_NpcIsGateGuard(self) == TRUE)
{
return COLL_APPLYDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Крик мертвых"
if(spellType == SPL_Skull)
{
// если НПС обездвижен или плывет или ныряет или нежить
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE)) || (C_NpcIsUndead(self))
{
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Порыв ветра"
if(spellType == SPL_WINDFIST)
{
// если расстояние между НПС > 10м
if(Npc_GetDistToNpc(other,self) >= 1000)
{
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};
// если заклинание "Молния" или "Шаровая молния" или "Стрела сотрясения"
if(spellType == SPL_Zap) || (spellType == SPL_ChargeZap) || (spellType == SPL_Concussionbolt)
{
// если НПС обездвижен
if(C_NpcIsDown(self))
{
return COLL_DONOTHING;
};
return COLL_APPLYDAMAGE | COLL_DONTKILL;
};
// если нападающий Черный маг
if(other.guild == GIL_DMT)
{
// если заклинание "Огненный дождь" или "Шторм" или "Удар молнии"
if(spellType == SPL_Firerain) || (spellType == SPL_Thunderstorm) || (spellType == SPL_LightningFlash)
{
// если НПС Черный маг
if(self.guild == GIL_DMT)
{
return COLL_DONOTHING;
}
// если НПС ГГ
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(hero))
{
return COLL_APPLYHALVEDAMAGE;
};
};
// если заклинание Большая огненная буря и НПС Черный маг
if(spellType == SPL_Firestorm) && (self.guild == GIL_DMT)
{
return COLL_DONOTHING;
};
};
// если заклинание Большой огненный шар или
if (spellType == SPL_ChargeFireball)
|| (spellType == SPL_InstantFireball) // или Огненный шар
|| (spellType == SPL_Firerain) // или Огненный дождь
|| (spellType == SPL_Firebolt) // или Огненная стрела
|| (spellType == SPL_Firestorm) // или Большая огненная буря
|| (spellType == SPL_Pyrokinesis) // или Малая огненная буря
|| (spellType == SPL_Deathbolt) // или Стрела смерти
|| (spellType == SPL_Deathball) // или Шар смерти
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС Огненный голем или
if (self.guild == GIL_FIREGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) // Огненная ящерица
|| (self.guild == GIL_GARGOYLE) // или Огненный дух мракориса
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE) // или Огненный дракон
{
return COLL_APPLYHALVEDAMAGE;
}
// если НПС Ледяной голем или
if (self.guild == GIL_ICEGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE) // Ледяной дракон
|| (self.aivar[AIV_MM_REAL_ID] == ID_ICEWOLF) // или Ледяной волк
{
return COLL_APPLYDOUBLEDAMAGE;
};
// если НПС Каменный голем или
if (self.guild == GIL_STONEGOLEM)
|| (self.guild == GIL_SUMMONED_GOLEM) // Вызванный голем
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_SUMMONED_DEMON) // или Вызванный демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_DRAGON) // или Дракон
{
return COLL_APPLYDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание Ледяная глыба или Ледяная волна или Ледяная стрела
if(spellType == SPL_IceCube) || (spellTYpe == SPL_IceWave) || (spelltype == SPL_Icebolt)
{
// если НПС обездвижен или плывет или ныряет
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
return COLL_DONOTHING;
};
// если НПС Огненный голем или
if (self.guild == GIL_FIREGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) // Огненная ящерица
|| (self.guild == GIL_GARGOYLE) // или Огненный дух мракориса
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE) // или Огненный дракон
{
return COLL_APPLYDOUBLEDAMAGE;
};
// если НПС Ледяной голем или
if (self.guild == GIL_ICEGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE) // Ледяной дракон
|| (self.aivar[AIV_MM_REAL_ID] == ID_ICEWOLF) // или Ледяной волк
{
return COLL_APPLYHALVEDAMAGE;
};
// если НПС Каменный голем или
if (self.guild == GIL_STONEGOLEM)
|| (self.guild == GIL_SUMMONED_GOLEM) // Вызванный голем
|| (self.guild == GIL_DEMON) // или Демон
|| (self.guild == GIL_SUMMONED_DEMON) // или Вызванный демон
|| (self.guild == GIL_TROLL) // или Троль
|| (self.guild == GIL_DRAGON) // или Дракон
{
return COLL_APPLYDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание Удар молнии
if (spellType == SPL_LightningFlash)
{
// если НПС обездвижен
if(C_NpcIsDown(self))
{
return COLL_DONOTHING;
};
// если НПС плывет или ныряет
if(C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
COLL_APPLYDOUBLEDAMAGE;
};
return COLL_DOEVERYTHING;
};
// если заклинание Страх
if(spellType == SPL_Fear)
{
// если НПС не Огненный голем и
if (self.guild != GIL_FIREGOLEM)
&& (self.guild != GIL_ICEGOLEM) // не Ледяной голем
&& (self.guild != GIL_STONEGOLEM) // и не Каменный голем
&& (self.guild != GIL_SUMMONED_GOLEM) // и не Вызванный голем
&& (self.guild != GIL_SWAMPSHARK) // и не Болотный голем
&& (self.guild != GIL_TROLL) // и не Троль
&& (!C_NpcIsEvil(self)) // и не источник зла
&& (C_NpcIsGateGuard(self) == FALSE) // и не охранник ворот
{
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
// если заклинание Уничтожить нежить
if(spellType == SPL_DestroyUndead)
{
// если НПС нежить и жизнь НПС <= урону заклинания
if(C_NpcIsUndead(self)) && (self.attribute[ATR_HITPOINTS_MAX] <= SPL_Damage_DESTROYUNDEAD)
{
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
// если заклинание Дым смерти
if(spellType == SPL_BreathOfDeath)
{
// если расстояние между НПС < 10м и НПС не нежить
if(Npc_GetDistToNpc(other,self) < 1000) && (!C_NpcIsUndead(self))
{
// если НПС дракон или НПС не ГГ
if(self.guild == GIL_DRAGON) || (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(hero))
{
return COLL_APPLYHALVEDAMAGE;
};
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
// если заклинание Волна смерти
if(spellType == SPL_MassDeath)
{
// если НПС не нежить
if(!C_NpcIsUndead(self))
{
// если НПС дракон
if(self.guild == GIL_DRAGON)
{
return COLL_APPLYHALVEDAMAGE;
};
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
// если заклинание Святой удар
if(spellType == SPL_MasterOfDisaster)
{
// если НПС не обездвижен и не плывет и не ныряет и нежить
if(!C_NpcIsDown(self)) && (!C_BodyStateContains(self,BS_SWIM)) && (!C_BodyStateContains(self,BS_DIVE)) && (C_NpcIsEvil(self))
{
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
// если заклинание Уменьшить монстра
if(spellType == SPL_Shrink)
{
// если НПС обездвижен или плывет или ныряет или дракон
if(C_NpcIsDown(self)) || (C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE)) || (self.guild == GIL_DRAGON)
{
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};
// если заклинание Святая стрела
if(spellType == SPL_PalHolyBolt)
{
// если НПС источник зла
if(C_NpcIsEvil(self))
{
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
}
// если заклинание Разогнать дьяволов
else if(spellType == SPL_PalRepelEvil)
{
// если НПС источник зла
if(C_NpcIsEvil(self))
{
// если жизнь НПС <= ущербу заклинания
if(self.attribute[ATR_HITPOINTS_MAX] <= SPL_Damage_PalRepelEvil)
{
return COLL_DOEVERYTHING;
}
else
{
return COLL_APPLYHALVEDAMAGE;
};
};
return COLL_DONOTHING;
}
// если заклинание Уничтожить дьяволов
else if(spellType == SPL_PalDestroyEvil)
{
// если НПС источник зла и жизнь НПС <= ущербу заклинания
if(C_NpcIsEvil(self)) && (self.attribute[ATR_HITPOINTS_MAX] <= SPL_Damage_PalDestroyEvil)
{
return COLL_DOEVERYTHING;
};
return COLL_DONOTHING;
};
return COLL_DOEVERYTHING;
};



//**************************************************************
//****************
// Управление процессом инвестирования маны для всех заклинаний
//------------------------------------------------------------------------------
// Данная функция вызывается только экзешником
// self - кастующий НПС (агрессор)
// other - НПС цель
//******************************************************************************
//=============================================================
// Аргументы:
//-------------------------------------------------------------
// manaInvested - кол-во инвестируемой маны
// -------------------------------------------------------------
// Возвращаемое значение:
// Одна из констант, управляющая процессом инвестирования маны.
// =============================================================


func int Spell_ProcessMana(var int manaInvested)
{
var int activeSpell;
// получить активное заклинание агрессора
activeSpell = Npc_GetActiveSpell(self);
// В зависимости от заклинания вызывается соответствующая функция, управляющая инвестированием маны
if(activeSpell == SPL_PalLight ) { return Spell_Logic_PalLight (manaInvested); };
if(activeSpell == SPL_PalLightHeal ) { return Spell_Logic_PalLightHeal (manaInvested); };
if(activeSpell == SPL_PalHolyBolt ) { return Spell_Logic_PalHolyBolt (manaInvested); };
if(activeSpell == SPL_PalMediumHeal ) { return Spell_Logic_PalMediumHeal (manaInvested); };
if(activeSpell == SPL_PalRepelEvil ) { return Spell_Logic_PalRepelEvil (manaInvested); };
if(activeSpell == SPL_PalFullHeal ) { return Spell_Logic_PalFullHeal (manaInvested); };
if(activeSpell == SPL_PalDestroyEvil ) { return Spell_Logic_PalDestroyEvil (manaInvested); };
if(activeSpell == SPL_PalTeleportSecret ) { return Spell_Logic_PalTeleportSecret(manaInvested); };
if(activeSpell == SPL_TeleportSeaport ) { return Spell_Logic_TeleportSeaport (manaInvested); };
if(activeSpell == SPL_TeleportMonastery ) { return Spell_Logic_TeleportMonastery(manaInvested); };
if(activeSpell == SPL_TeleportFarm ) { return Spell_Logic_TeleportFarm (manaInvested); };
if(activeSpell == SPL_TeleportXardas ) { return Spell_Logic_TeleportXardas (manaInvested); };
if(activeSpell == SPL_TeleportPassNW ) { return Spell_Logic_TeleportPassNW (manaInvested); };
if(activeSpell == SPL_TeleportPassOW ) { return Spell_Logic_TeleportPassOW (manaInvested); };
if(activeSpell == SPL_TeleportOC ) { return Spell_Logic_TeleportOC (manaInvested); };
if(activeSpell == SPL_TeleportOWDemonTower) { return Spell_Logic_TeleportOWDemonTower(manaInvested); };
if(activeSpell == SPL_TeleportTaverne ) { return Spell_Logic_TeleportTaverne (manaInvested); };
if(activeSpell == SPL_LIGHT ) { return Spell_Logic_Light (manaInvested); };
if(activeSpell == SPL_Firebolt ) { return Spell_Logic_Firebolt (manaInvested); };
if(activeSpell == SPL_Icebolt ) { return Spell_Logic_Icebolt (manaInvested); };
if(activeSpell == SPL_Zap ) { return Spell_Logic_Zap (manaInvested); };
if(activeSpell == SPL_LightHeal ) { return Spell_Logic_LightHeal (manaInvested); };
if(activeSpell == SPL_SummonGoblinSkeleton) { return Spell_Logic_SummonGoblinSkeleton(manaInvested); };
if(activeSpell == SPL_InstantFireball ) { return Spell_Logic_InstantFireball (manaInvested); };
if(activeSpell == SPL_SummonWolf ) { return Spell_Logic_SummonWolf (manaInvested); };
if(activeSpell == SPL_WINDFIST ) { return Spell_Logic_Windfist (manaInvested); };
if(activeSpell == SPL_Sleep ) { return Spell_Logic_Sleep (manaInvested); };
if(activeSpell == SPL_MediumHeal ) { return Spell_Logic_MediumHeal (manaInvested); };
if(activeSpell == SPL_LightningFlash ) { return Spell_Logic_LightningFlash (manaInvested); };
if(activeSpell == SPL_ChargeFireball ) { return Spell_Logic_ChargeFireball (manaInvested); };
if(activeSpell == SPL_ChargeZap ) { return Spell_Logic_ChargeZap (manaInvested); };
if(activeSpell == SPL_SummonSkeleton ) { return Spell_Logic_SummonSkeleton (manaInvested); };
if(activeSpell == SPL_Fear ) { return Spell_Logic_Fear (manaInvested); };
if(activeSpell == SPL_IceCube ) { return Spell_Logic_IceCube (manaInvested); };
if(activeSpell == SPL_ChargeZap ) { return Spell_Logic_ChargeZap (manaInvested); };
if(activeSpell == SPL_SummonGolem ) { return Spell_Logic_SummonGolem (manaInvested); };
if(activeSpell == SPL_DestroyUndead ) { return Spell_Logic_DestroyUndead (manaInvested); };
if(activeSpell == SPL_Pyrokinesis ) { return Spell_Logic_Pyrokinesis (manaInvested); };
if(activeSpell == SPL_Firestorm ) { return Spell_Logic_Firestorm (manaInvested); };
if(activeSpell == SPL_IceWave ) { return Spell_Logic_IceWave (manaInvested); };
if(activeSpell == SPL_SummonDemon ) { return Spell_Logic_SummonDemon (manaInvested); };
if(activeSpell == SPL_FullHeal ) { return Spell_Logic_FullHeal (manaInvested); };
if(activeSpell == SPL_Firerain ) { return Spell_Logic_Firerain (manaInvested); };
if(activeSpell == SPL_BreathOfDeath ) { return Spell_Logic_BreathOfDeath (manaInvested); };
if(activeSpell == SPL_MassDeath ) { return Spell_Logic_MassDeath (manaInvested); };
if(activeSpell == SPL_ArmyOfDarkness ) { return Spell_Logic_ArmyOfDarkness (manaInvested); };
if(activeSpell == SPL_Shrink ) { return Spell_Logic_Shrink (manaInvested); };
if(activeSpell == SPL_TrfSheep ) { return Spell_Logic_TrfSheep (manaInvested); };
if(activeSpell == SPL_TrfScavenger ) { return Spell_Logic_TrfScavenger (manaInvested); };
if(activeSpell == SPL_TrfGiantRat ) { return Spell_Logic_TrfGiantRat (manaInvested); };
if(activeSpell == SPL_TrfGiantBug ) { return Spell_Logic_TrfGiantBug (manaInvested); };
if(activeSpell == SPL_TrfWolf ) { return Spell_Logic_TrfWolf (manaInvested); };
if(activeSpell == SPL_TrfWaran ) { return Spell_Logic_TrfWaran (manaInvested); };
if(activeSpell == SPL_TrfSnapper ) { return Spell_Logic_TrfSnapper (manaInvested); };
if(activeSpell == SPL_TrfWarg ) { return Spell_Logic_TrfWarg (manaInvested); };
if(activeSpell == SPL_TrfFireWaran ) { return Spell_Logic_TrfFireWaran (manaInvested); };
if(activeSpell == SPL_TrfLurker ) { return Spell_Logic_TrfLurker (manaInvested); };
if(activeSpell == SPL_TrfShadowbeast ) { return Spell_Logic_TrfShadowbeast (manaInvested); };
if(activeSpell == SPL_TrfDragonSnapper ) { return Spell_Logic_TrfDragonSnapper(manaInvested); };
if(activeSpell == SPL_Charm ) { return Spell_Logic_Charm (manaInvested); };
if(activeSpell == SPL_MasterOfDisaster ) { return Spell_Logic_MasterOfDisaster(manaInvested); };
if(activeSpell == SPL_ConcussionBolt ) { return Spell_Logic_ConcussionBolt (manaInvested); };
if(activeSpell == SPL_Deathbolt ) { return Spell_Logic_Deathbolt (manaInvested); };
if(activeSpell == SPL_Deathball ) { return Spell_Logic_Deathball (manaInvested); };
if(activeSpell == SPL_Thunderstorm ) { return Spell_Logic_Thunderstorm (manaInvested); };
if(activeSpell == SPL_Waterfist ) { return Spell_Logic_Waterfist (manaInvested); };
if(activeSpell == SPL_Whirlwind ) { return Spell_Logic_Whirlwind (manaInvested); };
if(activeSpell == SPL_Geyser ) { return Spell_Logic_Geyser (manaInvested); };
if(activeSpell == SPL_Inflate ) { return Spell_Logic_Inflate (manaInvested); };
if(activeSpell == SPL_Icelance ) { return Spell_Logic_Icelance (manaInvested); };
if(activeSpell == SPL_Swarm ) { return Spell_Logic_Swarm (manaInvested); };
if(activeSpell == SPL_Greententacle ) { return Spell_Logic_Greententacle (manaInvested); };
if(activeSpell == SPL_SummonGuardian ) { return Spell_Logic_SummonGuardian (manaInvested); };
if(activeSpell == SPL_Energyball ) { return Spell_Logic_Energyball (manaInvested); };
if(activeSpell == SPL_SuckEnergy ) { return Spell_Logic_SuckEnergy (manaInvested); };
if(activeSpell == SPL_Skull ) { return Spell_Logic_Skull (manaInvested); };
if(activeSpell == SPL_SummonZombie ) { return Spell_Logic_SummonZombie (manaInvested); };
if(activeSpell == SPL_SummonMud ) { return Spell_Logic_SummonMud (manaInvested); };
return SPL_SENDSTOP; // (Моя коррекция)
};




//**************************************************************
//****************
//Управление процессом высвобождения инвестированной маны для заклинаний
//------------------------------------------------------------------------------
// Данная функция вызывается только экзешником
// self - кастующий НПС (агрессор)
//******************************************************************************


//=============================================================
// Аргументы:
//-------------------------------------------------------------
// manaInvested - кол-во высвобождаемой маны
//-------------------------------------------------------------
// Возвращаемое значение:
// Одна из констант, управляющая процессом инвестирования маны.
//=============================================================


func int Spell_ProcessMana_Release(var int manaInvested)
{
var int activeSpell;
// получить активное заклинание агрессора
activeSpell = Npc_GetActiveSpell(self);
// эти заклинания при освобождении маны всегда срабатывают
if (activeSpell == SPL_Pyrokinesis ) { return SPL_SENDCAST; };
if (activeSpell == SPL_ChargeFireball) { return SPL_SENDCAST; };
if (activeSpell == SPL_ChargeZap ) { return SPL_SENDCAST; };
if (activeSpell == SPL_WINDFIST ) { return SPL_SENDCAST; };
// все остальные заклинания завершаются без эффекта
return SPL_SENDSTOP;
};




// ******************************************************************
// Прототип всех заклинаний (значения по умолчанию)
// ******************************************************************


prototype C_Spell_Proto(c_spell)
{
time_per_mana = 500; // Время в мс, требуемое для инвестирования маны на один уровень - 500мс
damage_per_level = 1; // Наносимый урон за уровень заклинания - 1 пункт
damageType = DAM_MAGIC; // Тип повреждения - магия
spellType = SPELL_BAD; // Категория заклинания - плохое
canTurnDuringInvest = 1; // Возможность поворота во время инвестирования маны - есть
canChangeTargetDuringInvest = 1; // Возможность выбора цели во время инвестирования маны - есть
isMultiEffect = 0; // Возможность мультиэффектов заклинания - нет
targetCollectAlgo = TARGET_COLLECT_FOCUS_FALLBACK_NONE; // Константа описания цели - цель визуальный объект в фокусе, при потере фокуса траектория устанавливается заклинанием
targetCollectType = TARGET_TYPE_NPCS; // Тип цели заклинания - цель НПС
targetCollectRange = 10000; // Дальность действия - 100м
targetCollectAzi = 60; // Угол азимута - 60 градусов
targetCollectElev = 60; // Угол тангажа - 60 градусов
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
16. Заклинания.

Все файлы заклинаний расположены в директории ..\AI\Magic\Spells\
Все заклинания мы рассматривать не будем, разберем только основные типы и принципы работы.

Все заклинания состоят из следующих частей:
1. Объявление самого заклинания типа instance Spell_ххх(C_Spell_Proto) с инициализацией требуемых переменных, где ххх - название заклинания.
2. Функция, управляющая процессом инвестирования маны int Spell_Logic_ххх(var int manaInvested). Аргумент int manaInvested определяет кол-во инвестированной маны, функция возвращает одну из констант управления процессом инвестирования маны.
3. Функция вызова самого заклинания void Spell_Cast_ххх() (вызывается только экзешником). Имя ххх должно строго соответствовать ххх при объявлении инстанции.
// *******************************************
// Заклинание Свет
// *******************************************


const int SPL_Cost_LIGHT = 10; // кол-во требуемой маны

const int SPL_Duration_LIGHT = 5; // время действия заклинания в минутах

// объявление заклинания с инициализацией
instance Spell_Light(C_Spell_Proto)
{
time_per_mana = 500;
spelltype = SPELL_NEUTRAL;
targetCollectAlgo = TARGET_COLLECT_NONE;
targetCollectRange = 0;
targetCollectAzi = 0;
targetCollectElev = 0;
};

// функция инвестирования маны
func int Spell_Logic_Light(var int manaInvested)
{
// если активное заклинание свиток и есть требуемое кол-во маны
if(Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
// старт заклинания
return SPL_SENDCAST;
}
// иначе, если руна и есть требуемое кол-во маны
else if (self.attribute[ATR_MANA] >= SPL_Cost_Light)
{
// старт заклинания
return SPL_SENDCAST;
}
else // мало маны
{
// отмена заклинания
return SPL_SENDSTOP;
};
};

// вызов заклинания
func void Spell_Cast_Light()
{
// если свиток
if(Npc_GetActiveSpellIsScroll(self))
{
// уменьшение маны на стоимость свитков
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else // руна
{
// уменьшение маны на фактическую стоимость заклинания
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Light;
};
// изменить случайное число выбора заклинаний
self.aivar[AIV_SelectSpell] += 1;
};
По такому принципу работают большинство заклинаний, это:
SPL_PalLight //Святой свет, // файл Spell_Light_Alle.d
SPL_PalLightHeal //Малое лечение паладина // файл Spell_Heal_Alle.d
SPL_PalMediumHeal //Среднее лечение паладина
SPL_PalFullHeal //Сильное лечение паладина
SPL_LightHeal //Лечить легкое ранение
SPL_MediumHeal //Лечить среднее ранение
SPL_FullHeal //Лечить сильное ранение
SPL_PalHolyBolt //Святая стрела // файл Spell_PalHolyBolt.d
SPL_PalRepelEvil //Разогнать дьяволов // файл Spell_PalRepelEvil.d
SPL_PalDestroyEvil //Уничтожить дьяволов // файл Spell_PalDestroyEvil.d
SPL_Firebolt //Огненная стрела // файл Spell_FireBolt.d
SPL_Zap //Молния // файл Spell_Zap.d
SPL_Icebolt //Ледяная стрела // файл Spell_IceBolt.d
SPL_InstantFireball //Огненный шар // файл Spell_InstantFireball.d
SPL_LightningFlash //Удар молнии // файл Spell_LightningFlash.d
SPL_IceCube //Ледяная глыба // файл Spell_IceCube.d
SPL_DestroyUndead //Уничтожить нежить // файл Spell_DestroyUndead.d
SPL_Firestorm //Малая огненная буря // файл Spell_Firestorm.d
SPL_IceWave //Ледяная волна // файл Spell_IceWave.d
SPL_Firerain //Огненный дождь // файл Spell_Firerain.d
SPL_BreathOfDeath //Дым смерти // файл Spell_BreathOfDeath.d
SPL_MassDeath //Волна смерти // файл Spell_MassDeath.d
SPL_MasterOfDisaster //Святой удар // файл Spell_MasterOfDisaster.d
SPL_Deathbolt //Стрела смерти // файл Spell_DeathBolt.d
SPL_Deathball //Шар смерти // файл Spell_DeathBall.d
SPL_ConcussionBolt //Стрела сотрясения // файл Spell_ConcussionBolt.d
SPL_Thunderstorm //Шторм // файл Spell_Thunderstorm.d
SPL_Whirlwind //Смерч // файл Spell_Whirlwind.d
SPL_WaterFist //Кулак воды // файл Spell_WaterFist.d
SPL_IceLance //Ледяное копье // файл Spell_IceLance.d
SPL_Geyser //Гейзер // файл Spell_Geyser.d
SPL_Swarm //Рой // файл Spell_Swarm.d
SPL_GreenTentacle //Зеленые щупальца // файл Spell_GreenTentacle.d
SPL_Energyball //Шар энергии // файл Spell_EnergyBall.d
SPL_SuckEnergy //Украсть энергию // файл Spell_SuckEnergy.d
SPL_Skull //Крик мертвых // файл Spell_Skull.d
Телепортация.
// *************************
// Заклинания телепортации
// *************************

// стоимость заклинаний
const int SPL_Cost_Teleport = 10;

// Вывод сообщения о недоступности телепорта
// -------------------------------------------------------
// Level - уровень на котором находится телепорт прибытия

func void B_PrintTeleportTooFarAway(var int Level)
{
// если телепортация на другой уровень
if(Level != CurrentLevel)
{
// вывод сообщения "Слишком далеко"
PrintScreen(PRINT_TeleportTooFarAway,-1,YPOS_LevelUp,FONT_ScreenSmall,2);
};
};

// Инициализация заклинаний
instance Spell_Teleport(C_Spell_Proto)
{
time_per_mana = 0;
spelltype = SPELL_NEUTRAL;
targetCollectAlgo = TARGET_COLLECT_CASTER;
canTurnDuringInvest = 0;
targetCollectRange = 0;
targetCollectAzi = 0;
targetCollectElev = 0;
};

// Функции инвестирования маны для всех заклинаний телепортации идентичны ранее рассмотренной
func int Spell_Logic_PalTeleportSecret(var int manaInvested)
{
if (Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
return SPL_SENDCAST;
}
else if (self.attribute[ATR_MANA] >= SPL_Cost_Teleport)
{
return SPL_SENDCAST;
};
return SPL_NEXTLEVEL;
};

// Функции вызова заклинаний телепортации
func void Spell_Cast_PalTeleportSecret()
{
// вывод сообщения о недоступности телепорта
B_PrintTeleportTooFarAway(NEWWORLD_ZEN);
if (Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Teleport;
};
// телепортация в нужную точку
AI_Teleport(self,"NW_PAL_SECRETCHAMBER");
// анимация телепортации
AI_PlayAni(self,"T_HEASHOOT_2_STAND" );
};

// Остальные функции вызова заклинаний телепортации идентичны приведенной

// Вызов соответствующей функции телепортации в зависимости от активного заклинания
func void Spell_Cast_Teleport()
{
if (Npc_GetActiveSpell(self) == SPL_PalTeleportSecret ) { Spell_Cast_PalTeleportSecret (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportSeaport ) { Spell_Cast_TeleportSeaport (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportMonastery ) { Spell_Cast_TeleportMonastery (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportFarm ) { Spell_Cast_TeleportFarm (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportXardas ) { Spell_Cast_TeleportXardas (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportPassNW ) { Spell_Cast_TeleportPassNW (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportPassOW ) { Spell_Cast_TeleportPassOW (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportOC ) { Spell_Cast_TeleportOC (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportOWDemonTower) { Spell_Cast_TeleportOWDemonTower (); };
if (Npc_GetActiveSpell(self) == SPL_TeleportTaverne ) { Spell_Cast_TeleportTaverne (); };
};
Заклинания вызова монстров
Рассмотрим их на примере вызова Волка:
// **************
// Вызов Волка
// **************

// стоимость заклинания
const int SPL_Cost_SummonWolf = 40;

// Инициализация заклинания
instance Spell_SummonWolf(C_Spell_Proto)
{
time_per_mana = 0;
targetCollectAlgo = TARGET_COLLECT_NONE;
};

// Функция инвестирования маны идентична ранее рассмотренным
func int Spell_Logic_SummonWolf(var int manaInvested)
{
if(Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
return SPL_SENDCAST;
}
else if(self.attribute[ATR_MANA] >= SPL_Cost_SummonWolf)
{
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};

};

// Вызов заклинания
func void Spell_Cast_SummonWolf()
{
if(Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_SummonWolf;
};
// если заклинание применяет ГГ
if(Npc_IsPlayer(self))
{
// рождение Вызванного волка (1 штука на 5 минут)
Wld_SpawnNpcRange(self,Summoned_Wolf,1,500);
}
else
{
// рождение Волка
Wld_SpawnNpcRange(self,Wolf,1,500);
};
self.aivar[AIV_SelectSpell] += 1;
};
По такому принципу работают заклинания:
SPL_SummonGoblinSkeleton //Вызвать скелет гоблина // файл Spell_SummonGoblinSkeleton.d
SPL_SummonSkeleton //Вызвать скелет // файл Spell_SummonSkeleton.d
SPL_SummonGolem //Вызвать голема // файл Spell_SummonGolem.d
SPL_SummonDemon //Вызвать демона // файл Spell_SummonDemon.d
SPL_ArmyOfDarkness //Армия мрака // файл Spell_ArmyOfDarkness.d
SPL_SummonGuardian //Создать стража // файл Spell_SummonGuardian.d
SPL_SummonZombie //Создать зомби // файл Spell_SummonZombie.d
SPL_SummonMud //Вызвать Муда // файл Spell_SummonMud.d
Заклинания, требующие несколько уровней инвестирования маны
Рассмотрим их на примере заклинания "Порыв ветра":
// ************************
// Заклинание Порыв ветра
// ************************

const int SPL_Cost_WindFist = 80; // полная стоимость заклинания
const int STEP_WindFist = 20; // стоимость одного уровня заклинания
const int SPL_Damage_WindFist = 50; // ущерб наносимый заклинанием на уровень

// объявление заклинания с инициализацией
instance Spell_WindFist(C_Spell_Proto)
{
time_per_mana = 30;
damage_per_level = SPL_Damage_WindFist;
damageType = DAM_FLY;
canTurnDuringInvest = TRUE;
targetCollectAlgo = TARGET_COLLECT_FOCUS_FALLBACK_NONE;
targetCollectRange = 1000;
targetCollectType = TARGET_TYPE_NPCS;
};

// функция инвестирования маны
func int Spell_Logic_WindFist(var int manaInvested)
{
// если недостаточно маны на уровень заклинания
if(self.attribute[ATR_MANA] < STEP_WindFist)
{
// инвестирование маны невозможно
return SPL_DONTINVEST;
};
// если инвестировано маны < 1 уровня
if(manaInvested <= STEP_WindFist*1)
{
// установить уровень 1
self.aivar[AIV_SpellLevel] = 1;
// инвестированной маны недостаточно для перехода на следующий уровень
return SPL_STATUS_CANINVEST_NO_MANADEC;
}
// если инвестировано маны > требуемой для 1 уровня и уровень не выше первого
else if(manaInvested > (STEP_WindFist*1)) && (self.aivar[AIV_SpellLevel] <= 1)
{
// уменьшение маны на уровень
self.attribute[ATR_MANA] = (self.attribute[ATR_MANA] - STEP_WindFist);
// если мана < 0
if(self.attribute[ATR_MANA] < 0)
{
// мана = 0
self.attribute[ATR_MANA] = 0;
};
// установить уровень 2
self.aivar[AIV_SpellLevel] = 2;
// переход на следующий уровень
return SPL_NEXTLEVEL;
}
// аналогично приведенному выше для следующих уровней заклинания
else if(manaInvested > (STEP_WindFist*2)) && (self.aivar[AIV_SpellLevel] <= 2)
{
self.attribute[ATR_MANA] = (self.attribute[ATR_MANA] - STEP_WindFist);
if(self.attribute[ATR_MANA] < 0)
{
self.attribute[ATR_MANA] = 0;
};
self.aivar[AIV_SpellLevel] = 3;
return SPL_NEXTLEVEL;
}
else if(manaInvested > (STEP_WindFist*3)) && (self.aivar[AIV_SpellLevel] <= 3)
{
self.attribute[ATR_MANA] = (self.attribute[ATR_MANA] - STEP_WindFist);
if(self.attribute[ATR_MANA] < 0)
{
self.attribute[ATR_MANA] = 0;
};
self.aivar[AIV_SpellLevel] = 4;
return SPL_NEXTLEVEL;
}
// если достигнут последний уровень
else if(manaInvested > (STEP_WindFist*3)) && (self.aivar[AIV_SpellLevel] == 4)
{
// дальнейшее инвестирование маны невозможно
return SPL_DONTINVEST;
};
// инвестированной маны недостаточно для перехода на следующий уровень
return SPL_STATUS_CANINVEST_NO_MANADEC;
};

// вызов заклинания
// где spellLevel - достигнутый уровень заклинания

func void Spell_Cast_WindFist(var int spellLevel)
{
// уменьшение маны для последнего уровня
self.attribute[ATR_MANA] = (self.attribute[ATR_MANA] - STEP_WindFist);
if(self.attribute[ATR_MANA] < 0)
{
self.attribute[ATR_MANA] = 0;
};
// изменить случайное число выбора заклинаний
self.aivar[AIV_SelectSpell] += 1;
};
По такому принципу работают следующие заклинания:
SPL_ChargeFireball //Большой огненный шар // файл Spell_ChargeFireball.d
SPL_ChargeZap //Шаровая молния // файл Spell_ChargeZap.d
SPL_Pyrokinesis //Большая огненная буря // файл Spell_Pyrokinesis.d
Трансформация
// **************************
// Заклинания трансформации
// **************************

// стоимости заклинаний
const int SPL_Cost_TrfSheep = 10;
const int SPL_Cost_TrfScavenger = 10;
const int SPL_Cost_TrfGiantRat = 10;
const int SPL_Cost_TrfGiantBug = 10;
const int SPL_Cost_TrfWolf = 10;
const int SPL_Cost_TrfWaran = 10;
const int SPL_Cost_TrfSnapper = 10;
const int SPL_Cost_TrfWarg = 10;
const int SPL_Cost_TrfFireWaran = 10;
const int SPL_Cost_TrfLurker = 10;
const int SPL_Cost_TrfShadowbeast = 10;
const int SPL_Cost_TrfDragonSnapper = 10;

// общая инициализация для всех заклинаний
instance Spell_Transform(C_Spell_Proto)
{
time_per_mana = 0;
spelltype = SPELL_NEUTRAL;
targetCollectAlgo = TARGET_COLLECT_NONE;
canTurnDuringInvest = 0;
};

// Функции инвестирования маны у всех заклинаний трансформации практически одинаковы, рассмотрим одну их них
func int Spell_Logic_TrfSheep(var int manaInvested)
{
// если заклинание свиток и маны достаточно для свитка или маны достаточно для руны
if((Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll)))
|| (self.attribute[ATR_MANA] >= SPL_Cost_TrfSheep)
{
// уменьшить ману на стоимость заклинания для руны
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_TrfSheep;
// ссылка на объявление (инстанцию) зверюшки, в которую превращаемся
Npc_SetActiveSpellInfo(self,Sheep);
// старт заклинания
return SPL_SENDCAST;
}
else
{
// заклинание невозможно
return SPL_SENDSTOP;
};
};
Прочие заклинания
// ****************
// Заклинание Сон
// ****************

// self - кастующий НПС
// other - НПС цель


const int SPL_Cost_Sleep = 30; // стоимость маны
const int SPL_TIME_Sleep = 30; // время сна в сек

// Инициализация заклинания
instance Spell_Sleep(C_Spell_Proto)
{
time_per_mana = 0;
spelltype = SPELL_NEUTRAL;
targetCollectAlgo = TARGET_COLLECT_FOCUS;
};

// Функция инвестирования маны
func int Spell_Logic_Sleep(var int manaInvested)
{
// если заклинание свиток и маны достаточно для свитка или маны достаточно для руны
if((Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll)))
|| (self.attribute[ATR_MANA] >= SPL_Cost_Sleep)
{
// если свиток
if(Npc_GetActiveSpellIsScroll(self))
{
// израсходовать ману
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else // руна
{
// израсходовать ману
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Sleep;
};
// если цель не плывет и не ныряет и не обездвижена и
if (!C_BodyStateContains(other,BS_SWIM)) && (!C_BodyStateContains(other,BS_DIVE)) && (!C_NpcIsDown(other))
&& (other.guild < GIL_SEPERATOR_HUM) // человек
&& (other.flags != NPC_FLAG_IMMORTAL) // и уязвима
&& (Npc_GetDistToNpc(self,other) <= 1000) // и расстояние между кастующим и целью < 10м
&& (other.guild != GIL_KDF) // и цель не Маг огня
&& (other.guild != GIL_DMT) // и не Черный маг
&& (other.guild != GIL_PAL) // и не Паладин
{
// очистить очередь AI состояний цели
Npc_ClearAIQueue(other);
// очистить восприятия цели
B_ClearPerceptions(other);
// перевести цель в состояние Магического сна
AI_StartState(other,ZS_MagicSleep,0,"");
};
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};

// Вызов заклинания
func void Spell_Cast_Sleep()
{
// изменить случайное число выбора заклинаний
self.aivar[AIV_SelectSpell] += 1;
};



// *****************************
// Заклинание Уменьшить монстра
// *****************************

const int SPL_Cost_Shrink = 300; // стоимость маны

// Инициализация заклинания
instance Spell_Shrink(C_Spell_Proto)
{
time_per_mana = 0;
spelltype = SPELL_NEUTRAL;
targetCollectAlgo = TARGET_COLLECT_FOCUS;
targetCollectRange = 1000;
};

// Функция инвестирования маны (аналогична ранее рассмотренным)
func int Spell_Logic_Shrink(var int manaInvested)
{
if(Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
return SPL_SENDCAST;
}
else if(self.attribute[ATR_MANA] >= SPL_Cost_Shrink)
{
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};

// Вызов заклинания
func void Spell_Cast_Shrink()
{
// если свиток
if(Npc_GetActiveSpellIsScroll(self))
{
// израсходовать ману для свитка
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
// израсходовать ману для руны
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Shrink;
};
// если цель уязвима и не обездвижена и монстр и не уменьшена
if(other.flags != NPC_FLAG_IMMORTAL) && (!C_NpcIsUndead(other)) && (other.guild > GIL_SEPERATOR_HUM) && (other.aivar[AIV_MM_ShrinkState] == 0)
{
// очистить очередь AI состояний цели
Npc_ClearAIQueue(other);
// очистить восприятия цели
B_ClearPerceptions(other);
// перевести цель в состояние уменьшения
AI_StartState(other,ZS_MagicShrink,0,"");
};
// изменить случайное число выбора заклинаний
self.aivar[AIV_SelectSpell] += 1;
};




// *******************
// Заклинание Раздуть
// *******************

const int SPL_Cost_Inflate = 10; // стоимость маны
const int SPL_Inflate_Damage = 5; // ущерб от заклинания
const int SPL_TIME_Inflate = 19; // время действия 19 сек

// Инициализация заклинания
instance Spell_Inflate(C_Spell_Proto)
{
time_per_mana = 0;
targetCollectAlgo = TARGET_COLLECT_FOCUS;
};

// Функция инвестирования маны
func int Spell_Logic_Inflate(var int manaInvested)
{
// если заклинание свиток и маны достаточно для свитка или маны достаточно для руны
if ((Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll)))
|| (self.attribute[ATR_MANA] >= SPL_Cost_Inflate)
{
// если свиток
if(Npc_GetActiveSpellIsScroll(self))
{
// израсходовать ману для свитка
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
// израсходовать ману для руны
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Inflate;
};
// если цель не плывет и не ныряет и не обездвижена и
if(!C_BodyStateContains(other,BS_SWIM)) && (!C_BodyStateContains(other,BS_DIVE)) && (!C_NpcIsDown(other))
&& (other.guild < GIL_SEPERATOR_HUM) // человек
&& (other.flags != NPC_FLAG_IMMORTAL) // и уязвима
&& (Npc_GetDistToNpc(self,other) <= 1000) // и расстояние между кастующим и целью < 10м
&& (other.guild != GIL_KDF) // и цель не Маг огня
&& (other.guild != GIL_DMT) // и не Черный маг
&& (other.guild != GIL_PAL) // и не Паладин
{
// очистить очередь AI состояний цели
Npc_ClearAIQueue(other);
// очистить восприятия цели
B_ClearPerceptions(other);
// перевести цель в состояние Раздутия
AI_StartState(other,ZS_Inflate,0,"");
};
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};

// Вызов заклинания
func void Spell_Cast_Inflate()
{
// изменить случайное число выбора заклинаний
self.aivar[AIV_SelectSpell] += 1;
};




// ******************
// Заклинание Страх
// ******************

const int SPL_Cost_Fear = 50; // стоимость маны
const int SPL_TIME_Fear = 5; // время действия 5 сек

// Инициализация заклинания
instance Spell_Fear(C_Spell_Proto)
{
time_per_mana = 0;
damage_per_level = 0;
targetCollectAlgo = TARGET_COLLECT_NONE;
};

// Функция инвестирования маны (аналогична рассмотренным)
func int Spell_Logic_Fear(var int manaInvested)
{
if(Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
return SPL_SENDCAST;
}
else if(self.attribute[ATR_MANA] >= SPL_Cost_Fear)
{
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};

// Вызов заклинания
func void Spell_Cast_Fear()
{
// если цель не Дракон
if(other.guild != GIL_DRAGON)
{
// перевести всех НПС, находящихся на расстоянии 10м от кастующего, в состояние страха
AI_SetNpcsToState(self,ZS_MagicFlee,1000);
};
// израсходовать ману (аналогично рассмотренным заклинаниям)
if(Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Fear;
};
self.aivar[AIV_SelectSpell] += 1;
};




// ******************
// Заклинание Забыть
// ******************

const int SPL_Cost_Charm = 50; // стоимость маны
const int SPL_Damage_Charm = 0; // причиняемый ущерб

// Инициализация заклинания
instance Spell_Charm(C_Spell_Proto)
{
time_per_mana = 0;
spelltype = SPELL_NEUTRAL;
damage_per_level = SPL_Damage_Charm;
damageType = DAM_MAGIC;
};

// Функция инвестирования маны
func int Spell_Logic_Charm(var int manaInvested)
{
// если заклинание свиток и маны достаточно для свитка или маны достаточно для руны
if ((Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll)))
|| (self.attribute[ATR_MANA] >= SPL_Cost_Charm)
{
// если НПС цель видел криминал ГГ и квест Игназа в стадии выполнения
if(other.aivar[AIV_NpcSawPlayerCommit] != CRIME_NONE) && (MIS_Ignaz_Charm == LOG_RUNNING)
{
// тест заклинания проведен
Charm_Test = TRUE;
};
// удалить криминал ГГ для соответствующей локации
B_DeletePetzCrime(other);
// очистить что цель видела криминал
other.aivar[AIV_NpcSawPlayerCommit] = CRIME_NONE;
// последнего сражения с ГГ не было
other.aivar[AIV_LastFightAgainstPlayer] = FIGHT_NONE;
// если гильдии цели и кастующего не враги
if(Wld_GetGuildAttitude(other.guild,self.guild) != ATT_HOSTILE)
{
// если отношение цели и кастующего враждебно
if(Npc_GetAttitude(other,self) == ATT_HOSTILE)
{
// установить отношение цели к кастующему равное отношению их гильдий
Npc_SetTempAttitude(other,Wld_GetGuildAttitude(other.guild,self.guild));

};
};
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};

// Вызов заклинания (идентичен ранее рассмотренным)
func void Spell_Cast_Charm()
{
if(Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Charm;
};
self.aivar[AIV_SelectSpell] += 1;
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
17. Обработчики состояний заклинаний.

Все обработчики расположены в директории скриптов ..\AI\Magic\ZS_Magic в одноименных файлах.
//****************************************************
// Обработчик состояния заклинания Зеленые щупальца
//****************************************************

// ----------------------------------------------------
// self - жертва заклинания
// ----------------------------------------------------


// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartGreententacle()
{
// если последнее примененное заклинание Зеленые щупальца
if(Npc_GetLastHitSpellID(self) == SPL_Greententacle)
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
};
};

// Закончить действие заклинания
func void B_StopGreententacle()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если НПС человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_Greententacle()
{
// установить локальное восприятие на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartGreententacle);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_AssessDamage);
// остановить проигрывание файлов анимации заклинания
Npc_StopAni(self,"s_GreententacleA_Victim");
Npc_StopAni(self,"s_GreententacleB_Victim");
Npc_StopAni(self,"s_GreententacleC_Victim");
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp (self);
// если НПС находится не в бессознательном состоянии
if(!C_BodyStateContains(self,BS_UNCONSCIOUS))
{
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
var int randy;
//randy = Hlp_Random(3);
// проигрывается анимация бессознательного состояния (Примечание: т.к. предыдущая строка в скрипте закрыта, то randy всегда имеет значение 0)
if(randy == 0) { AI_PlayAniBS(self,"T_STAND_2_GREENTENTACLEA_VICTIM",BS_UNCONSCIOUS); };
if(randy == 1) { AI_PlayAniBS(self,"T_STAND_2_GREENTENTACLEB_VICTIM",BS_UNCONSCIOUS); };
if(randy == 2) { AI_PlayAniBS(self,"T_STAND_2_GREENTENTACLEC_VICTIM",BS_UNCONSCIOUS); };
}
else
{
// анимация бессознательного состояния
AI_PlayAniBS(self,"T_STAND_2_FREEZE_VICTIM",BS_UNCONSCIOUS);
};
};
};

// Функция цикла состояния
func int ZS_Greententacle_Loop ()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_Greententacle)
{
// остановить действие заклинания
B_StopGreententacle();
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_GreenTentacle_End()
{
}
;




// ****************************************
// Обработчик состояния заклинания Раздуть
// ****************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartInflate()
{
// если последнее примененное заклинание Раздуть
if(Npc_GetLastHitSpellID(self) == SPL_Inflate)
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
};
};

// Закончить действие заклинания
func void B_StopInflate()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_Inflate()
{
// установить локальное восприятие на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartInflate);
// остановить проигрывание файла анимации заклинания
Npc_StopAni(self,"S_INFLATE_VICTIM");
// если НПС находится не в бессознательном состоянии
if(!C_BodyStateContains(self,BS_UNCONSCIOUS))
{
// анимация бессознательного состояния
AI_PlayAniBS(self,"T_STAND_2_INFLATE_VICTIM",BS_UNCONSCIOUS);
};
// сброс времени цикла
self.aivar[AIV_InflateStateTime] = 0;
};

// Функция цикла состояния
func int ZS_Inflate_Loop ()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_Inflate)
{
// остановить действие заклинания
B_StopInflate();
return LOOP_END;
};
// если текущее время состояния не равно времени цикла
if(Npc_GetStateTime(self) != self.aivar[AIV_InflateStateTime])
{
// в зависимости от времени состояния установить жирность (объем) фигуры жертвы
// как видим по коэффициентам объема сначала идет раздутие фигуры, а затем возвращение к нормальному состоянию
if(Npc_GetStateTime(self) == 1) { Mdl_SetModelFatness(self,1); }
else if(Npc_GetStateTime(self) == 2) { Mdl_SetModelFatness(self,3); }
else if(Npc_GetStateTime(self) == 3) { Mdl_SetModelFatness(self,8 ); }
else if(Npc_GetStateTime(self) == 4) { Mdl_SetModelFatness(self,12); }
else if(Npc_GetStateTime(self) == 5)
{
Mdl_SetModelFatness(self,9);
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say(self,other,"$Aargh_1");
}
else if(Npc_GetStateTime(self) == 6) { Mdl_SetModelFatness (self,15); }
else if(Npc_GetStateTime(self) == 7) { Mdl_SetModelFatness (self,18 ); }
else if(Npc_GetStateTime(self) == 8 )
{
Mdl_SetModelFatness(self,11);
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say (self, other, "$Aargh_2");
}
else if(Npc_GetStateTime(self) == 9) { Mdl_SetModelFatness(self,15); }
else if(Npc_GetStateTime(self) == 10) { Mdl_SetModelFatness(self,13); }
else if(Npc_GetStateTime(self) == 11) { Mdl_SetModelFatness(self,12); }
else if(Npc_GetStateTime(self) == 12) { Mdl_SetModelFatness(self,10); }
else if(Npc_GetStateTime(self) == 13) { Mdl_SetModelFatness(self,8 ); }
else if(Npc_GetStateTime(self) == 14)
{
Mdl_SetModelFatness(self,5);
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say(self,other,"$Aargh_3");
}
else if(Npc_GetStateTime(self) == 15) { Mdl_SetModelFatness(self,6); }
else if(Npc_GetStateTime(self) == 16) { Mdl_SetModelFatness(self,4); }
else if(Npc_GetStateTime(self) == 17) { Mdl_SetModelFatness(self,2); }
else if(Npc_GetStateTime(self) == 18 ) { Mdl_SetModelFatness(self,1); }
else if(Npc_GetStateTime(self) == 19) { Mdl_SetModelFatness(self,1); };
// установить время уикла на текущее время
self.aivar[AIV_InflateStateTime] = Npc_GetStateTime(self);
// если жизнь жертвы > ущерба заклинания
if(self.attribute[ATR_HITPOINTS] > SPL_Inflate_DAMAGE)
{
// нанести ужерб жертве
B_MagicHurtNpc(other,self,SPL_Inflate_DAMAGE);
}
else
{
// нанести полный ужерб жертве (смерть)
B_MagicHurtNpc(other,self,self.attribute[ATR_HITPOINTS] - 1);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Inflate_End()
{
}
;




// ***********************************************************
// Обработчик состояния магического горения
// -----------------------------------------------------------

// В это состояние НПС переводится экзешником, а не скриптами
// ***********************************************************


// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


const int SPL_MAGICBURN_DAMAGE_PER_SEC = 1; // ущерб в сек от заклинания

// Закончить действие заклинания
func void B_StopMagicBurn()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
// продолжить распорядок дня НПС (т.к. не было принудительного перевода НПС в это состояние из скриптов и завершение этого состояния выполняется не из цикла состояния)
AI_ContinueRoutine(self);
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
// продолжить распорядок дня НПС
AI_ContinueRoutine(self);
};
};

// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartBurn()
{
// если последнее примененное заклинание
if (Npc_GetLastHitSpellID(self) == SPL_Firerain) // Огненный дождь
|| (Npc_GetLastHitSpellID(self) == SPL_ChargeFireball) // или Большой огненный шар
|| (Npc_GetLastHitSpellID(self) == SPL_InstantFireball) // или Огненный шар
|| (Npc_GetLastHitSpellID(self) == SPL_Firebolt) // или Огненная стрела
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
return;
};
// если последнее примененное заклинание
if (Npc_GetLastHitSpellID(self) == SPL_IceWave) // Ледяная волна
|| (Npc_GetLastHitSpellID(self) == SPL_IceCube) // или Ледяная глыба
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// очистить восприятия
B_ClearPerceptions(self);
// перевести жертву в состояние Магической заморозки
AI_StartState(self,ZS_MagicFreeze,0,"");
};
};

// Инициализация состояния
func void ZS_MagicBurn()
{
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopMagicBurn);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
};

// Функция цикла состояния
func int ZS_MagicBurn_Loop()
{
// разрешить локальное восприятие на воздействие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartBurn);
// если прошла 1 секунда
if(Npc_GetStateTime(self) == 1)
{
// сбросить время состояния
Npc_SetStateTime(self,0);
// нанести жертве секундный урон
B_MagicHurtNpc(other,self,SPL_MAGICBURN_DAMAGE_PER_SEC);
};
// если жизнь жертвы кончилась
if(self.attribute[ATR_HITPOINTS] <= 0)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicBurn_End()
{
}
;


// ****************************************************
// Обработчик состояния Короткого магического горения
// ****************************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


const int SPL_MAGICBURNSHORT_DAMAGE_PER_SEC = 1; // ущерб в сек от заклинания

// Закончить действие заклинания
func void B_StopMagicBurnShort()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
// продолжить распорядок дня НПС (т.к. завершение этого состояния выполняется не из цикла состояния)
AI_ContinueRoutine(self);
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
// продолжить распорядок дня НПС
AI_ContinueRoutine(self);
};
};

// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartBurnShort()
{
// если последнее примененное заклинание
if (Npc_GetLastHitSpellID(self) == SPL_ChargeFireball) // Большой огненный шар
|| (Npc_GetLastHitSpellID(self) == SPL_Firestorm) // или Малая огненная буря
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
return;
};
// если последнее примененное заклинание
if (Npc_GetLastHitSpellID(self) == SPL_IceWave) // Ледяная волна
|| (Npc_GetLastHitSpellID(self) == SPL_IceCube) // или Ледяная глыба
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// очистить восприятия
B_ClearPerceptions(self);
// перевести жертву в состояние Магической заморозки
AI_StartState(self,ZS_MagicFreeze,0,"");
};
};

// Инициализация состояния
func void ZS_MagicBurnShort()
{
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopMagicBurnShort);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp (self);
}
else
{
// НПС быстро встает
AI_StandUpQuick (self);
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// анимация горения
Npc_PlayAni(self,"S_FIRE_VICTIM");
};
};

// Функция цикла состояния
func int ZS_MagicBurnShort_Loop()
{
// разрешить локальное восприятие на воздействие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartBurnShort);
// если прошла 1 секунда
if(Npc_GetStateTime(self) == 1)
{
// сбросить время состояния
Npc_SetStateTime(self,0);
// нанести жертве секундный урон
B_MagicHurtNpc(other,self,SPL_MAGICBURNSHORT_DAMAGE_PER_SEC);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// анимация горения
Npc_PlayAni(self,"S_FIRE_VICTIM");
};
// если жизнь жертвы кончилась
if(self.attribute[ATR_HITPOINTS] <= 0)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicBurnShort_End()
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
};




// **************************************
// Обработчик состояния страха
// **************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Закончить действие заклинания
func void B_StopMagicFlee()
{
// запретить восприятие повреждений
Npc_PercDisable(self,PERC_ASSESSDAMAGE);
// восстановить other на агрессора
Npc_SetTarget(self,other);
// переход в состояние убегания от агрессора
AI_StartState(self,ZS_Flee,0,"");
};

// Инициализация состояния
func void ZS_MagicFlee ()
{
// если жертва Дракон
if(self.guild == GIL_DRAGON)
{
// продолжить распорядок дня НПС (нет реакции на магию)
AI_ContinueRoutine(self);
};
var int randy;
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_StopMagicFlee);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// сбросить статус предупреждений охраны
self.aivar[AIV_Guardpassage_Status] = GP_NONE;
// сбросить счетчик отказа от диалога
Npc_SetRefuseTalk(self,0);
// установить временное отношение между жертвой и ГГ равное постоянному
Npc_SetTempAttitude(self,Npc_GetPermAttitude(self,hero));
// НПС и ГГ перестают смотреть друг на друга
B_StopLookAt(self);
// НПС прекращает на что-либо указывать
AI_StopPointAt(self);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
randy = Hlp_Random (3);
// проигрывается анимация
if(randy == 0) { AI_PlayAniBS(self,"T_STAND_2_FEAR_VICTIM1",BS_STAND); };
if(randy == 1) { AI_PlayAniBS(self,"T_STAND_2_FEAR_VICTIM2",BS_STAND); };
if(randy == 2) { AI_PlayAniBS(self,"T_STAND_2_FEAR_VICTIM3",BS_STAND); };
};
};

// Функция цикла состояния
func int ZS_MagicFlee_Loop()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_Time_Fear)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// закончить действие обработчика
B_StopMagicFlee();
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicFlee_End()
{
}
;




// *******************************************
// Обработчик состояния Магической заморозки
// *******************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartFreeze()
{
// если последнее примененное заклинание
if (Npc_GetLastHitSpellID(self) == SPL_IceCube) // Ледяная глыба
|| (Npc_GetLastHitSpellID(self) == SPL_IceWave) // или Ледяная волна
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
};
};

// Закончить действие заклинания
func void B_StopMagicFreeze()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_MagicFreeze()
{
// разрешить локальное восприятие на воздействие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartFreeze);
// прекратить анимацию
Npc_StopAni(self,"S_FIRE_VICTIM");
// если состояние тела НПС не прерываемо
if(!C_BodyStateContains(self,BS_UNCONSCIOUS))
{
// анимация заморозки
AI_PlayAniBS(self,"T_STAND_2_FREEZE_VICTIM",BS_UNCONSCIOUS);
};
// сброс времени заморозки
self.aivar[AIV_FreezeStateTime] = 0;
};

// Функция цикла состояния
func int ZS_MagicFreeze_Loop()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_FREEZE)
{
// закончить действие обработчика
B_StopMagicFreeze();
return LOOP_END;
};
// если время в состоянии не равно времени заморозки
if(Npc_GetStateTime(self) != self.aivar[AIV_FreezeStateTime])
{
// время заморозки = времени состояния
self.aivar[AIV_FreezeStateTime] = Npc_GetStateTime(self);
// если жизнь жертвы > ущерба от заклинания
if(self.attribute[ATR_HITPOINTS] > (self.attribute[ATR_HITPOINTS] - SPL_FREEZE_DAMAGE))
{
// если жертва Огненный голем или
if (self.guild == GIL_FIREGOLEM)
|| (self.aivar[AIV_MM_REAL_ID] == ID_FIREWARAN) // Огненная ящерица
|| (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_FIRE) // или Огненный дракон
{
// нанести удвоенное повреждение в сек
B_MagicHurtNpc(other,self,SPL_FREEZE_DAMAGE*2);
return LOOP_CONTINUE;
};
// если жертва Ледяной голем или Ледяной дракон
if(self.guild == GIL_ICEGOLEM) || (self.aivar[AIV_MM_REAL_ID] == ID_DRAGON_ICE)
{
// нанести половинное порреждение в сек
B_MagicHurtNpc(other,self,SPL_FREEZE_DAMAGE/2);
return LOOP_CONTINUE;
};
// нанести обычное повреждение в сек
B_MagicHurtNpc(other,self,SPL_FREEZE_DAMAGE);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicFreeze_End()
{
}
;




// ***************************************
// Обработчик состояния Уменьшить монстра
// ***************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Инициализация состояния
func void ZS_MagicShrink()
{
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// сброс времени уменьшения
self.aivar[AIV_MM_ShrinkState] = 0;
};

// Функция цикла состояния
func int ZS_MagicShrink_Loop()
{
// за 13 секунд плавно уменьшить жертву
if (self.aivar[AIV_MM_ShrinkState] == 0) { Mdl_SetModelScale(self,0.90,0.90,0.90); self.aivar[AIV_MM_ShrinkState] = 1; }
else if(self.aivar[AIV_MM_ShrinkState] == 1) { Mdl_SetModelScale(self,0.85,0.85,0.85); self.aivar[AIV_MM_ShrinkState] = 2; }
else if(self.aivar[AIV_MM_ShrinkState] == 2) { Mdl_SetModelScale(self,0.80,0.80,0.80); self.aivar[AIV_MM_ShrinkState] = 3; }
else if(self.aivar[AIV_MM_ShrinkState] == 3) { Mdl_SetModelScale(self,0.75,0.75,0.75); self.aivar[AIV_MM_ShrinkState] = 4; }
else if(self.aivar[AIV_MM_ShrinkState] == 4) { Mdl_SetModelScale(self,0.70,0.70,0.70); self.aivar[AIV_MM_ShrinkState] = 5; }
else if(self.aivar[AIV_MM_ShrinkState] == 5) { Mdl_SetModelScale(self,0.65,0.65,0.65); self.aivar[AIV_MM_ShrinkState] = 6; }
else if(self.aivar[AIV_MM_ShrinkState] == 6) { Mdl_SetModelScale(self,0.60,0.60,0.60); self.aivar[AIV_MM_ShrinkState] = 7; }
else if(self.aivar[AIV_MM_ShrinkState] == 7) { Mdl_SetModelScale(self,0.55,0.55,0.55); self.aivar[AIV_MM_ShrinkState] = 8; }
else if(self.aivar[AIV_MM_ShrinkState] == 8) { Mdl_SetModelScale(self,0.50,0.50,0.50); self.aivar[AIV_MM_ShrinkState] = 9; }
else if(self.aivar[AIV_MM_ShrinkState] == 9) { Mdl_SetModelScale(self,0.45,0.45,0.45); self.aivar[AIV_MM_ShrinkState] = 10;}
else if(self.aivar[AIV_MM_ShrinkState] == 10) { Mdl_SetModelScale(self,0.40,0.40,0.40); self.aivar[AIV_MM_ShrinkState] = 11;}
else if(self.aivar[AIV_MM_ShrinkState] == 11) { Mdl_SetModelScale(self,0.35,0.35,0.35); self.aivar[AIV_MM_ShrinkState] = 12;}
else if(self.aivar[AIV_MM_ShrinkState] == 12) { Mdl_SetModelScale(self,0.30,0.30,0.30); self.aivar[AIV_MM_ShrinkState] = 13;}
// если жертва уменьшена
else if(self.aivar[AIV_MM_ShrinkState] == 13)
{
// уменьшить жизнь жертвы
Npc_ChangeAttribute(self,ATR_HITPOINTS,-((self.attribute[ATR_HITPOINTS]*9)/10));
// уменьшить макс. жизнь жертвы
Npc_ChangeAttribute(self,ATR_HITPOINTS_MAX,-((self.attribute[ATR_HITPOINTS_MAX]*9)/10));
// уменьшить силу жертвы
Npc_ChangeAttribute(self,ATR_STRENGTH,-((self.attribute[ATR_STRENGTH]*9)/10));
// уменьшить защиту от тупого оружия
self.protection[PROT_BLUNT] = self.protection[PROT_BLUNT]/10;
// уменьшить защиту от острого оружия
self.protection[PROT_EDGE] = self.protection[PROT_EDGE]/10;
// уменьшить защиту от огня
self.protection[PROT_FIRE] = self.protection[PROT_FIRE]/10;
// защита от нокаута = 0
self.protection[PROT_FLY] = 0;
// уменьшить защиту от магии
self.protection[PROT_MAGIC] = self.protection[PROT_MAGIC]/10;
// уменьшить защиту от тотечного оружия
self.protection[PROT_POINT] = self.protection[PROT_POINT]/10;
// переход на следующую фазу состояния
self.aivar[AIV_MM_ShrinkState] = 14;
}
// если достигнута последняя фаза состояния
else if(self.aivar[AIV_MM_ShrinkState] == 14)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// установить обработчик поведения в уменьшенном состоянии
self.start_aistate = ZS_MagicShrunk;
// переход в новый обработчик
AI_StartState(self,ZS_MagicShrunk,1,"");
return LOOP_END;
};
// задержка перед последней фазой состояния
AI_Wait(self,0.38 );
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicShrink_End()
{
}
;

// ********************************************
// Обработчик поведения уменьшенного монстра
// ********************************************

// Инициализация состояния
func void ZS_MagicShrunk()
{
// установить целью ГГ
Npc_SetTarget(self,hero);
};

// Функция цикла состояния
func int ZS_MagicShrunk_Loop()
{
// монстр убегает от ГГ
AI_Flee(self);
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicShrunk_End()
{
};


// **************************************
// Обработчик состояния Магический сон
// **************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Локальное восприятие повреждения (окончание действия заклинания)
func int B_StopMagicSleep()
{
// запретить восприятие повреждений
Npc_PercDisable(self,PERC_ASSESSDAMAGE);
// жертва говорит агрессору (SVM фраза) "(сам с собою, просыпаясь) Что это было!?" (Примечание: Ошибка слово $WHATWASSTHAT надо заменить на $WHATWASTHAT, а то фраза не будет сказана)
B_Say_Overlay(self,other,"$WHATWASSTHAT");
// анимация перехода в нормальное состояние
AI_PlayAni(self,"T_VICTIM_SLE_2_STAND");
};

// Локальное восприятие разговора
func void B_AssessMagicSleepTalk()
{
// жертва говорит агрессору (SVM фраза) "(просыпаясь) Черт, что случилось?"
B_Say(self,other,"$YOUDISTURBEDMYSLUMBER");
// жертва переходит в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,1,"");
};

// Инициализация состояния
func void ZS_MagicSleep()
{
// установить локальное восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_StopMagicSleep);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// установить локальное восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessMagicSleepTalk);
// Сбросить статус предупреждений охраной
self.aivar[AIV_Guardpassage_Status] = GP_NONE;
// сбросить счетчик отказа от диалога
Npc_SetRefuseTalk(self,0);
// установить временное отношение между жертвой и ГГ равное постоянному
Npc_SetTempAttitude(self,Npc_GetPermAttitude(self,hero));
// НПС и ГГ перестают смотреть друг на друга
B_StopLookAt(self);
// НПС прекращает на что-либо указывать
AI_StopPointAt(self);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// проигрывается анимация перехода в Магический сон
AI_PlayAniBS(self,"T_STAND_2_VICTIM_SLE",BS_LIE );
};

// Функция цикла состояния
func int ZS_MagicSleep_Loop()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_Time_Sleep)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// закончить действие обработчика
B_StopMagicSleep();
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_MagicSleep_End()
{
}
;




// ***********************************************************
// Обработчик состояния Большой огненной бури
// -----------------------------------------------------------

// В это состояние НПС переводится экзешником, а не скриптами
// ***********************************************************


// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Закончить действие заклинания
func void B_StopPyro()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
// продолжить распорядок дня НПС (т.к. не было принудительного перевода НПС в это состояние из скриптов и завершение этого состояния выполняется не из цикла состояния)
AI_ContinueRoutine(self);
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
// продолжить распорядок дня НПС
AI_ContinueRoutine(self);
};
};

// Инициализация состояния
func void ZS_Pyro()
{
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopPyro);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self, BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// проиграть анимацию входа в состояние
AI_PlayAni(self,"T_STAND_2_LIGHTNING_VICTIM");
};
};

// Функция цикла состояния
func int ZS_Pyro_Loop()
{
// если прошла 1 секунда
if(Npc_GetStateTime(self) >= 1)
{
// сбросить время состояния
Npc_SetStateTime(self,0);
// нанести жертве секундный урон
B_MagicHurtNpc(other,self,SPL_PYRO_DAMAGE_PER_SEC);
// если жизнь жертвы кончилась
if(self.attribute[ATR_HITPOINTS] <= 0)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Pyro_End()
{
}
;




// ************************************************
// Обработчик состояния реакции на Шаровую молнию
// ************************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Закончить действие заклинания
func void B_StopShortZapped()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
// продолжить распорядок дня НПС (т.к. завершение этого состояния выполняется не из цикла состояния)
AI_ContinueRoutine(self);
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
// продолжить распорядок дня НПС
AI_ContinueRoutine(self);
};
};

// Инициализация состояния
func void ZS_ShortZapped()
{
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopShortZapped);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// проиграть анимацию входа в состояние
AI_PlayAni(self,"T_STAND_2_LIGHTNING_VICTIM");
};
};

// Функция цикла состояния
func int ZS_ShortZapped_Loop()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_SHORTZAPPED)
{
// закончить действие обработчика
B_StopShortZapped();
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_ShortZapped_End()
{
}
;




// *************************************
// Обработчик состояния Украсть энергию
// *************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


var int Temp_SuckEnergy_DistToPlayer; // расстояние между жертвой и ГГ

// Функция реакции на локальное восприятие магии (заклинания)
func void B_RestartSuckEnergy()
{
// если последнее примененное заклинание Украсть энергию
if(Npc_GetLastHitSpellID(self) == SPL_SuckEnergy)
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
// анимация состояния
AI_PlayAni(self,"T_STAND_2_SUCKENERGY_VICTIM");
};
};

// Закончить действие заклинания
func void B_StopSuckEnergy()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_SuckEnergy()
{
// установить локальное восприятие на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartSuckEnergy);
// остановить проигрывание файла анимации заклинания
Npc_StopAni(self, "S_SUCKENERGY_VICTIM");
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// сброс времени цикла
self.aivar[AIV_SuckEnergyStateTime] = 1;
// запомнить расстояние между жертвой и ГГ
Temp_SuckEnergy_DistToPlayer = Npc_GetDistToPlayer(self);
};

// Функция цикла состояния
func int ZS_SuckEnergy_Loop()
{
// если время в состоянии > времени действия заклинания или расстояние между ГГ и жертвой увеличилось на более 10м
if(Npc_GetStateTime(self) > SPL_TIME_SuckEnergy) || (Temp_SuckEnergy_DistToPlayer >= Npc_GetDistToPlayer(self) + 100)
{
// остановить действие заклинания
B_StopSuckEnergy();
return LOOP_END;
};
// если текущее время состояния не равно времени цикла
if(Npc_GetStateTime(self) != self.aivar[AIV_SuckEnergyStateTime])
{
// если первая фаза состояния
if(Npc_GetStateTime(self) == 0)
{
// если состояние тела НПС не прерываемо
if(!C_BodyStateContains(self, BS_UNCONSCIOUS))
{
// анимация перехода в бессознательное состояние
AI_PlayAniBS(self,"T_STAND_2_SUCKENERGY_VICTIM",BS_UNCONSCIOUS);
};
// эффект высасывания энергии
Wld_PlayEffect("spellFX_SuckEnergy_BloodFly",self,hero,0,0,0,FALSE);
};
// обновить время цикла
self.aivar[AIV_SuckEnergyStateTime] = Npc_GetStateTime(self);
// если жизнь жертвы > ущерба от заклинания
if(self.attribute[ATR_HITPOINTS] > SPL_SuckEnergy_DAMAGE)
{
// нанести жертве урон
B_MagicHurtNpc(other,self,SPL_SuckEnergy_DAMAGE);
// добавить украденную жизнь агрессору
Npc_ChangeAttribute(other,ATR_HITPOINTS,SPL_SuckEnergy_DAMAGE);
}
else
{
// убить жертву
B_MagicHurtNpc(other,self,self.attribute[ATR_HITPOINTS] - 1);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_SuckEnergy_End()
{
}
;


// *************************************
// Обработчик состояния заклинания Рой
// *************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Функция реакции на локальное восприятие магии
func void B_RestartSwarm()
{
// если последнее примененное заклинание Рой
if(Npc_GetLastHitSpellID(self) == SPL_Swarm)
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
};
};

// Закончить действие заклинания
func void B_StopSwarm()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if (self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_Swarm()
{
// установить локальное восприятие на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartSwarm);
// остановить проигрывание файла анимации заклинания
Npc_StopAni(self,"S_SWARM_VICTIM");
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если состояние тела НПС не прерываемо
if(!C_BodyStateContains(self,BS_UNCONSCIOUS))
{
// анимация перехода в бессознательное состояние
AI_PlayAniBS(self,"T_STAND_2_SWARM_VICTIM",BS_UNCONSCIOUS);
};
// сброс времени цикла
self.aivar[AIV_SwarmStateTime] = 0;
};

// Функция цикла состояния
func int ZS_Swarm_Loop ()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_Swarm)
{
// остановить действие заклинания
B_StopSwarm();
return LOOP_END;
};
// если прошла 1 сек
if(Npc_GetStateTime(self) != self.aivar[AIV_SwarmStateTime])
{
// если жертва находится в состоянии 2 сек
if(Npc_GetStateTime(self) == 2)
{
// жертва говорит агрессору (SVM фраза) "Ах, черт!"
B_Say(self,other,"$RunAway");
}
// через 6 сек
else if(Npc_GetStateTime(self) == 6)
{
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say(self,other,"$Aargh_2");
}
// через 7 сек
else if(Npc_GetStateTime(self) == 7)
{
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say (self,other,"$Aargh_3");
}
// через 8 сек
else if(Npc_GetStateTime(self) == 8 )
{
// жертва говорит агрессору (SVM фраза) "Ууух!"
B_Say(self,other,"$Aargh_1");
};
// установить счетчик цикла на текущее время
self.aivar[AIV_SwarmStateTime] = Npc_GetStateTime(self);
// если жизнь жертвы > ущерба от заклинания
if(self.attribute[ATR_HITPOINTS] > SPL_Swarm_DAMAGE)
{
// нанести жертве урон
B_MagicHurtNpc(other,self,SPL_Swarm_DAMAGE);
}
else
{
// убить жертву
B_MagicHurtNpc(other,self,self.attribute[ATR_HITPOINTS] - 1);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Swarm_End()
{
}
;




// ******************************************
// Обработчик состояния заклинания Смерч
// ******************************************

// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Функция реакции на локальное восприятие магии
func void B_RestartWhirlwind()
{
// если последнее примененное заклинание Смерч
if(Npc_GetLastHitSpellID(self) == SPL_Whirlwind)
{
// сбросить время нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
};
};

// Закончить действие заклинания
func void B_StopWhirlwind()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
};
};

// Инициализация состояния
func void ZS_Whirlwind()
{
// установить локальное восприятие на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_RestartWhirlwind);
// остановить проигрывание файла анимации заклинания
Npc_StopAni(self,"S_WHIRLWIND_VICTIM");
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если состояние тела НПС не прерываемо
if(!C_BodyStateContains(self, BS_UNCONSCIOUS))
{
// анимация перехода в бессознательное состояние
AI_PlayAniBS(self,"T_STAND_2_WHIRLWIND_VICTIM",BS_UNCONSCIOUS);
};
// сброс счетчика цикла
self.aivar[AIV_WhirlwindStateTime] = 0;
};

// Функция цикла состояния
func int ZS_Whirlwind_Loop ()
{
// если время в состоянии > времени действия заклинания
if(Npc_GetStateTime(self) > SPL_TIME_WHIRLWIND)
{
// остановить действие заклинания
B_StopWhirlwind();
return LOOP_END;
};
// если прошла 1 сек
if(Npc_GetStateTime(self) != self.aivar[AIV_WhirlwindStateTime])
{
// установить счетчик цикла на текущее время
self.aivar[AIV_WhirlwindStateTime] = Npc_GetStateTime(self);
// если жизнь жертвы > ущерба от заклинания
if(self.attribute[ATR_HITPOINTS] > SPL_Whirlwind_DAMAGE)
{
// нанести жертве урон
B_MagicHurtNpc(other,self,SPL_Whirlwind_DAMAGE);
}
else
{
// убить жертву
B_MagicHurtNpc(other,self,self.attribute[ATR_HITPOINTS] - 1);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Whirlwind_End()
{
}
;




// ***********************************************************
// Обработчик состояния Удар молнии
// -----------------------------------------------------------

// В это состояние НПС переводится экзешником, а не скриптами
// ***********************************************************


// ----------------------------------------------------
// self - жертва заклинания
// other - кастующий НПС (агрессор)
// ----------------------------------------------------


// Закончить действие заклинания
func void B_StopZapped()
{
// возвратить общую функцию состояния реакции на магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// реакция НПС на повреждение
B_AssessDamage();
// продолжить распорядок дня НПС (т.к. не было принудительного перевода НПС в это состояние из скриптов и завершение этого состояния выполняется не из цикла состояния)
AI_ContinueRoutine(self);
}
else
{
// установить временно враждебное отношение НПС к ГГ
Npc_SetTempAttitude(self,ATT_HOSTILE);
// продолжить распорядок дня НПС
AI_ContinueRoutine(self);
};
};

// Инициализация состояния
func void ZS_Zapped()
{
// установить восприятие прекращения действия магии
Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopZapped);
// если состояние тела НПС не прерываемо
if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
{
// НПС встает
AI_StandUp(self);
}
else
{
// НПС быстро встает
AI_StandUpQuick(self);
};
// если жертва человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// включить анимацию действия заклинания
AI_PlayAni(self,"T_STAND_2_LIGHTNING_VICTIM");
};
};

// Функция цикла состояния
func int ZS_Zapped_Loop()
{
// если прошла 1 секунда
if(Npc_GetStateTime(self) >= 1)
{
// сбросить время состояния
Npc_SetStateTime(self,0);
// нанести жертве секундный урон
B_MagicHurtNpc(other,self,SPL_ZAPPED_DAMAGE_PER_SEC);
// если жизнь жертвы кончилась
if(self.attribute[ATR_HITPOINTS] <= 0)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Zapped_End()
{
}
;
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
18. Разные AI функции.

// ***********************************************
// Функция обновления снаряжения при респавне НПС
// -----------------------------------------------

// Вызывается только экзешником
// ***********************************************


// -----------------------------------------------
// self - возрождаемый НПС
// -----------------------------------------------


func void B_RefreshAtInsert()
{
// если НПС мертв
if(self.attribute[ATR_HITPOINTS] <= 0)
{
return;
};
var c_npc her;
// получить ссылку на ГГ
her = Hlp_GetNpc(PC_Hero);
// если НПС человек и НПС не ГГ
if(self.guild < GIL_SEPERATOR_HUM) && (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(her))
{
// установить текущую жизнь равной максимальной
self.attribute[ATR_HITPOINTS] = self.attribute[ATR_HITPOINTS_MAX];
// если НПС не имеет никакого оружия
if(Npc_HasEquippedWeapon(self) == FALSE)
{
// если НПС милиционер
if(self.guild == GIL_MIL)
{
// создать в инвентаре Тяжелую палку
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
};
// если НПС паладин
if(self.guild == GIL_PAL)
{
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
};
// если НПС наемник
if(self.guild == GIL_SLD)
{
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
};
// если НПС крестьянин
if(self.guild == GIL_BAU)
{
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
};
// если НПС маг послушник
if(self.guild == GIL_NOV)
{
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
};
};
};
};
Эта функция расположена в директории ..\AI\AI_Intern в одноименном файле.

// ***********************************************************
// Функция реплик НПС при обыскивании тел, когда нечего взять
// -----------------------------------------------------------

// Вызывается только экзешником
// ***********************************************************


// -----------------------------------------------
// self - обыскивающий НПС
// -----------------------------------------------


func void PLAYER_PLUNDER_IS_EMPTY()
{
var int rnd;
rnd = Hlp_Random(100);
// с вероятностью 0.4
if(rnd <= 40)
{
// напечатать текст по цетру экрана "здесь ничего нет..."
Print(PRINT_NOTHINGTOGET);
// произносится SVM фраза "Здесь нечего унести ..."
B_Say_Overlay(self,self,"$NOTHINGTOGET");
}
// с вероятностью 0.4
else if(rnd <= 80)
{
// напечатать текст по цетру экрана "Нечего унести..."
Print(PRINT_NOTHINGTOGET02);
// произносится SVM фраза "нечего унести ..."
B_Say_Overlay(self,self,"$NOTHINGTOGET02");
}
// с вероятностью 0.2
else if(rnd <= 99)
{
// напечатать текст по цетру экрана "Нечего грабить..."
Print(PRINT_NOTHINGTOGET03);
// произносится SVM фраза "нечего украсть ..."
B_Say_Overlay(self,self,"$NOTHINGTOGET03");
};
};
Эта функция расположена в директории ..\AI\AI_Intern в одноименном файле.

//**************************************************************
//*****
// Функция обновления доспехов НПС
// -------------------------------------------------------------------

// Вызывается только экзешником (пока пуста)
// *******************************************************************


func void B_RefreshArmor()
{
}
;
Эта функция расположена в директории ..\AI\Human в одноименном файле.

B_ функции монстров расположены в директории ..\AI\Monster\B_Monster
// ***********************************
// Функция задержки реакции монстров
// ***********************************


func void B_MM_DeSynchronize()
{
var int msec;
msec = Hlp_Random(1000);
// случайная задержка от 0 до 1 сек
AI_Waitms(self,msec);
};




// *******************************************
// Выполнение Огоньком заданий
// *******************************************

// ----------------------------------------------------
// self - Огонек
// item - предмет
// ----------------------------------------------------


// Реакция Огонька на найденный предмет
func void B_GetWispDetectedItem()
{
// если предмет не существует
if(!Hlp_IsValidItem(item))
{
return;
};
// если расстояние между Огоньком и предметом > 5м
if(Npc_GetHeightToItem(self,item) > 500)
{
return;
};
var int randy;
randy = Hlp_Random(100);
// Огонек движется к предмету
AI_GotoItem(self,item);
// если расстояние между Огоньком и предметом < 1м и вероятность <= 0.01
if(Npc_GetDistToItem(self,item) < 1000) && (randy <= 1)
{
// проигрывается анимация выкапывания предмета
Wld_PlayEffect("spellFX_ItemAusbuddeln",item,item,0,0,0,FALSE );
};
};

// Поиск Огоньком предметов
//----------------------------------------------------------------
// Возвращаемое значение: что нашел Огонек (в принципе не нужно)

func int B_WispDetectedItem()
{
// если Огонек ничего не ищет
if(WispSearching == WispSearch_Follow)
{
}
else // иначе (режим поиска)
{
var int WispSearchFlags;
// флаг поиска
WispSearchFlags = 0;
// если Огонек обучен искать оружие ближнего радиуса поражения и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_NF] == TRUE)
// (режим поиска - искать всё или оружие ближнего радиуса поражения)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_NF)))
{
// установить соответствующий флаг
WispSearchFlags = WispSearchFlags | ITEM_KAT_NF;
};
// если Огонек обучен искать оружие дальнего радиуса поражения и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_FF] == TRUE)
// (режим поиска - искать всё или оружие дальнего радиуса поражения)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_FF)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_FF | ITEM_KAT_MUN;
};
// если Огонек обучен искать деньги, ключи, предметы обихода и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_NONE] == TRUE)
// (режим поиска - искать всё или указанные вещи)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_NONE)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_NONE | ITEM_KAT_KEYS | ITEM_KAT_LIGHT | ITEM_KAT_ARMOR;
};
// если Огонек обучен искать руны и свитки и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_RUNE] == TRUE)
// (режим поиска - искать всё или указанные вещи)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_RUNE)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_RUNE | ITEM_KAT_DOCS;
};
// если Огонек обучен искать кольца и амулеты и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_MAGIC] == TRUE)
// (режим поиска - искать всё или указанные вещи)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_MAGIC)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_MAGIC;
};
// если Огонек обучен искать пропитание и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_FOOD] == TRUE)
// (режим поиска - искать всё или указанные вещи)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_FOOD)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_FOOD;
};
// если Огонек обучен искать напитки и
if ((PLAYER_TALENT_WISPDETECTOR[WISPSKILL_POTIONS] == TRUE)
// (режим поиска - искать всё или указанные вещи)
&& ((WispSearching == WispSearch_ALL) || (WispSearching == WispSearch_POTIONS)))
{
WispSearchFlags = WispSearchFlags | ITEM_KAT_POTIONS;
};
// если Огонек способен что-то найти
if(WispSearchFlags != 0)
{
// если найден предмет с указанными флагами
if(Wld_DetectItem(self,WispSearchFlags))
{
// реакция Огонька на найденный предмет
B_GetWispDetectedItem();
};
};
return WispSearchFlags;
};
return 0;
};

// Выполнение Огоньком заданий
func int B_MM_WispDetect()
{
// если self (вызванный монстр) есть Огонек
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Wisp_Detector))
{
// разрешить Огоньку воспринимать все объекты в зоне действия восприятия
Npc_PerceiveAll(self);
// если найден другой Огонек (other инициализирован Огоньком)
if(Wld_DetectNpc(self,Wisp_Detector,NOFUNC,-1)
{
// удалить Огонек
B_RemoveNpc(self);
};
// если расстояние между Огоньком и ГГ меньше 20м и установлен флаг близости
if(Npc_GetDistToNpc(self,hero) < 2000) && (self.aivar[AIV_TAPOSITION] == ISINPOS)
{
// сброс времени жизни монстра
self.aivar[AIV_SummonTime] = 0;
// выполнение поиска Огоньком
B_WispDetectedItem();
return LOOP_END;
}
else
{
// если расстояние между Огоньком и ГГ меньше 5м
if(Npc_GetDistToNpc(self,hero) < 500)
{
// установить флаг близости
self.aivar[AIV_TAPOSITION] = ISINPOS;
}
else
{
// установить флаг удаленности
self.aivar[AIV_TAPOSITION] = NOTINPOS;
// очистка очереди AI состояний Огонька
Npc_ClearAIQueue(self);
// Огонек движется к ГГ
AI_GotoNpc(self,hero);
};
return LOOP_END;
};
};
return LOOP_CONTINUE;
};
C_ функции монстров расположены в директории ..\AI\Monsrer\C_Monster
// ********************************************************************
// Является ли монстр магом
// ********************************************************************

// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый монстр
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_NpcIsMonsterMage(var c_npc slf)
{
// если монстр Маг скелетов или
if (slf.guild == GIL_SKELETON_MAGE)
|| (slf.guild == GIL_FIREGOLEM) // Огненный голем
|| (slf.guild == GIL_ICEGOLEM) // или Ледяной голем
|| (slf.guild == GIL_DRAGON) // или Дракон
{
return TRUE;
};
return FALSE;
};




// ********************************************************************************
//*****
// Устраивает ли монстра добыча в виде жертвы (на кого охотяться монстры)
// ********************************************************************************
//*****

// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый монстр (охотник)
// oth - НПС добыча
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_PredatorFoundPrey(var c_npc slf,var c_npc oth)
{
// если охотник волк, но не кабан
if(slf.guild == GIL_WOLF) && (slf.aivar[AIV_MM_REAL_ID] != ID_Keiler)
{
// если добыча овца
if(oth.guild == GIL_SHEEP) { return TRUE; };
// если добыча крыса
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
// если добыча кротокрыс
if(oth.guild == GIL_MOLERAT) { return TRUE; };
// если добыча падальщик, но не зубастик
if(oth.guild == GIL_SCAVENGER) && (oth.aivar[AIV_MM_REAL_ID] != ID_ORCBITER) { return TRUE; };
};
// если охотник шныг
if(slf.guild == GIL_LURKER)
{
// если добыча гоблин
if (oth.guild == GIL_GOBBO) { return TRUE; };
};
// если охотник глорх
if(slf.guild == GIL_SNAPPER)
{
// если добыча человек
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
// если добыча гоблин
if(oth.guild == GIL_GOBBO) { return TRUE; };
// если добыча овца
if(oth.guild == GIL_SHEEP) { return TRUE; };
// если добыча крыса
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
// если добыча кротокрыс
if(oth.guild == GIL_MOLERAT) { return TRUE; };
// если добыча падальщик, но не зубастик
if(oth.guild == GIL_SCAVENGER) && (oth.aivar[AIV_MM_REAL_ID] != ID_ORCBITER) { return TRUE; };
};
// если охотник мракорис
if(slf.guild == GIL_SHADOWBEAST)
{
// если добыча человек
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
// если добыча орк
if(oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
// если добыча овца
if(oth.guild == GIL_SHEEP) { return TRUE; };
// если добыча крыса
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
// если добыча кротокрыс
if(oth.guild == GIL_MOLERAT) { return TRUE; };
// если добыча падальщик, но не зубастик
if(oth.guild == GIL_SCAVENGER) && (oth.aivar[AIV_MM_REAL_ID] != ID_ORCBITER) { return TRUE; };
};
return FALSE;
};




// ***********************************
// Пожирает ли монстр труп добычи
// ***********************************

// ====================================================================
// Аргументы:
// --------------------------------------------------------------------
// slf - проверяемый монстр (охотник)
// oth - НПС добыча (труп)
// --------------------------------------------------------------------
// Возвращаемое значение:
// TRUE - да, FALSE - нет.
// ====================================================================


func int C_WantToEat(var c_npc slf,var c_npc oth)
{
// если монстр член партии ГГ
if(slf.aivar[AIV_PARTYMEMBER] == TRUE)
{
return FALSE;
};
// если охотник падальщик
if(slf.guild == GIL_SCAVENGER)
{
// если труп человек или орк
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if(oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
// если труп овца или полевые хищники
if(oth.guild == GIL_SHEEP) { return TRUE; };
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
if(oth.guild == GIL_MOLERAT) { return TRUE; };
// если труп гарпия
if(oth.guild == GIL_HARPY) { return TRUE; };
// если труп волки
if(oth.guild == GIL_WOLF) { return TRUE; };
if(oth.guild == GIL_SUMMONED_WOLF) { return TRUE; };
// если труп мракорис
if(oth.guild == GIL_SHADOWBEAST) { return TRUE; };
// если труп рептилий
if(oth.guild == GIL_GOBBO) { return TRUE; };
if(oth.guild == GIL_WARAN) { return TRUE; };
if(oth.guild == GIL_LURKER) { return TRUE; };
if(oth.guild == GIL_SNAPPER) { return TRUE; };
// в принципе здесь все понятно и без комментариев
if(oth.guild == GIL_MEATBUG) { return TRUE; };
if(oth.guild == GIL_GIANT_BUG) { return TRUE; };
if(oth.guild == GIL_BLOODFLY) { return TRUE; };
if(oth.guild == GIL_MINECRAWLER) { return TRUE; };
};
// если охотник крыса
if(slf.guild == GIL_GIANT_RAT)
{
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if(oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
if(oth.guild == GIL_SHEEP) { return TRUE; };
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
if(oth.guild == GIL_MOLERAT) { return TRUE; };
if(oth.guild == GIL_SCAVENGER) { return TRUE; };
if(oth.guild == GIL_HARPY) { return TRUE; };
if(oth.guild == GIL_WOLF) { return TRUE; };
if(oth.guild == GIL_SUMMONED_WOLF) { return TRUE; };
if(oth.guild == GIL_SHADOWBEAST) { return TRUE; };
if(oth.guild == GIL_GOBBO) { return TRUE; };
if(oth.guild == GIL_WARAN) { return TRUE; };
if(oth.guild == GIL_LURKER) { return TRUE; };
if(oth.guild == GIL_SNAPPER) { return TRUE; };
if(oth.guild == GIL_MEATBUG) { return TRUE; };
if(oth.guild == GIL_GIANT_BUG) { return TRUE; };
if(oth.guild == GIL_BLOODFLY) { return TRUE; };
if(oth.guild == GIL_MINECRAWLER) { return TRUE; };
};
// если охотник полевой жук
if(slf.guild == GIL_GIANT_BUG)
{
if(oth.guild == GIL_MEATBUG) { return TRUE; };
if(oth.guild == GIL_BLOODFLY) { return TRUE; };
if(oth.guild == GIL_MINECRAWLER) { return TRUE; };
};
// если охотник ящерица
if(slf.guild == GIL_WARAN)
{
if(oth.guild == GIL_SCAVENGER) { return TRUE; };
if(oth.guild == GIL_HARPY) { return TRUE; };
if(oth.guild == GIL_GOBBO) { return TRUE; };
};
// если охотник волк, но не кабан
if(slf.guild == GIL_WOLF) && (slf.aivar[AIV_MM_REAL_ID] != ID_Keiler)
{
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if(oth.guild == GIL_SHEEP) { return TRUE; };
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
if(oth.guild == GIL_MOLERAT) { return TRUE; };
};
// если охотник вызванный волк
if(slf.guild == GIL_SUMMONED_WOLF)
{
if(oth.guild == GIL_SHEEP) { return TRUE; };
if(oth.guild == GIL_GIANT_RAT) { return TRUE; };
if(oth.guild == GIL_MOLERAT) { return TRUE; };
};
// если охотник ползун
if(slf.guild == GIL_MINECRAWLER)
{
if(oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if(oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
if(oth.guild == GIL_MEATBUG) { return TRUE; };
if(oth.guild == GIL_GIANT_BUG) { return TRUE; };
if(oth.guild == GIL_BLOODFLY) { return TRUE; };
};
// если охотник шныг
if(slf.guild == GIL_LURKER)
{
if (oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if (oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
if (oth.guild == GIL_GOBBO) { return TRUE; };
};
// если охотник зомби
if (slf.guild == GIL_ZOMBIE)
{
if (oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if (oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
};
// если охотник глорх
if (slf.guild == GIL_SNAPPER)
{
if (oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if (oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
if (oth.guild == GIL_SHEEP) { return TRUE; };
if (oth.guild == GIL_GIANT_RAT) { return TRUE; };
if (oth.guild == GIL_MOLERAT) { return TRUE; };
if (oth.guild == GIL_SCAVENGER) { return TRUE; };
if (oth.guild == GIL_HARPY) { return TRUE; };
if (oth.guild == GIL_WOLF) { return TRUE; };
if (oth.guild == GIL_SUMMONED_WOLF) { return TRUE; };
if (oth.guild == GIL_SHADOWBEAST) { return TRUE; };
if (oth.guild == GIL_GOBBO) { return TRUE; };
if (oth.guild == GIL_WARAN) { return TRUE; };
if (oth.guild == GIL_LURKER) { return TRUE; };
};
// если охотник мракорис
if (slf.guild == GIL_SHADOWBEAST)
{
if (oth.guild < GIL_SEPERATOR_HUM) { return TRUE; };
if (oth.guild > GIL_SEPERATOR_ORC) { return TRUE; };
if (oth.guild == GIL_SHEEP) { return TRUE; };
if (oth.guild == GIL_GIANT_RAT) { return TRUE; };
if (oth.guild == GIL_MOLERAT) { return TRUE; };
if (oth.guild == GIL_SCAVENGER) { return TRUE; };
if (oth.guild == GIL_HARPY) { return TRUE; };
if (oth.guild == GIL_WOLF) { return TRUE; };
if (oth.guild == GIL_SUMMONED_WOLF) { return TRUE; };
if (oth.guild == GIL_GOBBO) { return TRUE; };
if (oth.guild == GIL_WARAN) { return TRUE; };
if (oth.guild == GIL_LURKER) { return TRUE; };
if (oth.guild == GIL_SNAPPER) { return TRUE; };
};
return FALSE;
};
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.160
Благодарности
6.141
Баллы
1.565
19. Обработчики состояний функций распорядка дня для людей.

Все обработчики расположены в директории ..\AI\Human\TA_Human
// ******************************************
// Объявления Герольда
// ------------------------------------------

// self - герольд, hero - ГГ
// ******************************************


// Функция инициализации состояния
func void ZS_Announce_Herold()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// разрешить восприятие тихих звуков (шаги, звон падающего предмета)
Npc_PercDisable(self,PERC_ASSESSQUIETSOUND);
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// выравнивание на вайпоинте
AI_AlignToWP(self);
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Announce_Herold_loop()
{
// если время цикла > 70 сек и ГГ ни с кем не разговаривает
if(Npc_GetStateTime(self) >= 70) && (hero.aivar[AIV_INVINCIBLE] == FALSE)
{
// анимация перехода в состояние чтения
AI_PlayAni(self,"T_HGUARD_2_STAND");
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
// зачитывание приказов
B_Announce_Herold();
// сброс времени цикла
Npc_SetStateTime(self, 0);
};
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// анимация перехода в обычное состояние
AI_PlayAni (self,"T_STAND_2_HGUARD");
// установка флага
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Announce_Herold_end()
{
}
;




// ***************************************
// Обработчик поведения бандита
// ***************************************

// Функция инициализации состояния
func void ZS_Bandit()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между бандитом и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Bandit_loop()
{
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// если бандит не у костра и костер имеется (Примечание: "костер" это ближайший свободный фрипоинт с именем FP_CAMPFIRE_xx, в дальнейшем буду использовать только сокращенное описание)
if(!Npc_IsOnFP(self,"CAMPFIRE")) && (Wld_IsFPAvailable(self,"CAMPFIRE"))
{
// бандит идет к костру
AI_GotoFP(self,"CAMPFIRE");
// выравнивается
AI_AlignToFP(self);
// садится
AI_PlayAniBS(self,"T_STAND_2_SIT",BS_SIT);
}
// если бандит не на своем месте и место имеется (свободно)
else if(!Npc_IsOnFP(self,"STAND")) && (Wld_IsFPAvailable(self,"STAND"))
{
// бандит идет к месту
AI_GotoFP(self,"STAND");
// выравнивается
AI_AlignToFP(self);
// охраняет
AI_PlayAni(self,"T_STAND_2_HGUARD");
}
else // иначе
{
// выравнивается
AI_AlignToWP(self);
// охраняет
AI_PlayAni(self,"T_STAND_2_HGUARD");
};
// установка флага
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// если прошло 5 сек и флаг установлен и бандит не сидит
if(Npc_GetStateTime(self) > 5) && (self.aivar[AIV_TAPOSITION] == ISINPOS) && (!C_BodyStateContains(self,BS_SIT))
{
var int random;
random = Hlp_Random(3);
// с вероятностью 0.33
if(random == 0)
{
// анимация осмотра
AI_PlayAni(self,"T_HGUARD_LOOKAROUND");
};
// сброс времени цикла
Npc_SetStateTime (self, 0);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Bandit_end()
{
// если бандит сидит
if(C_BodyStateContains(self,BS_SIT))
{
// встает
AI_PlayAniBS(self,"T_SIT_2_STAND",BS_STAND);
}
else // иначе
{
// просто стоит
AI_PlayAni(self,"T_HGUARD_2_STAND");
};
};



// ************************************
// Обработчик ритуала в Круге солнца
// ************************************

// Функция инициализации состояния
func void ZS_Circle()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить время реакции на восприятия 0.3 сек
Npc_SetPercTime(self,0.3);
// НПС встает
AI_StandUp(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// движение в Круг солнца
AI_GotoWP(self,self.wp);
// выравнивание
AI_AlignToWP(self);
};

// Функция цикла состояния
func int ZS_Circle_Loop ()
{
var int randy;
var int randyKDW;
var int randyKDW_Lightstar;
// если НПС черный маг
if(self.guild == GIL_DMT)
{
randy = Hlp_Random(3000);
// случайное время
if(Npc_GetStateTime(self) > randy)
{
// анимация "Дрожь земли"
Wld_PlayEffect("FX_EarthQuake",self,self,0,0,0,FALSE);
// сброс времени цикла
Npc_SetStateTime(self,0);
// анимация красного экрана
Wld_PlayEffect("spellFX_INCOVATION_RED",self,self,0,0,0,FALSE);
// упражнение в магии
AI_PlayAni(self,"T_PRACTICEMAGIC5");
};
}
// если НПС маг воды
else if(self.guild == GIL_KDW)
{
randyKDW = Hlp_Random(2500);
randyKDW_Lightstar= Hlp_Random(2);
// случайное время
if(Npc_GetStateTime(self) > randyKDW)
{
// выравнивание
AI_AlignToWP(self);
// сброс времени цикла
Npc_SetStateTime(self,0);
// анимация "Дрожь земли"
Wld_PlayEffect("FX_EarthQuake",self,self,0,0,0,FALSE );
// упражнение в магии
AI_PlayAni(self,"T_PRACTICEMAGIC5");
// далее какие-то эффекты, кто знает, что делают маги воды в Круге солнца, может написать
Wld_PlayEffect("spellFX_RingRitual2",ItMi_AmbossEffekt_Addon,ItMi_AmbossEffekt_Addon,0,0,0,FALSE);
if(randyKDW_Lightstar == 0)
{
Wld_PlayEffect("spellFX_RingRitual1",ItMi_AmbossEffekt_Addon,ItMi_AmbossEffekt_Addon,0,0,0,FALSE);
}
else if(randyKDW_Lightstar == 1)
{
Wld_PlayEffect("spellFX_LIGHTSTAR_RingRitual",ItMi_AmbossEffekt_Addon,ItMi_AmbossEffekt_Addon,0,0,0,FALSE);
};
};
}
// если квест по восстановлению Глаза Инноса не завершен
else if(MIS_RitualInnosEyeRepair != LOG_SUCCESS)
{
randy = Hlp_Random(1000);
// случайное время
if(Npc_GetStateTime(self) > randy)
{
// сброс времени цикла
Npc_SetStateTime(self,0);
// анимация "Дрожь земли"
Wld_PlayEffect("FX_EarthQuake",self,self,0,0,0,FALSE);
// упражнение в магии
AI_PlayAni(self,"T_PRACTICEMAGIC5");
// если НПС Ксардас
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Xardas))
{
// анимация фиолетового экрана
Wld_PlayEffect("spellFX_INCOVATION_VIOLET",self,self,0,0,0,FALSE);
}
// если НПС Пирокар
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Pyrokar))
{
// анимация красного экрана
Wld_PlayEffect("spellFX_INCOVATION_RED",self,self,0,0,0,FALSE);
}
else // иначе Ватрас
{
// анимация голубого экрана
Wld_PlayEffect("spellFX_INCOVATION_BLUE",self,self,0,0,0,FALSE);
};
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Circle_End()
{
}
;




// ***************************************
// Обработчик концерта InExtremo в аддоне
// ***************************************

// Функция инициализации состояния
func void ZS_Concert()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if (Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Concert_Loop ()
{
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// если НПС "Yellow Pfeiffer"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1394_Addon_InExtremo_YellowPfeiffer))
{
// использует Желтую волынку
AI_UseItemToState(self,ItMi_IEDudelGelb,1);
}
// если НПС "Dr. Pymonte"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1390_Addon_InExtremo_DrPymonte))
{
// использует Арфу
AI_UseItemToState(self,ItMi_IEHarfe,1);
}
// если НПС "The Flail"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1391_Addon_InExtremo_TheFlail))
{
// использует Drum
AI_UseItemToState(self,ItMi_iedrum,1);
}
// если НПС "Thomas the forger"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1392_Addon_InExtremo_ThomasTheForger))
{
// использует Виолончель
AI_UseItemToState(self,ItMi_IECello,1);
}
// если НПС "Unicorn"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1393_Addon_InExtremo_Unicorn))
{
// использует Лютню
AI_UseItemToState(self,ItMi_IELaute,1);
}
// если НПС "Lutter"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1395_Addon_InExtremo_Lutter))
{
// использует Drumscheit
AI_UseItemToState(self,ItMi_IEDrumscheit,1);
}
// если НПС "Flex"
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1396_Addon_InExtremo_Flex))
{
// использует Голубую волынку
AI_UseItemToState(self,ItMi_IEDudelBlau,1);
}
else
{
// Танцы пиратов?
};
// установка флага
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Concert_End()
{
// шестерка музыкантов, кроме Flexа, убирают свои инструменты
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1394_Addon_InExtremo_YellowPfeiffer))
{
AI_UseItemToState(self,ItMi_IEDudelGelb,-1);
}
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1390_Addon_InExtremo_DrPymonte))
{
AI_UseItemToState(self,ItMi_IEHarfe,-1);
}
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1391_Addon_InExtremo_TheFlail))
{
AI_UseItemToState(self,ItMi_iedrum,-1);
}
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1392_Addon_InExtremo_ThomasTheForger))
{
AI_UseItemToState(self,ItMi_IECello,-1);
}
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1393_Addon_InExtremo_Unicorn))
{
AI_UseItemToState(self,ItMi_IELaute,-1);
}
else if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PIR_1395_Addon_InExtremo_Lutter))
{
AI_UseItemToState(self,ItMi_IEDrumscheit,-1);
};
};


// ***************************************
// Обработчик приготовления пищи в котле
// ***************************************

// Функция инициализации состояния
func void ZS_Cook_Cauldron()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет ложки
if(Npc_HasItems(self,ItMi_Scoop) == 0)
{
// создать в инвентаре НПС ложку
CreateInvItem(self,ItMi_Scoop);
};
};

// Функция цикла состояния
func int ZS_Cook_Cauldron_Loop()
{
// если действие с МОВом не прерываемо и котел имеется
if(!C_BodyStateContains(self,BS_MOBINTERACT_INTERRUPT)) && (Wld_IsMobAvailable(self,"CAULDRON"))
{
// мешать ложкой в котле
AI_UseMob(self,"CAULDRON",1);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Cook_Cauldron_End()
{
// прекратить использовать котел
AI_UseMob(self,"CAULDRON",-1);
};




// *******************************************
// Обработчик приготовления пищи на сковороде
// *******************************************

// Функция инициализации состояния
func void ZS_Cook_Pan()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет Сырого мяса
if(Npc_HasItems(self,ItFoMuttonRaw) == 0)
{
// создать в инвентаре НПС Сырое мясо
CreateInvItem(self,ItFoMuttonRaw);
};
};

// Функция цикла состояния
func int ZS_Cook_Pan_Loop()
{
// если действие с МОВом не прерываемо и сковорода имеется
if(!C_BodyStateContains(self,BS_MOBINTERACT_INTERRUPT)) && (Wld_IsMobAvailable(self,"PAN"))
{
// жарить мясо
AI_UseMob(self,"PAN",1);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Cook_Pan_End()
{
// прекратить использовать котел
AI_UseMob(self,"PAN",-1);
// съесть жареное мясо
AI_UseItem(self,ItFoMutton);
};




// *************************************
// Обработчик приготовления пищи в печи
// *************************************

// Функция инициализации состояния
func void ZS_Cook_Stove()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет Сырого мяса
if(Npc_HasItems(self,ItFoMuttonRaw) == 0)
{
// создать в инвентаре НПС Сырое мясо
CreateInvItem(self,ItFoMuttonRaw);
};
};

// Функция цикла состояния
func int ZS_Cook_Stove_Loop()
{
// если действие с МОВом не прерываемо и печь имеется
if(!C_BodyStateContains(self,BS_MOBINTERACT_INTERRUPT)) && (Wld_IsMobAvailable(self,"STOVE"))
{
// жарить мясо
AI_UseMob(self,"STOVE",1);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Cook_Stove_End()
{
// прекратить использовать печь
AI_UseMob(self,"STOVE",-1);
// если НПС имеет больше 1 куска жареного мяса
if(Npc_HasItems(self,ItFoMutton) >=1 )
{
// удалить из инветаря НПС 1 кусок жареного мяса
Npc_RemoveInvItems(self,ItFoMutton,1);
};
};




// ***********************
// Обработчик танцев НПС
// ***********************

// Функция инициализации состояния
func void ZS_Dance()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// выравнивание
AI_AlignToWP(self);
};
};

// Функция цикла состояния
func int ZS_Dance_Loop()
{
var int danceStyle;
danceStyle = Hlp_Random(9);
// случайная анимация фаз танца
if(danceStyle == 0)
{
AI_PlayAni(self,"T_DANCE_01");
};
if(danceStyle == 1)
{
AI_PlayAni(self,"T_DANCE_02");
};
if(danceStyle == 2)
{
AI_PlayAni(self,"T_DANCE_03");
};
if(danceStyle == 3)
{
AI_PlayAni(self,"T_DANCE_04");
};
if(danceStyle == 4)
{
AI_PlayAni(self,"T_DANCE_05");
};
if(danceStyle == 5)
{
AI_PlayAni(self,"T_DANCE_06");
};
if(danceStyle == 6)
{
AI_PlayAni(self,"T_DANCE_07");
};
if(danceStyle == 7)
{
AI_PlayAni(self,"T_DANCE_08");
};
if(danceStyle == 8 )
{
AI_PlayAni(self,"T_DANCE_09");
};
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// выравнивание
AI_AlignToWP(self);
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Dance_End()
{
// танцор останавливается
AI_StandUp(self);
};




// **************************************
// Обработчик убегания НПС на свою точку
// **************************************

// Функция инициализации состояния
func void ZS_FleeToWp()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// если НПС Корнелиус
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Cornelius))
{
// закрыть восприятие входа в помещение
Npc_PercDisable(self,PERC_ASSESSENTERROOM);
};
// установить режим передвижения бегом
AI_SetWalkmode(self,NPC_RUN);
// включить модель убегающего человека
Mdl_ApplyOverlayMds(self,"HUMANS_FLEE.MDS");
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP (self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// выравнивание
AI_AlignToWP(self);
// анимация состояния охраны
AI_PlayAni(self,"T_STAND_2_HGUARD");
};

// Функция цикла состояния
func int ZS_FleeToWp_Loop()
{
// если время в состоянии > 5 сек
if(Npc_GetStateTime(self) > 5)
{
var int random;
random = Hlp_Random(2);
// с вероятностью 0.5
if(random == 0)
{
// осмотреть окресности
AI_PlayAni(self,"T_HGUARD_LOOKAROUND");
};
// сброс времени состояния
Npc_SetStateTime(self,0);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func int ZS_FleeToWp_End()
{
};


// *********************************
// Обработчик следования НПС за ГГ
// *********************************

// Функция локального восприятия НПС на ГГ
func void B_AssessFollowPlayer()
{
// если НПС Диего в Минентале
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(DiegoOW))
{
// расстояние между НПС и ГГ < дистанции следования и флаг сброшен (НПС движется)
if(Npc_GetDistToNpc(self,hero) < self.aivar[AIV_FollowDist]) && (self.aivar[AIV_TAPOSITION] == FALSE)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает (ждет действий ГГ)
AI_StandUp(self);
// установить флаг (НПС остановился)
self.aivar[AIV_TAPOSITION] = TRUE;
}
// если Диего слишком далеко и флаг сброшен
else if(C_DiegoTooFar(0)) && (self.aivar[AIV_TAPOSITION] == FALSE)
{
// очистить очередь AI состояний Диего
Npc_ClearAIQueue(self);
// Диего встает (ждет действий ГГ)
AI_StandUp(self);
// установить флаг
self.aivar[AIV_TAPOSITION] = TRUE;
// если расстояние между Диего и ГГ > дистанции начала разговора
if(Npc_GetDistToNpc(self,hero) > PERC_DIST_DIALOG)
{
// Диего говорит ГГ (SVM фраза) "Подожди!" (Примечание: правильней other заменить на hero)
B_Say(self,other,"$SC_HEYWAITASECOND");
};
}
else // иначе
{
// обычная реакция НПС на ГГ
B_AssessPlayer();
};
return;
};
// расстояние между НПС и ГГ < дистанции следования и флаг сброшен
if(Npc_GetDistToNpc(self,hero) < self.aivar[AIV_FollowDist]) && (self.aivar[AIV_TAPOSITION] == FALSE)
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает (ждет действий ГГ)
AI_StandUp(self);
// установить флаг
self.aivar[AIV_TAPOSITION] = TRUE;
}
else
{
// обычная реакция НПС на ГГ
B_AssessPlayer();
};
};

// Функция локального восприятия НПС на звук сражения
func void B_AssessFollowFightSound()
{
// если other (нападающий) есть ГГ или victim (жертва) есть ГГ или
if(Npc_IsPlayer(other)) || (Npc_IsPlayer(victim))
|| (other.aivar[AIV_PARTYMEMBER] == TRUE) // other - член партии ГГ
|| (victim.aivar[AIV_PARTYMEMBER] == TRUE) // или victim - член партии ГГ
{
// обычная реакция НПС на звук сражения
B_AssessFightSound();
};
};

// Данная функция не используется и может быть удалена.
func void B_MoveFollowNpc()
{
}
;

// Функция инициализации состояния
func void ZS_Follow_Player()
{
// разрешить НПС все чувства
self.senses = SENSE_SEE|SENSE_HEAR|SENSE_SMELL;
// установить дальность чувств 20 метров
self.senses_range = 2000;
// установить время реакции на восприятия 0.3 сек
Npc_SetPercTime(self,0.3);
// разрешить минимальный набор восприятий
Perception_Set_Minimal();
// установить локальное восприятие НПС на ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_AssessFollowPlayer);
// разрешить восприятие врага
Npc_PercEnable(self,PERC_ASSESSENEMY,B_AssessEnemy);
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
// разрешить восприятие перемещения МОВа
Npc_PercEnable(self,PERC_MOVEMOB,B_MoveMob);
// установить локальное восприятие звуков сражения
Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND,B_AssessFollowFightSound);
// перевод НПС в исходное состояние
B_ResetAll(self);
// НПС встает
AI_StandUp(self);
// установить режим передвижения бегом
AI_SetWalkmode(self,NPC_RUN);
// если дистанция между НПС не задана
if(self.aivar[AIV_FollowDist] == 0)
{
// задать дистанцию 5м
self.aivar[AIV_FollowDist] = 500;
};
};

// Функция цикла состояния
func int ZS_Follow_Player_Loop()
{
// расстояние между НПС и ГГ > дистанции следования
if(Npc_GetDistToNpc(self,hero) > self.aivar[AIV_FollowDist])
{
// если НПС Диего в Минентале
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(DiegoOW))
{
// если Диего слишком далеко
if(C_DiegoTooFar(0))
{
// если прошло > 1 сек
if(Npc_GetStateTime(self) > 1)
{
// Диего поворачивается к ГГ
B_TurnToNpc(self,hero);
// сброс времени цикла
Npc_SetStateTime(self,0);
};
return LOOP_CONTINUE;
};
};
// если НПС не плывет
if(!C_BodyStateContains(self,BS_SWIM))
{
// установить режим передвижения бегом
AI_SetWalkmode(self,NPC_RUN);
};
// НПС движется к ГГ
AI_GotoNpc(self,hero);
// сброс флага (НПС в движении)
self.aivar[AIV_TAPOSITION] = FALSE;
}
else // расстояние < дистанции следования
{
// если прошло > 1 сек
if(Npc_GetStateTime(self) > 1)
{
// НПС поворачивается к ГГ
B_TurnToNpc(self,hero);
// сброс времени цикла
Npc_SetStateTime(self,0);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Follow_Player_End()
{
}
;




// **********************************
// Обработчик поведения призраков
// **********************************

// Функция инициализации состояния
func void ZS_Ghost()
{
var c_npc Quarho;
// получить ссылку на Куарходрона
Quarho = Hlp_GetNpc(NONE_ADDON_111_Quarhodron);
// если НПС Куарходрон
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Quarho))
{
// если информация о "Камерах Аданоса" не известна
if(Ghost_SCKnowsHow2GetInAdanosTempel == FALSE)
{
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
};
}
else
{
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
};
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_AssessDamage);
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить время реакции на восприятия 0.1 сек
Npc_SetPercTime(self,0.1);
// НПС встает
AI_StandUp(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// движение на свой вайпоинт
AI_GotoWP(self, self.wp);
// выравнивание
AI_AlignToWP(self);
};

// Функция цикла состояния
func int ZS_Ghost_Loop()
{
// если прошло >= 5 сек
if(Npc_GetStateTime(self) >= 5)
{
// если расстояние между НПС и ГГ > дистанции начала диалога
if(Npc_GetDistToNpc(self,hero) > PERC_DIST_DIALOG)
{
// выравнивание
AI_AlignToWP(self);
// сброс времени состояния
Npc_SetStateTime(self,0);
};
// удалить призрака
B_RemoveGhost();
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Ghost_End()
{
}
;

// ******************************
// Обработчик поведения Радемеса
// ******************************

// Функция инициализации состояния
func void ZS_GhostWusel()
{
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_AssessDamage);
// перевод НПС в исходное состояние
B_ResetAll(self);
// НПС встает
AI_StandUp(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// движение на свободный фрипоинт
AI_GotoFP(self,"FP_ROAM");
};

// Функция цикла состояния (Радемес бродит по фрипоинтам)
func int ZS_GhostWusel_Loop()
{
// если прошло >= 3 сек
if(Npc_GetStateTime(self) >= 3)
{
// если Радемес находится на фрипоинте
if(Npc_IsOnFP(self,"FP_ROAM"))
{
// если есть свободный следующий фрипоинт
if(Wld_IsNextFPAvailable(self,"FP_ROAM"))
{
// очистка очереди AI ссостояний НПС
Npc_ClearAIQueue(self);
// переход на следующий фрипоинт
AI_GotoNextFP(self,"FP_ROAM");
};
}
else // не на фрипоинте
{
// если НПС не передвигается
if(!C_BodyStateContains(self,BS_WALK)) && (!C_BodyStateContains(self,BS_RUN))
{
// перейти на фрипоинт
AI_GotoFP(self,"FP_ROAM");
};
};
// сброс времени состояния
Npc_SetStateTime(self,0);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_GhostWusel_End()
{
}
;



// **********************************
// Охрана Святого молота Гарвигом
// **********************************

// Функция инициализации состояния
func void ZS_Guard_Hammer()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Guard_Hammer_loop()
{
// если НПС находится на фрипоинте охраны
if(Npc_IsOnFP(self,"STAND"))
{
// выравнивание
AI_AlignToFP(self);
// если НПС шел на фрипоинт
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
}
// если фрипоинт существует и свободен
else if(Wld_IsFPAvailable(self,"STAND"))
{
// идти на фрипоинт
AI_GotoFP(self,"STAND");
// встать
AI_StandUp(self);
// выровняться
AI_AlignToFP(self);
// установить флаг перемещения
self.aivar[AIV_TAPOSITION] = NOTINPOS_WALK;
}
else // фрипоинт занят
{
// выровняться на вайпоинте
AI_AlignToWP(self);
// если НПС шел в точку
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
};
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// анимация перехода в режим охраны
AI_PlayAni(self,"T_STAND_2_HGUARD");
// установить флаг охраны
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// если НПС имеет Святой молот и расстояние до места хранения молота < 5м
if(Npc_HasItems(self,Holy_Hammer_MIS) == 1) && (Npc_GetDistToWP(self,"NW_MONASTERY_SANCTUM_01") <= 500)
{
// изъять из инвентаря НПС Святой молот
Npc_RemoveInvItems(self,Holy_Hammer_MIS,1);
// положить молот в точку хранения
Wld_InsertItem(Holy_Hammer_MIS,"FP_HAMMER");
};
// если прошло > 5 сек и НПС находится в режиме охраны
if((Npc_GetStateTime(self) > 5) && (self.aivar[AIV_TAPOSITION] == ISINPOS))
{
var int random;
random = Hlp_Random(10);
// с вероятностью 0.1
if(random == 0)
{
// осмотреть окрестности
AI_PlayAni(self,"T_HGUARD_LOOKAROUND");
};
// сброс времени цикла
Npc_SetStateTime(self,0);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Guard_Hammer_end()
{
// анимация перехода из состояния охраны в стоячее
AI_PlayAni(self,"T_HGUARD_2_STAND");
};




// ************************
// Охрана прохода НПС
// ************************

// Функция инициализации состояния
func void ZS_Guard_Passage()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll (self);
// установить время реакции на восприятия 0.1 сек
Npc_SetPercTime(self,0.1);
// НПС встает
AI_StandUp(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// если расстояние между НПС и ГГ > дистанции диалога
if(Npc_GetDistToNpc(self,hero) > PERC_DIST_DIALOG)
{
// выровняться
AI_AlignToWP(self);
};
};

// Функция цикла состояния
func int ZS_Guard_Passage_Loop()
{
// если прошло >= 3 сек
if (Npc_GetStateTime(self) >= 3)
{
// если расстояние между НПС и ГГ > дистанции диалога
if(Npc_GetDistToNpc(self,hero) > PERC_DIST_DIALOG)
{
// выровняться
AI_AlignToWP(self);
// сброс времени цикла
Npc_SetStateTime(self,0);
};
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Guard_Passage_End ()
{
}
;




// *********************************
// Обработчик следования ГГ за НПС
// *********************************

// Функция локального восприятия НПС на ГГ
func void B_AssessGuidePlayer()
{
// если расстояние между НПС и ГГ > 8м
if(Npc_GetDistToNpc(self,hero) > 800)
{
// если расстояние от НПС до его вайпоинта < расстояния от ГГ до этого же вайпоинта
if(Npc_GetDistToWP(self,self.wp) < Npc_GetDistToWP(hero,self.wp))
{
// очистить очередь AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// НПС поворачивается к ГГ
B_TurnToNpc(self,hero);
};
// если расстояние между НПС и ГГ > 12м и враги у НПС есть и отношения между НПС и ГГ враждебные
if(Npc_GetDistToNpc(self,hero) > 1200) && (self.aivar[AIV_EnemyOverride] == TRUE) && (Npc_GetAttitude(self,hero) == ATT_HOSTILE)
{
// сброс флага врагов (врагов и НПС нет)
self.aivar[AIV_EnemyOverride] = FALSE;
};
}
else
{
// обычная реакция НПС на ГГ
B_AssessPlayer();
};
};

// Функция локального восприятия НПС на звук сражения
func void B_AssessGuideFightSound()
{
// если other (нападающий) есть ГГ или victim (жертва) есть ГГ
if(Npc_IsPlayer(other)) || (Npc_IsPlayer(victim))
{
// обычная реакция НПС на звук сражения
B_AssessFightSound();
};
};

// Функция инициализации состояния
func void ZS_Guide_Player()
{
// разрешить минимальный набор восприятий
Perception_Set_Minimal();
// перевод НПС в исходное состояние
B_ResetAll (self);
// разрешить НПС все чувства
self.senses = SENSE_SEE | SENSE_HEAR | SENSE_SMELL;
// установить дальность чувств 20 метров
self.senses_range = 2000;
// установить время реакции НПС на восприятия 1 сек
Npc_SetPercTime(self,1);
// установить локальное восприятие НПС на ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_AssessGuidePlayer);
// разрешить восприятие врага
Npc_PercEnable(self,PERC_ASSESSENEMY,B_AssessEnemy);
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
// разрешить восприятие перемещения МОВа
Npc_PercEnable(self,PERC_MOVEMOB,B_MoveMob);
// установить локальное восприятие звуков сражения
Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND,B_AssessGuideFightSound);
};

// Функция цикла состояния
func int ZS_Guide_Player_Loop()
{
// если расстояние между НПС и ГГ > 8м и расстояние от НПС до его вайпоинта < расстояния от ГГ до этого же вайпоинта
if(Npc_GetDistToNpc(self,hero) > 800) && (Npc_GetDistToWP(self,self.wp) < Npc_GetDistToWP(hero,self.wp))
{
// локальная реакция НПС на ГГ
B_AssessGuidePlayer();
}
// если расстояние между НПС и его вайпоинтом > 3м
else if(Npc_GetDistToWP(self,self.wp) > 300)
{
// если НПС не плывет
if(!C_BodyStateContains(self,BS_SWIM))
{
// установить режим передвижения бегом
AI_SetWalkmode(self,NPC_RUN);
};
// движение НПС на вайпоинт
AI_GotoWP(self,self.wp);
}
else
{
// НПС поворачивается к ГГ
B_TurnToNpc(self,hero);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func int ZS_Guide_Player_End()
{
};




// *****************************
// НПС справляет малую нужду
// *****************************

// Функция инициализации состояния
func void ZS_Pee()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Pee_loop()
{
// если НПС на нужном фрипоинте
if(Npc_IsOnFP(self,"PEE"))
{
// выравнивание
AI_AlignToFP(self);
// если НПС шел на фрипоинт
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
}
// если фрипоинт существует и свободен
else if(Wld_IsFPAvailable(self,"PEE"))
{
// идти на фрипоинт
AI_GotoFP(self,"PEE");
// встать
AI_StandUp(self);
// выровняться
AI_AlignToFP(self);
// установить флаг перемещения
self.aivar[AIV_TAPOSITION] = NOTINPOS_WALK;
}
else // фрипоинт занят
{
// выровняться на вайпоинте
AI_AlignToWP(self);
// если НПС шел в точку
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
};
// если флаг сброшен и НПС на нужном фрипоинте
if((self.aivar[AIV_TAPOSITION] == NOTINPOS) && (Npc_IsOnFP(self,"PEE")))
{
// выровняться
AI_AlignToFP(self);
// встать
AI_StandUp(self);
// анимация мочеиспускания
AI_PlayAni(self,"T_STAND_2_PEE");
// установить флаг выполнения нужной функции
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Pee_end()
{
// прекратить мочеиспускание
AI_PlayAni(self,"T_PEE_2_STAND");
};


// *********************************************************
// НПС бродит по PICK фрипоинтам (что-то ищет или собирает)
// *********************************************************

// Функция инициализации состояния
func void ZS_Pick_FP()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
};

// Функция цикла состояния
func int ZS_Pick_FP_Loop()
{
// если время состояния >= 7сек и с вероятностью 0.5
if((Npc_GetStateTime(self) >= 7) && (Hlp_Random(2)))
{
// если НПС на фрипоинте и есть еще фрипоинт
if((Npc_IsOnFP(self,"PICK")) && (Wld_IsFPAvailable(self,"PICK")))
{
// НПС идет на следующий фрипоинт
AI_GotoNextFP(self,"PICK");
// анимация поиска
AI_PlayAni(self,"T_PLUNDER");
// сброс времени цикла
Npc_SetStateTime(self,0);
}
// если НПС на фрипоинте
else if(Npc_IsOnFP(self,"PICK"))
{
// анимация поиска
AI_PlayAni(self,"T_PLUNDER");
// сброс времени цикла
Npc_SetStateTime(self,0);
};
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
}
// если время состояния >= 7сек
else if(Npc_GetStateTime(self) >= 7)
{
// если НПС на фрипоинте
if(Npc_IsOnFP(self,"PICK"))
{
// анимация поиска
AI_PlayAni(self,"T_PLUNDER");
};
// установить режим передвижения шагом
AI_SetWalkmode (self,NPC_WALK);
};
// если НПС не на фрипоинте и есть еще фрипоинт
if((!Npc_IsOnFP(self,"PICK")) && (Wld_IsFPAvailable(self,"PICK")))
{
// НПС идет на фрипоинт
AI_GotoFP(self,"PICK");
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Pick_FP_End()
{
}
;




// *********************
// НПС добывает руду
// *********************

// Функция инициализации состояния
func void ZS_Pick_Ore()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет кирки
if(Npc_HasItems(self,ItMw_2H_Axe_L_01) == 0)
{
// создать в инвентаре НПС кирку
CreateInvItem(self,ItMw_2H_Axe_L_01);
};
// взять в руки кирку
EquipItem(self,ItMw_2H_Axe_L_01);
};

// Функция цикла состояния
func int ZS_Pick_Ore_Loop()
{
// если действие с МОВом не прерываемо и залежи руды имеются
if(!C_BodyStateContains(self,BS_MOBINTERACT_INTERRUPT)) && (Wld_IsMobAvailable(self,"ORE"))
{
// добыча руды
AI_UseMob(self,"ORE",1);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Pick_Ore_End()
{
// прекратить добычу руды
AI_UseMob(self,"ORE",-1);
};




// *****************
// Игра на лютне
// *****************

func void ZS_Play_Lute()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет лютни
if(Npc_HasItems(self,ItMi_Lute) == 0)
{
// создать в инвентаре НПС лютню
CreateInvItem(self,ItMi_Lute);
};
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Play_Lute_Loop()
{
// если НПС на нужном фрипоинте
if(Npc_IsOnFP(self,"STAND"))
{
// выравнивание
AI_AlignToFP(self);
// если НПС шел на фрипоинт
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
}
// если фрипоинт существует и свободен
else if(Wld_IsFPAvailable(self,"STAND"))
{
// идти на фрипоинт
AI_GotoFP(self,"STAND");
// встать
AI_StandUp(self);
// выровняться
AI_AlignToFP(self);
// установить флаг перемещения
self.aivar[AIV_TAPOSITION] = NOTINPOS_WALK;
}
else // фрипоинт занят
{
// выровняться на вайпоинте
AI_AlignToWP(self);
// если НПС шел в точку
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
};
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// играть на лютне
AI_UseItemToState(self,ItMi_Lute,1);
// установить флаг выполнения нужной функции
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Play_Lute_End()
{
// прекратить игру на лютне
AI_UseItemToState(self,ItMi_Lute,-1);
};




// ************************************
// Приготовление алхимических напитков
// ************************************

// Функция инициализации состояния
func void ZS_Potion_Alchemy()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если НПС расположен не на своем вайпоинте
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
// если НПС не имеет Лабораторной колбы
if(Npc_HasItems(self,ItMi_Flask) == 0)
{
// создать в инвентаре НПС Лабораторную колбу
CreateInvItem(self,ItMi_Flask);
};
};

// Функция цикла состояния
func int ZS_Potion_Alchemy_Loop()
{
// если действие с МОВом не прерываемо и лабораторный стол имеется
if(!C_BodyStateContains(self,BS_MOBINTERACT_INTERRUPT)) && (Wld_IsMobAvailable(self,"LAB"))
{
// изготовление напитка
AI_UseMob(self,"LAB",1);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Potion_Alchemy_End()
{
// прекратить алхимию
AI_UseMob(self,"LAB",-1);
};




// *****************************
// Тренировка магии
// *****************************

// Функция инициализации состояния
func void ZS_Practice_Magic()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
};
};

// Функция цикла состояния
func int ZS_Practice_Magic_Loop()
{
// если НПС на нужном фрипоинте
if(Npc_IsOnFP(self,"STAND"))
{
// выравнивание
AI_AlignToFP(self);
// если НПС шел на фрипоинт
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK)
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
}
// если фрипоинт существует и свободен
else if(Wld_IsFPAvailable(self,"STAND"))
{
// идти на фрипоинт
AI_GotoFP(self,"STAND");
// встать
AI_StandUp(self);
// выровняться
AI_AlignToFP(self);
// установить флаг перемещения
self.aivar[AIV_TAPOSITION] = NOTINPOS_WALK;
}
else // фрипоинт занят
{
// выровняться на вайпоинте
AI_AlignToWP(self);
// если НПС шел в точку
if(self.aivar[AIV_TAPOSITION] == NOTINPOS_WALK )
{
// сброс флага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
};
// если время состояния > 7сек и флаг сброшен
if((Npc_GetStateTime(self) > 7) && (self.aivar[AIV_TAPOSITION] == NOTINPOS))
{
var int zufall;
zufall = Hlp_Random(100);
// с разной вероятностью выполнять магические упражнения
if(zufall <= 25)
{
AI_PlayAni(self,"T_PRACTICEMAGIC");
}
else if(zufall <= 50)
{
AI_PlayAni(self,"T_PRACTICEMAGIC2");
}
else if(zufall <= 70)
{
AI_PlayAni(self,"T_PRACTICEMAGIC3");
}
else if(zufall <= 90)
{
AI_PlayAni(self,"T_PRACTICEMAGIC4");
}
else
{
AI_PlayAni(self,"R_SCRATCHHEAD");
};
// сброс времени состояния
Npc_SetStateTime(self,0);
};
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Practice_Magic_End()
{
}
;




// **********************
// Упражнения с мечом
// **********************

// Функция инициализации состояния
func void ZS_Practice_Sword()
{
// установить нормальный набор восприятий
Perception_Set_Normal();
// перевод НПС в исходное состояние
B_ResetAll(self);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
// если расстояние между НПС и его вайпоинтом > дистанции выполнения функций
if(Npc_GetDistToWP(self,self.wp) > TA_DIST_SELFWP_MAX)
{
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// выравнивание
AI_AlignToWP(self);
};
// взять в руки лучшее оружие ближнего радиуса поражения
AI_EquipBestMeleeWeapon(self);
// сброс флага цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла состояния
func int ZS_Practice_Sword_Loop()
{
// если флаг сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// если НПС не имеет оружия ближнего радиуса поражения
if(!Npc_HasEquippedMeleeWeapon(self))
{
// создать в инвентаре НПС Тяжелую палку
CreateInvItems(self,ItMw_1h_Bau_Mace,1);
// взять её в руки
AI_EquipBestMeleeWeapon(self);
};
// подготовиться
AI_ReadyMeleeWeapon(self);
// установка флага готовности
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// анимация упражнений
AI_PlayAni(self,"T_1HSFREE");
// движение на свой вайпоинт
AI_GotoWP(self,self.wp);
// выравняться
AI_AlignToWP(self);
return LOOP_CONTINUE;
};

// Функция завершения состояния
func void ZS_Practice_Sword_End()
{
// встать
AI_StandUp(self);
// убрать оружие
AI_RemoveWeapon(self);
};
 

Saturas


Модостроитель
Регистрация
11 Фев 2009
Сообщения
2.512
Благодарности
1.332
Баллы
315
Кстати нашел небольшую ошибочку в туторе вама, а именно в классе C_NPC:
Код:
var int     weapon;                     //(не используется)
У него написано что эта переменная не используется, хотя это не так, в этой переменной находится текущий режим боя ГГ/НПС
Код:
// WEAPON MODE
const int WEAPON_NONE            =    0;
const int WEAPON_FIST            =    1;
const int WEAPON_KNIFE            =    2;
const int WEAPON_1H                =    3;
const int WEAPON_2H                =    4;
const int WEAPON_BOW            =    5;
const int WEAPON_CROSSBOW        =    6;
const int WEAPON_MAGIC            =    7;
Вот кстати список ВСЕХ доступных режимов борьбы в игре, ибо в констнтах этой инфы нету.
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу