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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!

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

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

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема первая: Типы переменных.

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

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема вторая: Операции над данными.

Существует несколько типов операций: арифметические, присваивания, отношения, логические, побитовые, над массивами, операции с членами классов.
В основном, все операции применимы только к простым типам, за исключением типа string.

1. Арифметические операции.

+ - простое сложение
- - простое вычитание
* - простое умножение
/ - простое деление (результат целая часть)
% - простое деление (результат остаток)

2. Операции присваивания.

= - простое присваивание
+= - сложение с приваиванием
-= - вычитание с присваиванием
*= - умножение с присваиванием
/= - деление с приваиванием (целая часть)

3. Операции отношения.

< - истина, если меньше
> - истина, если больше
<=- истина, если меньше или равно
>= - истина, если больше или равно
== - истина, если равно
!= - истина, если не равно

4. Логические операции.

! - истина, если выражение ложно
|| - истина, если истинно значение первого или второго операнда
&& - истина, если истинно значение первого и второго операнда
Операция ! является только префиксной операцией (пример !операнд)

5. Побитовые операции.

~ - инверсия операнда (префиксная операция)
>> - логический сдвиг вправо операнда1 на величину операнда2
<< - логический сдвиг влево операнда1 на величину операнда2
| - побитовая операция ИЛИ
& - побитовая операция И
^ - побитовая операция исключающее ИЛИ

6. Операции над массивами.

[] - получение или задание элемента массива по индексу (при инициализации массива задание его размерности)

7. Операции с членами классов.

. - обращение к элементу класса
Пример: аа.бб , где аа - имя класса, бб - имя переменной класса

8. Другие операции.

() - вызов функции с аргументами
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема третья: Операторы и идентификаторы типа.

1. Операторы.

Операторов в скриптах реализовано очень мало:
{ выражение (я) };- оператор блок, после закрывающей фигурной скобки обязательна точка с запятой.
Блоки допускают вложения друг в друга.
if (условие(я)) блок - оператор условного выполнения. Если условие истина, то выполняется блок, исли условие ложно, то блок пропускается. Возможна и другая реализация:
if (условие(я)) блок else блок - если условие истина, выполняется только блок if, если условие ложь, то выполняется только блок else. Возможно вложение операторов if друг в друга.
return - оператор выхода из функции, может возвращать значение.

2. Идентификаторы типа.

Существуют два идентификатора типа:
const- определяет тип константы
var - определяет тип переменной
Оба идентификатора типа применимы к следующим типам: int, float, string, func.
Идентификатор var может использоваться только внутри блока.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема четвертая: Грамматика скриптов.

Текст скриптов состоит из файлов с расширением .D, файлы желательно располагать по определенным темам, согласно директорий, можно создавать любое кол-во файлов и директорий с произвольными именами.
Процесс компиляции начинается с файла с расширением .SRC, в нем записывается порядок, в котором будут компилироваться файлы .D. Допускается вложенность файлов .SRC.

Одно общее правило: прежде чем использовать какую-либо переменную, она должна быть декларирована. Декларация переменной с определенным именем во всех скриптах должна быть одна. Декларация (объявление) может быть с инициализацией или без нее.
Формат .D файла прост: любая декларация должна начинаться с одного из ключевых слов: const, var, func, class, instance, prototype. Идентификатор var, как говорилось ранее, может быть использован только в блоке.
Компилятор одинаково распознает как заглавные буквы, так и строчные буквы, поэтому имена Аааа и аааа - это одно и то же.
Комментарии могут быть любые и в любом месте файла, они начинаются с // и до конца строки, или выделяются конструкцией /* комментарий */ и могуть включать несколько строк.

Существует несколько главных файлов .SRC, их имена изменять нельзя. Это в папке Content - gothic.src и fight.src, а в папке System - camera.src, menu.src, music.src, sfx.src, visualfx.src и particlefx.src -из них компилируются соответствующие *.dat файлы.
Дальше будем рассматривать базовые классы и функции. Все конкретные классы и функции будут относиться только к скриптам gothic.src. Остальные скрипты пока рассматривать не будем, может потом в этом появится необходимость.
Небольшое замечание: В скриптах кол-во локальных переменных в блоке и размерность любого массива ограничены числом 255.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема пятая: Классы.

Все классы описаны в файле ..\_intern\Classes.d

1. Класс параметров НПС.
const int MAX_CHAPTER = 5; //Макс. количество глав в игре (не используется)
const int MAX_MISSIONS = 5; //Макс. количество одновременно выполняемых миссий
const int MAX_HITCHANCE = 5; //Макс. размерность массива способностей владения видами оружия
class c_npc
{
var int id; //Однозначный идентификатор, связывающий конкретного НПС с его параметрами
var string name[5]; //Имя НПС, оно появляется на экране, если НПС находится в фокусе
var string slot; //(не используется) Можно использовать для хранения какой-нибудь строки текста!
var string effect; //Имя визуального эффекта, привязанного к НПС
var int npcType; //Тип НПС (описывается в файле ..AI\AI_Intern\AI_Constants.d)
var int flags; //Флаги НПС (NPC_FLAG_IMMORTAL, NPC_FLAG_GHOST)
var int attribute[ATR_INDEX_MAX]; //Массив значений атрибутов (ATR_HITPOINTS, ATR_MANA, ATR_STRENGTH и т.д.)
var int HitChance[MAX_HITCHANCE]; //Способность владения НПС определенным оружием
var int protection[PROT_INDEX_MAX]; //Массив значений защиты от определенных повреждений
var int damage[DAM_INDEX_MAX]; //Массив значений наносимых повреждений
var int damagetype; //Тип повреждения (НПС наносит в данный момент)
var int guild; //Принадлежность к гильдии
var int level; //Уровень НПС
var func mission[MAX_MISSIONS]; //(не используется)
var int fight_tactic; //Тактика сражения (описывается в файле ..AI\AI_Intern\AI_Constants.d)
var int weapon; //(не используется)
var int voice; //Номер голоса в диалогах
var int voicePitch; //Тональность голоса
var int bodymass; //(не используется)
var func daily_routine; //Функция распорядка дня
var func start_aistate; //Функция начального AI состояния (ZS_ функции)
var string spawnPoint; //Имя Waypoint, в котором рождается НПС
var int spawnDelay; //Задержка в секундах между смертью и возрождением НПС
var int senses; //Чувства (зрение, слух, обоняние)
var int senses_range; //Диапазон чувств в см.
var int aivar[100]; //Массив значений AI переменных (описывается в файле ..AI\AI_Intern\AI_Constants.d), неиспользуемые индексы могут использоваться для собственных целей. Для Готики 2.
// Для Готики 1 var int aivar[50];

var string wp; //Текущий Waypoint, в котором находится НПС (отслеживается Gothic.exe)
var int exp; //Количество полученной экспы (только для ГГ)
var int exp_next; //Количество экспы оставшееся до следующего уровня (только для ГГ)
var int lp; //Свободные очки обучения (только для ГГ)
var int bodyStateInterruptableOverride; //Флаг возможности прерывания действия НПС (если TRUE - НПС прервать нельзя)
var int noFocus; //Флаг, отвечающий за фокус (если TRUE и НПС находится в фокусе, то у НПС не показывается имя и количество жизни)
};
2. Класс миссий (не используется).
class c_mission
{
var string name;
var string description;
var int duration;
var int important;
var func offerConditions;
var func offer;
var func successConditions;
var func success;
var func failureConditions;
var func failure;
var func obsoleteConditions;
var func obsolete;
var func running;
};
3. Класс параметров предмета.
class c_item
{
var int id; //Однозначный идентификатор, связывающий конкретный предмет с его параметрами
var string name; //Имя предмета, оно появляется на экране, если предмет находится в фокусе
var string nameID; //(не используется) Можно использовать для хранения какой-нибудь строки текста!
var int hp,hp_max; //???
var int mainflag; //Флаги категории предмета
var int flags; //Остальные флаги предметов
var int weight,value; //Вес и стоимость предмета
var int damageType; //Тип наносимого повреждения (используется для оружия)
var int damageTotal; //Суммарное повреждение (используется для оружия)
var int damage[DAM_INDEX_MAX]; //Величина ущерба по типам повреждений (используется для оружия)
var int wear; //Флаги ношения предмета
var int protection[PROT_INDEX_MAX]; //Величина защиты от конкретных повреждений (используется для брони)
var int nutrition; //(не используется)
var int cond_atr[3]; //Массив атрибутов, требуемых для применения
var int cond_value[3]; //Массив значений атрибутов, требуемых для применения
var int change_atr[3]; //(не используется)
var int change_value[3]; //(не используется)
var func magic; //(не используется)
var func on_equip; //Функция вызываемая при экипировке
var func on_unequip; //Функция вызывается, когда предмет снимается или убирается в инвентарь
var func on_state[4]; //Функции вызываемые при использовании предмета по видам состояний (видов состояний не обнаружил ???)
var func owner; //Владелец предмета, записывается ID НПС (не понятен тип переменной FUNC ???)
var int ownerGuild; //Какой гильдии принадлежит предмет
var int disguiseGuild; //(не используется)
var string visual; //Имя .3DS файла текстур предмета
var string visual_change; //Имя .ASC файла визуальных эффектов при получении этого предмета
var string effect; //Имя визуального эффекта, привязанного к предмету
var int visual_skin; //Вариация текстуры для .3DS файла текстур предмета
var string scemeName; //Внутреннее имя предмета
var int material; //Материал предмета
var int munition; //Тип заряда для оружия дальнего радиуса поражения
var int spell; //Номер заклинания, которое вызывает данный предмет
var int range; //Радиус поражения оружием ближнего боя
var int mag_circle; //Круг магии, к которому принадлежит предмет
var string description; //Название предмета в инвентаре
var string text[ITM_TEXT_MAX]; //Массив строк описания предмета в инвентаре
var int count[ITM_TEXT_MAX]; //Массив значений характеристик предмета в инвентаре (соответствует определенной текстовой строке)
// Характеристики изображения предмета в инвентаре
var int inv_zbias; //Масштаб предмета в инвентаре
var int inv_rotx; //Поворот предмета в инвентаре относительно оси X
var int inv_roty; //Поворот предмета в инвентаре относительно оси Y
var int inv_rotz; //Поворот предмета в инвентаре относительно оси Z
var int inv_animate; //Вращение предмета в инвентаре
};
4. Класс параметров фокуса.
class c_focus
{
// для НПС
var float npc_longrange; //Ширина
var float npc_range1,npc_range2; //Диапазон дальности
var float npc_azi; //Азимут
var float npc_elevdo,npc_elevup; //Тангаж
var int npc_prio; //Приоритет
// для предметов
var float item_range1,item_range2; //Диапазон дальности
var float item_azi; //Азимут
var float item_elevdo,item_elevup; //Тангаж
var int item_prio; //Приоритет
// для MOB's
var float mob_range1,mob_range2; //Диапазон дальности
var float mob_azi; //Азимут
var float mob_elevdo,mob_elevup; //Тангаж
var int mob_prio; //Приоритет
};
5. Класс параметров диалогов.
class c_info
{
var int npc; //ID НПС, которому принадлежит диалог
var int nr; //Опция диалога с большим nr будет отображаться в списке ниже
var int important; //Флаг начала диалога (TRUE - диалог начинаешь ты, FALSE - с тобой)
var func condition; //Функция проверки условий начала диалога (пока функция не возвратит TRUE, диалог не начнется)
var func information; //Функция управления диалогом
var string description; //Строка, которая выводится в окно выбора вариантов ответов
var int trade; //Возможность торговли (TRUE - возможно торговать, FALSE - нет)
var int permanent; //Постоянность диалога (TRUE - диалог повторяется при каждом обращении, FALSE - однократный)
};
6. Класс реакций на предметы (не используется).
class c_itemreact
{
var int npc;
var int trade_item;
var int trade_amount;
var int requested_cat;
var int requested_item;
var int requested_amount;
var func reaction;
};
7. Класс параметров заклинаний.
class c_spell
{
var float time_per_mana; //Время в мс, требуемое для инвестирования маны на один уровень
var int damage_per_level; //Наносимый урон за уровень заклинания
var int damageType; //Тип повреждения
var int spellType; //Категория заклинания
var int canTurnDuringInvest; //Возможность поворота во время инвестирования маны (TRUE - возможно)
var int canChangeTargetDuringInvest; //Возможность выбора цели во время инвестирования маны (TRUE - возможно)
var int isMultiEffect; //Возможность мультиэффектов заклинания (множественные цели и др.)
var int targetCollectAlgo; //Константа описания цели
var int targetCollectType; //Тип цели заклинания
var int targetCollectRange; //Дальность действия
var int targetCollectAzi; //Угол азимута
var int targetCollectElev; //Угол тангажа
};
8. Глобальные ссылки на классы.
instance self,other(c_npc); // Сам НПС и Другой НПС
instance victim(c_npc); // НПС - жертва определенного действия (3ий в действии)
instance item(c_item); // Сам предмет
instance hero(c_npc); // Сам ГГ (игрок)
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема шестая: Функции.

Несколько общих замечаний:
1. Функции могут возвращать значения только этих типов: void, int, float, string, instance.
2. Рассматривать будем пока только базовые функции, которые реализованы в екзешнике.
3. Большинство базовых функций описано в файле externals.d, но в нем есть ошибки (этот файл приведен только для справки, он не компилируется), о них буду говорить по мере разбора функций, и отмечать значком ***.
4. Идентификаторы func (при объявлении функции) и var (как идентификатор аргументов) для простоты приводить не буду.

1. Функции вывода текста.

void Print (string s0); - выводит на экран строку текста s0, как OutputUnits текст (аналогично выводу из OU файла).
void PrintMulti (string s0, string s1, string s2, string s3, string s4); - выводит текст на экран, объединяя строки параметров s0- s 4 в одну строку.
int PrintScreen (string msg, int posx, int posy, string font, int timeSec); - выводит на экран строку текста msg (имя шрифта – font) с координатами posx, posy (диапазон от 0 до 99% размера экрана, -1 означает вывод по центру соответствующей оси экрана) на время timeSec (в секундах). Возвращаемое значение всегда = 0.***
void PrintDebug (string s); - выводит текст строки s через zSpy или в лог. файл, работает только в отладочном режиме (включается (Alt+D))
void PrintDebugInst (string text); - выводит текст строки text через zSpy или в лог. файл для ссылки self в отладочном режиме.
void PrintDebugInstCh (int ch, string text); - выводит текст строки text через zSpy или в лог. Файл для ссылки self канала ch в отладочном режиме (каналы определены в файле PrintDebug. d).
void PrintDebugCh (int ch, string text); - выводит текст строки text через zSpy или в лог. файл для канала ch в отладочном режиме
int PrintDialog (int dialogNr, string msg, int posx, int posy, string font, int timeSec); - работает аналогично функции PrintScreen, только вывод осуществляется в окно диалога c номером dialogNr (координаты в % действуют внутри окна диалога).***

2. Функции преобразования типов.

string IntToString (int x); - преобразовывает целое число x в строку.
string floatToString (float x); - преобразовывает число с плавающей точкой x в строку.***
int floatToInt (float x); - преобразовывает число с плавающей точкой x в целое число.
float IntTofloat (int x); - преобразовывает целое число х в число с плавающей точкой.
string ConcatStrings (string str1, string str2); - результирующей строкой является объединение двух строк str1 и str2.

3. Функции работы со звуком.

void Snd_Play (string s0); - воспроизвести звуковой файл с именем s0.
void Snd_Play3D (c_npc n0, string s1); - воспроизвести звуковой файл с именем s0 для НПС n0.
int Snd_IsSourceNpc (c_npc self); - проверить, является ли НПС self источником звука (return > 0) и установить ссылку other на этого НПС.
int Snd_IsSourceItem (c_npc self); - проверить, является ли у НПС self предмет источником звука (return > 0) и установить ссылку item на этот предмет
int Snd_GetDistToSource (c_npc self); - выдать расстояние в сантиметрах до источника звука от НПС self.

4. Вспомогательные функции.

int Hlp_Random (int n0); - сгенерировать случайное целое число в диапазоне от 0 до n0 - 1.
int Hlp_StrCmp (string s1, string s2); - сравнивает две строки s1 и s2, возвращает TRUE при равенстве строк или FALSE при неравенстве.
int Hlp_IsValidNpc (c_npc self); - если ссылка на НПС self существует, то возвращает TRUE, иначе – FALSE.
int Hlp_IsValidItem (c_item item); - если ссылка на предмет item существует, то возвращает TRUE, иначе – FALSE.
int Hlp_IsItem (c_item item, int instanceName); - проверяет принадлежность предмета item к соответствующему типу instanceName, возвращает TRUE при соответствии, иначе – FALSE.
c_npc Hlp_GetNpc (int instanceName); - возвращает ссылку на НПС, принадлежащему к типу instanceName.
int Hlp_GetInstanceID (c_npc npc); - получить ID номер npc по ссылке на класс npc.
int Hlp_GetInstanceID (c_item item); - получить ID номер предмета по ссылке на класс item.

5. Функции работы с документами (свитки, книги, записки, карты).

int Doc_Create (); - создает новый документ и возвращает номер его обработчика.
int Doc_CreateMap (); - создает новую карту и возвращает номер её обработчика. ***
void Doc_SetLevel (int handle, string world); - устанавливает уровень world (формат ZEN) для документа handle.*** (Не знаю, что конкретно делает эта функция).
void Doc_SetPages (int handle, int pages); - задает кол-во отображаемых страниц pages для документа handle.
void Doc_SetPage (int handle, int page, string pageimage, int scale); - устанавливает параметры страницы page (если параметр page = -1, то применяется ко всем страницам) документа handle: pageimage – имя файла изображения страницы в формате TGA, scale = 0 - применять масштабируемось, scale = 1 - не использовать масштабируемость (применяется для карт).
void Doc_SetFont (int handle, int page, string fontname); - задать шрифт для страницы page документа handle, где fontname – имя файла шрифта в формате TGA.
void Doc_SetMargins (int handle, int page, int leftMargin, int topMargin, int rightMargin, int bottomMargin, int pixel); - установить границы вывода текста на странице page документа handle, где leftMargin, topMargin, rightMargin, bottomMargin – соответственно левая, верхняя, правая и нижняя границы, pixel – кол-во пикселей на единицу границы.
void Doc_PrintLine (int handle, int page, string text); - выводит строку текста text на странице page документа handle.
void Doc_PrintLines (int handle, int page, string text); - выводит текст text в несколько строк на странице page документа handle.
void Doc_Show (int handle); - выводит созданный документ handle на экран.
void Doc_Open (string picName); - открывает документ с именем picName, как рисунок на заднем плане (в скриптах не используется).
void Doc_Font (string fontName); - задает для документа шрифт fontName (в скриптах не используется).
void Doc_Print (string text); - выводит текст text документа на экран (в скриптах не используется).
void Doc_MapCoordinates (string levelName, float gamex1, float gamey1, float pixelx1, float pixely1, float gamex2, float gamey2, float pixelx2, float pixely2); - инициализирует карту с именем уровня levelName, где gamex1, gamey1, gamex2, gamey2 – координаты углов карты, соответствующие координатам уровня, а pixelx1, pixely1, pixelx2, pixely2 – соответственно коодинаты пикселей углов карты (в скриптах не используется).

6. Функции работы с журналом квестов.

void Log_CreateTopic (string name, int section); - создать в журнале тему с именем name в разделе section (предопределены два раздела LOG_MISSION или LOG_NOTE).
void Log_SetTopicStatus (string name, int status); - установить статус status темы с именем name (предопределены следующие статусы - LOG_RUNNING, LOG_SUCCESS, LOG_FAILED, LOG_OBSOLETE).
void Log_AddEntry (string topic, string entry); - записать в тему topic текст из строки entry.

7. Функции работы с миссиями.

void Mis_SetStatus (int missionName, int newStatus); - установить статус newStatus миссии missionName (предопределены следующие статусы RUNNING, SUCCESS, FAILED и т.д.)
int Mis_GetStatus (int missionName); - получить статус миссии missionName.
int Mis_OnTime (int missionName); - проверка миссии, возвращает TRUE, если миссия активна, т.е. не завершена. Примечание: данная функция в экзешнике реализована неверно, она ничего не возвращает (лучше ее не использовать).
void Mis_AddMissionEntry (c_mission miss, string name); - добавить в список миссий новую миссию miss под именем name.***
void Mis_RemoveMission (c_mission miss); - удалить из списка миссий миссию miss. ***

8. Функции работы с инвентарем.

void CreateInvItem (c_npc n0, int n1); - создает в инвентаре НПС n0 предмет с ID n1.
void CreateInvItems (c_npc n0, int n1, int n2); - создает в инвентаре НПС n0 предметы с ID n1 количеством n2.
void EquipItem (c_npc n0, int n1); - экипировать НПС n0 предметом с ID n1.
void Mob_CreateItems (string mobName, int itemInstance, int amount); - создает в контейнере с именем mobName (например сундук) предметы с ID itemInstance количеством amount.
int Mob_HasItems (string mobName, int itemInstance); - получить количество предметов с ID itemInstance, находящихся в контейнере с именем mobName.

9. Функции анимации.

void Mdl_ApplyOverlayMds (c_npc n0, string s1); - запустить файл анимации s1 с расширением mds для НПС n0.
void Mdl_RemoveOverlayMDS (c_npc self, string overlayName); - отключить от НПС self файл анимации overlayName.
void Mdl_ApplyOverlayMDSTimed (c_npc self, string overlayname, int timeTicks); - запустить файл анимации overlayname для НПС self на время timeTicks.***
void Mdl_ApplyRandomAni (c_npc n0, string s1, string s2); - запустить случайные анимации s1 для НПС n0 в последовательности анимационных состояний s2.
void Mdl_ApplyRandomAniFreq (c_npc n0, string s1, float f2); - устанавливает частоту выборки f2 случайных анимационных состояний s1 для НПС n0.
void Mdl_StartFaceAni (c_npc self, string name, float intensity, float holdTime); - запускает файл name анимации лица для НПС self с интенсивностью intensity (в %, 1100%) и временем удержания holdTime (1 – постоянно).
void Mdl_ApplyRandomFaceAni (c_npc self, string name, float timeMin, float timeMinVar, float timeMax, float timeMaxVar, float probMin); - запускает файл случайной анимации лица name для НПС self со следующими параметрами : timeMin, timeMax – диапазон времени воспроизведения анимации в сек, timeMinVar, timeMaxVar – отклонения от значений timeMin, timeMax в сек, probMin – вероятность использования отклонения (от 0 до 1) от нижней до верхней границы.
void Mdl_SetVisual (c_npc self, string fileMds); - задать для НПС self файл изображения с именем fileMds (формат MDS).***
void Mdl_SetVisualBody (c_npc self, string body, int bodytex, int color, string head, int htex, int ttex, int armor); - установить параметры изображения НПС self, где : body – имя mesh файла изображения тела, bodytex – номер текстуры тела, color – номер палитры цвета кожи, head – имя MMS файла изображения головы, htex – номер текстуры головы, ttex – номер текстуры зубов, armor – номер одетой брони (- 1 – брони нет).***
void Mdl_SetModelScale (c_npc self, float x, float y, float z); - установить масштаб mesh изображения модели НПС self по координатам x, y, z в % (1 -100%).
void Mdl_SetModelFatness (c_npc self, float fatness); - установить жирность mesh изображения модели НПС self в % (1 - 100%). Может кто-нибудь пояснить, что это за функция?

10. Функции распорядка дня.

void TA_Min (c_npc self, int start_h, int start_m, int stop_h, int stop_m, func state, string waypoint); - для НПС self задается функция распорядка дня state, где start_h и start_m – время в часах и минутах начала выполнения функции, stop_h и stop_m – соответственно время окончания функции, waypoint – имя точки, в которой выполняется функция.
void TA (c_npc self, int start_h, int stop_h, func state, string waypoint); - выполняет все то, что и предыдущая функция, только без привязки к минутам.
void TA_CS (c_npc self, string csName, string roleName); - функция, выполняемая последней в списке функций распорядка дня для НПС self, где csName – имя файла CS (Cutscene), roleName – роль НПС, которая должна выполняться. (частично не понял)
void TA_BeginOverlay (c_npc self); - начать выполнять заявленный распорядок дня для НПС self.
void TA_EndOverlay (c_npc self); - закончить выполнять заявленный распорядок дня для НПС self.
void TA_RemoveOverlay (c_npc self); - удалить заявленный распорядок дня для НПС self.

11. Функции работы с диалогами.

int InfoManager_HasFinished (); - показывает, завершен ли диалог (возвращает 0 во время диалога и 1 после окончания диалога).***
void Info_AddChoice (c_info menu, string text, func fn); - добавляет в меню диалога menu строку выбора действия text, fn – функция, которая активируется при выборе данного пункта меню.***
void Info_ClearChoices (c_info menu); - удалить тему диалога menu.***

12. Функции различного назначения.

void ExitGame (); - просто закончить игру.***
int PlayVideo (string video); - показать видео файл video (c расширением BIK), возвращает 1, если видео показано, 0 – в случае ошибки.***
void SetPercentDone (int perc); - установить процент perc отображения полоски в окне загрузки (ProgressBar), значение от 0 до 100.***
void IntroduceChapter (string chapter, string name, string file, string sound, int time); - вывести на экран окно новой главы, где chapter – номер главы, name – название главы, file – файл заставки главы (формат TGA), sound – звуковой файл (формат WAV), time – время показа заставки.***
void Tal_Configure (int tal, int value); - переопределить значение таланта value для константы tal (например, определены константы NPC_TALENT_PICKLOCK, NPC_TALENT_MAGE и т.д.).***
void Perc_SetRange (int percID, int range); - устанавливает дальность действия range пассивного восприятия percID в сантиметрах.
void Rtn_Exchange (string oldRoutine, string newRoutine); - заменяет функции oldRoutine распорядка дня НПС self на новые функции newRoutine. (Имя функции должно начинаться с RTN_ и заканчиваться идентификатором НПС скрипта).
int Hlp_CutscenePlayed (string csName); - информирует, игралась ли Cutscene с именем csName (0 – нет, 1 – да).

13. Функции работы с миром Готики.

int Wld_DetectNpc (c_npc self, int instance, func aiState, int guild); - эта функция инициализирует глобальную переменную скриптов other, отличную от НПС self, где instance – производная от класса c_npc, которая должна быть найдена и проинициализирована (-1 – любая производная), guild – гильдия, членом которой должен быть искомый НПС (-1 – любая гильдия), aiState – функция AI состояния, в котором должен находится искомый НПС (NOFUNC – любое AI состояние). Функция возвращает 1 в случае успешного завершения (other инициализирован найденным НПС), 0 – неудача (other не определен).
int Wld_DetectNpcEx (c_npc self, int instance, func aiState, int guild, int detectPlayer); - выполняет все тоже, что и предыдущая функция, дополнительный параметр detectPlayer указывает, исключить ли игрока (ГГ) из поиска (0 – исключить, 1 – нет).
int Wld_DetectItem (c_npc self, int flags); - эта функция инициализирует глобальную переменную скриптов item предметом, возможно находящимся у НПС self и имеющим флаг flags, возвращает 1 при успешном поиске и инициализации, иначе – 0.
int Wld_DetectPlayer (c_npc self); - возвращает 1, если ГГ есть НПС self, иначе – 0.
void Wld_SetGuildAttitude (int guild1, int attitude, int guild2); - установить отношение между гильдиями, где guild1, guild2 – гильдии, между которыми устанавливается отношение, attitude – отношение между гильдиями (определены отношения ATT_HOSTILE, ATT_FRIENDLY, ATT_NEUTRAL, ATT_ANGRY).
int Wld_GetGuildAttitude (int guild1, int guild2); - получить отношение между гильдиями guild1 и guild2.
int Wld_IsMobAvailable (c_npc self, string schemeName); - проверяет, есть ли MOB с именем schemeName в окрестности 10 метров от НПС self, возвращает TRUE, если MOB существует и свободен, иначе FALSE.
int Wld_GetMobState (c_npc self, string schemeName); - определяет состояние MOB с именем schemeName для НПС self, возвращает состояние или -1, если MOB не найден.
int Wld_IsFPAvailable (c_npc self, string fpName); - проверяет, есть ли FP (Freepoint) с именем fpName в окрестности 20 метров от НПС self, возвращает TRUE, если FP существует и свободна, иначе FALSE.
int Wld_IsNextFPAvailable (c_npc self, string fpName); - работает аналогично предыдущей функции, но проверится ближайшая точка, если fpName блокирована.
int Wld_GetDay (); - получить текущий день, отсчет дней идет от дня старта (Gamestart) = 0.
int Wld_IsTime (int hour1, int min1, int hour2, int min2); - возвращает 1, если текущее время находится между границами (hour1, min1 – нижняя граница, hour2, min2 – верхняя граница в часах и минутах), иначе возвращает 0.
void Wld_SetTime (int hour, int min); - установить текущее время в часах hour и минутах min.***
void Wld_InsertNpc (int npcInstance, string spawnPoint); - разместить в мире одного НПС, где npcInstance – ссылка на НПС, spawnPoint – имя точки размещения (может быть как WP, так и FP).
void Wld_InsertNpcAndRespawn (int instance, string spawnPoint, int spawnDelay); - выполняется аналогично предыдущей функции, только НПС после смерти будет оживлен в заданной точке через spawnDelay секунд.***
void Wld_SpawnNpcRange (c_npc self, int npcInstance, int number, float time); - НПС self около себя создает НПС (ссылка на него npcInstance) количеством number на время жизни time. Используется в заклинаниях вызова.***
void Wld_RemoveNpc (int npcInstance); - удалить из мира НПС (ссылке на него npcInstance).***
void Wld_InsertItem (int itemInstance, string spawnPoint); - разместить в мире один предмет, где itemInstance – ссылка на предмет, spawnPoint – имя точки размещения (может быть как WP, так и FP). В примечании к функции написано: «Осторожно, не функционирует! Предмет будет вставлен в центр мира.» В скриптах данная функция используется, осталось выяснить, как она работает.
int Wld_RemoveItem (c_item item); - удалить из мира предмет по item ссылке на него, возвращает 1 – успешное удаление, иначе – 0.
void Wld_InsertObject (string name, string point); - разместить в мире визуальный объект name в точке с именем point (может быть как WP, так и FP).***
void Wld_SetObjectRoutine (int hour1, int min1, string objName, int state); -объект с именем objName (VOB объект) перейдет в состояние state в момент времени hour1, min1 (часы и минуты).
void Wld_SetMobRoutine (int hour1, int min1, string objName, int state); - выполняется как и предыдущая функция, только для MOB объекта.
void Wld_SendTrigger (string name); - активировать функцию VOB объекта с именем name. (Я не знаю где где прописаны эти функции).***
void Wld_SendUntrigger (string name); - деактивировать функцию VOB объекта с именем name.***
void Wld_ExchangeGuildAttitudes (string name); - установить взаимоотношения между гильдиями, где name – имя таблицы заданных отношений.
void Wld_AssignRoomToGuild (string s0, int guild); - размещает гильдию guild на пространстве s0.
void Wld_AssignRoomToNpc (string s0, c_npc roomowner); - размещает НПС roomowner на пространстве s0.
c_npc Wld_GetPlayerPortalOwner ();
int Wld_GetPlayerPortalGuild ();
c_npc Wld_GetFormerPlayerPortalOwner ();
int Wld_GetFormerPlayerPortalGuild ();
Какие-то четыре функции, определяющие положение игрока в пространстве, большего сказать, увы, не могу.
void Wld_PlayEffect (string ???, instance ???, instance ???, int ???, int ???, int ???, int ???); - данная функция абсолютно нигде не применяется и не описана, поэтому ее действие и аргументы мне не известны.***

14. Функции работы с НПС.

int Npc_GetTRUEGuild (c_npc npc); - возвращает номер гильдии, к которой принадлежит НПС npc.
int Npc_SetTRUEGuild (c_npc npc, int guildID); - установить принадлежность НПС npc к гильдии guildID.
void Npc_SetAttitude (c_npc self, int att); - установить постояноое отношение att НПС self ко всем остальным НПС.
void Npc_SetTempAttitude (c_npc self, int att); - установить временное отношение att НПС self ко всем остальным НПС.
int Npc_GetAttitude (c_npc self, c_npc other); - получить любое отношение НПС self к НПС other.
int Npc_GetPermAttitude (c_npc self, c_npc other); - получить постоянное отношение НПС self к НПС other.
int Npc_GetGuildAttitude (c_npc self, c_npc other); - получить отношение НПС self к НПС other, как отношение между гильдиями, а не личностями.
void Npc_SetKnowsPlayer (c_npc self, c_npc player) ; - эта функция задает, что НПС self знаком с НПС player (ГГ).
int Npc_KnowsPlayer (c_npc self, c_npc player); - проверить, знаком ли НПС self с НПС player, возвращает TRUE, если знаком, иначе FALSE.
int Npc_OwnedByNpc (c_item item, c_npc npc); - проверить, принадлежит ли предмет item npc, возвращает 1, если принадлежит, иначе - 0.
int Npc_OwnedByGuild (c_item item, int guild); - - проверить, принадлежит ли предмет item гильдии guild, возвращает 1, если принадлежит, иначе - 0.
string Npc_GetNearestWP (c_npc self); - возвращает название WP, в которой расположен НПС self.
string Npc_GetNextWP (c_npc self); - возвращает название соседней точки WP, рядом с которой расположен НПС self.
int Npc_IsWayBlocked (c_npc self); - возвращает 1, если путь НПС self прегражден препятствием, иначе – 0.
int Npc_IsOnFP (c_npc self, string name); - проверяет, находится ли НПС self в точке FP с именем name, возвращает 1 – да, иначе – 0.
int Npc_IsDead (c_npc n0); - возвращает 1, если НПС n0 мертв, иначе – 0.
int Npc_KnowsInfo (c_npc self, int infoInstance); - возвращает TRUE, если НПС self уже получил информацию infoInstance, иначе FALSE.
int Npc_CheckInfo (c_npc npc, int important); - проверяет, имеет ли НПС npc действительную информацию для игрока, в этом случае возвращается 1 и начинается диалог, иначе 0, где important – важность информации (1 – важная, 0 – обычная).
int Npc_GiveInfo (c_npc npc, int important); - работает аналогично предыдущей функции, есть какое-то отличие, но я его не понял.
int Npc_CheckAvailableMission (c_npc npc, int missionState, int important); - проверяет, имеет ли npc миссию в состоянии missionState (AVAILABLE, RUNNING) с важностью important, возвращает 1, если имеет, иначе – 0.
int Npc_CheckRunningMission (c_npc npc, int important); - работает аналогично предыдущей функции, только проверяется миссия в состоянии текущего выполнения.
int Npc_CheckOfferMission (c_npc npc, int important); - работает аналогично предыдущей функции, только проверяется миссия в которой НПС npc может что-то предложить игроку.
int Npc_GetStateTime (c_npc self); - возвращает кол-во секунд, которые НПС self находится в текущем состоянии, заданном в " Loop " цикле.
void Npc_SetStateTime (c_npc self, int seconds); - установить кол-во секунд seconds, как долго НПС self может находится в этом состоянии.
int Npc_GetBodyState (c_npc self); - возвращает состояние, в котором находится НПС self (BS_константы).
int Npc_HasBodyFlag (c_npc self, int bodyFlag); - проверяет, установлен ли у НПС self флаг состояния bodyFlag, возвращает 1, если установлен, иначе – 0.
int Npc_IsPlayer (c_npc player); - возвращает 1, если проверяемый НПС player является ГГ.
int Npc_HasDetectedNpc (c_npc self, c_npc other); - возвращает 1, если НПС self чувствует (видит, сышит и т.д.) НПС other, иначе – 0.
int Npc_IsInState (c_npc self, func state); - запрос на текущее состояние фигуры НПС self, где state – функция состояния фигуры, возвращает TRUE, если НПС находится в этом состоянии, иначе – FALSE.
int WasInState (c_npc self, func state); - аналогично предыдущей функции, только запрос на предыдущее состояние фигуры НПС.
int Npc_IsInRoutine (c_npc self, func state); - проверяет, находится ли НПС self в функции state, возвращает TRUE если находится, иначе – FALSE.
void Npc_ExchangeRoutine (c_npc self, string routineName); - поменять у НПС self распорядок дня routineName.
int Npc_IsInCutscene (c_npc self); - возвращает 1, если НПС self находится во время проигрывания Cutscene, иначе – 0.
int Npc_IsVoiceActive (c_npc self); - возвращает 1, если НПС self разговаривает, иначе – 0.***
void Npc_ClearAIQueue (c_npc self); - удаляет все команды для НПС self из очереди AI_Queue.
void Npc_PlayAni (c_npc self, string file); - воспроизвести файл анимации file для НПС self.***
void Npc_SetRefuseTalk (c_npc self, int timeSec); - установить счетчик отказа от диалога для НПС self на timeSec секунд.
int Npc_RefuseTalk (c_npc self); - проверить, истек ли счетчик отказа от диалога для НПС self, возвращает TRUE, если счетчик не истек, иначе – FALSE.
int Npc_IsNear (c_npc self, c_npc other); - возвращает 1, если НПС other находится на расстоянии не менее 3 метров от НПС self, иначе – 0.
int Npc_GetDistToNpc (c_npc npc1, c_npc npc2); - возвращает расстояние в см. между npc1 и npc2.
int Npc_GetDistToWP (c_npc self, string wpName); - возвращает расстояние в см. между НПС self и WP wpName.
int Npc_GetDistToItem (c_npc self, c_item item); - возвращает расстояние в см. между НПС self и предметом item.
int Npc_GetDistToPlayer (c_npc npc1); - возвращает расстояние в см. между npc1 и ГГ.
void Npc_MemoryEntry (c_npc self, int source, c_npc offender, int newsid, c_npc victim); - данная функция записывает для НПС self новости, где source – источник новостей (определено два источника: NEWS_SOURCE_WITNESS – есть свидетель произошедшего, NEWS_SOURCE_GOSSIP – сплетня), newsid – идентификатор новости (определены новости: NEWS_MURDER - убийство, NEWS_ATTACK – атака, NEWS_THEFT – воровство, NEWS_DEFEAT – поражение, NEWS_NERVE – переживание, NEWS_INTERFERE – вмешательство, NEWS_HASDEFEATED – победа), offender – НПС преступник, victim – НПС жертва.
void Npc_MemoryEntryGuild (c_npc self, int source, c_npc offender, int newsid, c_npc victimguild); - работает аналогично предыдущей функции, только жертвой является вся гильдия.
int Npc_HasNews (c_npc self, int newsID, c_npc offender, c_npc victim); - эта функция проверяет, имеет ли НПС self новость с идентификатором newsID о жертве victim и преступнике offender, возвращает 1, если имеет, иначе – 0. (Вместо ненужных параметров можно записать 0).
int Npc_IsNewsGossip (c_npc self, int newsNumber); - возвращает 1, если новость для НПС self является сплетней, иначе – 0.
c_npc Npc_GetNewsWitness (c_npc self, int newsNumber); - возвращает ссылку на свидетеля в новости newsNumber для НПС self.
c_npc Npc_GetNewsVictim (c_npc self, int newsNumber); - возвращает ссылку на жертву в новости newsNumber для НПС self.
c_npc Npc_GetNewsOffender (c_npc self, int newsNumber); - возвращает ссылку на преступника в новости newsNumber для НПС self.
int Npc_DeleteNews (c_npc self, int newsNumber); - удаляет новость newsNumber для НПС self, возвращает 1, исли удаление успешно, иначе – 0.***
void Npc_ChangeAttribute (c_npc self, int atr, int value); - изменяет значение атрибута atr на кол-во единиц value для НПС self.
void Npc_CreateSpell (c_npc self, int spellnr); - НПС self создает заклинание spellnr, оно становится активным, но еще не применяется.
void Npc_LearnSpell (c_npc self, int spellnr); - НПС self выучил заклинание spellnr и может его использовать.
int Npc_GetActiveSpell (c_npc self); - возвращает номер заклинания, которое имеет активным НПС self, иначе - -1.
int Npc_GetActiveSpellCat (c_npc self); - возвращает номер категории активного заклинания у НПС self. Существуют три категории заклинаний:SPELL_GOOD, SPELL_NEUTRAL, SPELL_BAD.
int Npc_SetActiveSpellInfo (c_npc npc, int i1); - задает любое значение i1 для активного заклинания у НПС npc, это значение может использоваться в скриптах, экзешник на него не реагирует. Возвращаемое значение неизвестно.
int Npc_GetActiveSpellLevel (c_npc self); - возвращает уровень активного заклинания у НПС self.
int Npc_HasSpell (c_npc self, int spellID); - возвращает 1, если НПС self может использовать заклинание spellID, иначе – 0.
void Npc_PercEnable (c_npc self, int percID, func function); - функция активации восприятия percID у НПС self, где function – функция обработки восприятия.
void Npc_PercDisable (c_npc self, int percID); - функция деактивации восприятия percID у НПС self.
void Npc_SetPercTime (c_npc self, float seconds); - установка времени реакции в секундах seconds НПС self на событие для активного восприятия.
void Npc_SendPassivePerc (c_npc npc1, int Perc_type, c_npc npc2, c_npc npc3); - функция посылки пассивного восприятия Perc_type от npc1, где npc2 – жертва, npc3 – преступник.
void Npc_SendSinglePerc (c_npc self, c_npc target, int percID); - функция посылки восприятия percID от НПС self к НПС target.
void Npc_PerceiveAll (c_npc self); - разрешает НПС self воспринимать все объекты в зоне действия восприятия, затем можно использовать функции Wld_DetectNpc и Wld_DetectItem.
string Npc_GetDetectedMob (c_npc self); - возвращает имя MOB (Move Object) объекта, который распознал НПС self. Например: если имя MOB объекта " DOOR_OCR _135", то функция возвратит " DOOR ".
int Npc_CanSeeNpc (c_npc npc1, c_npc npc2); - возвращает TRUE, если npc1 может видеть npc2, иначе – FALSE.
int Npc_CanSeeNpcFreeLOS (c_npc self, c_npc other); - возвращает TRUE, если НПС self может видеть НПС other по прямой, без учета угла обзора, иначе – FALSE.
int Npc_CanSeeItem (c_npc npc1, c_item item); - возвращает TRUE, если npc1 может видеть предмет item, иначе – FALSE.
int Npc_CanSeeSource (c_npc self); - возвращает TRUE, если НПС self может видеть источник звука, иначе – FALSE.
int Npc_IsPlayerInMyRoom (c_npc npc); - возвращает TRUE, если НПС npc находится в своем помещении или в помещении своей гильдии, иначе – FALSE.
int Npc_WasPlayerInMyRoom (c_npc npc); - возвращает TRUE, если НПС npc находился в своем помещении или в помещении своей гильдии перед изменением своего положения, иначе – FALSE.
int Npc_GetComrades (c_npc npc); - возвращает 1, если НПС npc имеет друзей, иначе – 0. ***
int Npc_IsDetectedMobOwnedByNpc (c_npc user, c_npc owner); - возвращает значение > 0, если НПС owner является владельцем MOB а, который использует НПС user.
int Npc_IsDetectedMobOwnedByGuild (c_npc user, int ownerguild); - возвращает значение > 0, если гильдия ownerguild является владельцем MOB а, который использует НПС user.
void Npc_GiveItem (c_npc self, c_item item, c_npc other); - НПС self получает предмет item от НПС other.
int Npc_StartItemReactModules (c_npc self, c_npc other, c_item item); - проверяет все модули ItemReact реакции на предмет item, полученный НПС self от НПС other, запускает соответствующую функцию Reaction и возвращает TRUE, если находит модуль, иначе – FALSE.
int Npc_HasOffered (c_npc self, c_npc other, int itemInstance); - проверяет, имеет ли НПС other предмет itemInstance для передачи НПС self, возвращает TRUE, если предмет имеется, иначе – FALSE.
c_item Npc_GetInvItem (c_npc self, int itemInstance); - получить ссылку на предмет, который имеет НПС self с номером itemInstance.
int Npc_HasItems (c_npc n0, int itemInstance); - возвращает количетво предметов itemInstance у НПС n0.
int Npc_GetInvItemBySlot (c_npc self, int category, int slotNr); - возвращает кол- во предметов, которые находятся у НПС self, где category – категория инвентаря (INV_WEAPON, INV_ARMOR, INV_RUNE, INV_MAGIC, INV_FOOD, INV_POTION, INV_DOC, INV_MISC), slotNr – номер слота предмета.
void Npc_RemoveInvItem (c_npc owner, int itemInstance); - предмет itemInstance удаляется из инвентаря НПС owner и из игры.
void Npc_RemoveInvItems (c_npc owner, int itemInstance, int amount); - указанное кол-во amount предметов itemInstance удаляется из инвентаря НПС owner и из игры.
c_item Npc_GetEquippedMeleeWeapon (c_npc n0); - возвращает оружие ближнего радиуса поражения, которым экипирован НПС n0.
c_item Npc_GetEquippedRangedWeapon (c_npc n0); - возвращает оружие дальнего радиуса поражения, которым экипирован НПС n0.
c_item Npc_GetEquippedArmor (c_npc n0); - возвращает доспехи, которыми экипирован НПС n0.
int Npc_HasEquippedWeapon (c_npc self); - возвращает 1, если НПС self экипирован оружием, иначе - 0.
int Npc_HasEquippedMeleeWeapon (c_npc self); - возвращает 1, если НПС self экипирован оружием ближнего радиуса поражения, иначе - 0.
int Npc_HasEquippedRangedWeapon (c_npc self); - возвращает 1, если НПС self экипирован оружием дальнего радиуса поражения, иначе - 0.
int Npc_HasEquippedArmor (c_npc self); - возвращает 1, если НПС self экипирован доспехами, иначе - 0.
void Npc_SetToFistMode (c_npc self); - ставит НПС self в режим кулачного боя.
void Npc_SetToFightMode (c_npc self, int weapon); - ставит НПС self в режим боя с соответствующим оружием weapon.
int Npc_IsInFightMode (c_npc self, int fmode); - возвращает 1, если НПС self находится в боевом режиме fmode, иначе - 0. Заданы следующие боевые режимы: FMODE_NONE – небоевой режим, FMODE_FIST – режим кулачного боя, FMODE_MELEE – боевой режим с оружием ближнего радиуса поражения, FMODE_FAR - боевой режим с оружием дальнего радиуса поражения, FMODE_MAGIC – боевой режим с магией.
c_item Npc_GetReadiedWeapon (c_npc n0); - возвращает ссылку на оружие, которое НПС n0 держит в руке.
int Npc_HasReadiedWeapon (c_npc self); - возвращает 1, если НПС self держит любое оружие в руке, иначе - 0.
int Npc_HasReadiedMeleeWeapon (c_npc self); - возвращает 1, если НПС self держит в руке оружие ближнего радиуса поражения, иначе - 0.
int Npc_HasReadiedRangedWeapon (c_npc self); - возвращает 1, если НПС self держит в руке оружие дальнего радиуса поражения, иначе - 0.
int Npc_HasRangedWeaponWithAmmo (c_npc npc); - возвращает 1, если НПС npc держит в руке или имеет в инвентаре оружие дальнего радиуса поражения с боеприпасами, иначе - 0.
int Npc_GetTarget (c_npc self); - возвращает TRUE, если НПС self имеет цель для поражения (в качестве цели выступает НПС other), иначе – FALSE.
int Npc_GetNextTarget (c_npc self); - выполняется активный поиск цели для НПС self. Если цель находится, то она становится внутренней целью и записывается в переменную
other, если цель не найдена, то внутренняя цель удаляется и other становится недействительным. Критерий поиска цели - в качестве цели возмется враждебный противник, который не мертв или находится не в бессознательном состоянии. Возвращает TRUE, если цель найдена, иначе – FALSE. Внимание: Поиск основывается на активном восприятии НПС self, поэтому, если активное восприятие не установлено, то сначала следует применять функцию Npc_PerceiveAll ().
int Npc_IsNextTargetAvailable (c_npc self); - работает аналогично предыдущей функции, только ни внутренняя цель, ни переменная other не инициализируются.
void Npc_SetTarget (c_npc self, c_npc other); - устанавливает для НПС self в качестве внутренней цели для поражения НПС other.
int Npc_AreWeStronger (c_npc self, c_npc other); - выявляет более сильного НПС среди self и other по следующему алгоритму: если сумма уровней всех НПС (людей и монстров), которые враждебны к self и дружелюбны к other, более чем в два раза превышает сумму уровней всех НПС (людей и монстров), которые дружелюбны к self и враждебны к other, то other сльнее и возвращается FALSE, иначе сильнее self и возвращается TRUE. Замечания: 1. НПС, которые враждебны к обоим, не учитываются. 2. НПС, который враждебен к одному и дружелюбен к другому, будет участвовать в подсчете два раза.
int Npc_IsAiming (c_npc self, c_npc other); - возвращает 1, если НПС other целится в НПС self из оружия дальнего радиуса поражения или магией, иначе – 0.
int Npc_GetTalentSkill (c_npc self, int talent); - возвращает уровень навыка talent, который имеет НПС self.*** Определены следующие способности: NPC_TALENT _1 H – владение одноручником, NPC_TALENT _2 H – владение двуручником, NPC_TALENT_BOW – владение луком, NPC_TALENT_CROSSBOW – владение арбалетом, NPC_TALENT_PICKLOCK – умение вскрывать замки, NPC_TALENT_PICKPOCKET – карманная кража, NPC_TALENT_MAGE – владение магией, NPC_TALENT_SNEAK – умение подкрадываться, NPC_TALENT_REGENERATE – способность восстанавливать здоровье, NPC_TALENT_FIREMASTER – способность мастерски обращаться с огнем, NPC_TALENT_ACROBAT – акробатика.
int Npc_GetTalentValue (c_npc self, int talent); - возвращает кол-во единиц навыка talent, которые имеет НПС self.***
void Npc_SetTalentSkill (c_npc self, int talent, int level); - установить уровень level навыка talent, которым владеет НПС self.***
void Npc_SetTalentValue (c_npc self, int talent, int value); - установить кол-во единиц value навыка talent, которым владеет НПС self.***
Вот мы и закончили рассмотрение большого раздела – функции работы с НПС.

15. Функции искусственного интеллекта (AI_ функции).

void AI_Wait (c_npc n0, float n1); - НПС n0 переводится на n1 секунд в состояние ожидания, в этом состоянии он не делает ничего, но наносимый ущерб регистрируется и работает пассивное восприятие.
void AI_PlayAni (c_npc n0, string s0); - для НПС n0 проигрывается файл анимации s0 (имя файла s0 обязательно пишется заглавными буквами).
void AI_StandUp (c_npc self); - если НПС self находится в состоянии анимации, то проигрывается соответствующее движение, если НПС self находится на MOBSI объекте (стул, кровать и т.д.), то он встает.
void AI_StandUpQuick (c_npc self); - в отличии от предыдущей функции никаких движений не проигрывается, НПС self сразу переводится в стоячее состояние.
void AI_QuickLook (c_npc self, c_npc other); - НПС self быстро бросает взгляд на НПС other. Выполняется только движение головой в течение 2 секунд.
void AI_LookAt (c_npc self, string name); - НПС self смотрит на определенную точку на местности или на объект, где name – имя точки местности или имя VOB объекта.
void AI_LookAtNpc (c_npc self, c_npc other); - НПС self смотрит на НПС other.
void AI_StopLookAt (c_npc self); - НПС self снова смотрит прямо перед собой.
void AI_PointAt (c_npc self, string name); - НПС self указывает на определенную точку на местности или на объект, где name – имя точки местности или имя VOB объекта.
void AI_PointAtNpc (c_npc self, c_npc other); - НПС self указывает на НПС other.
void AI_StopPointAt (c_npc self); - НПС self прекращает указывать на что-нибудь или кого-нибудь.
void AI_TakeItem (c_npc self, c_item item); - НПС self берет (принимает) предмет item.
void AI_DropItem (c_npc self, int itemid); - НПС self выбрасывает на землю или на пол предмет itemid.
void AI_UseItem (c_npc self, int itemInstance); - НПС self использует предмет itemInstance.
void AI_UseItemToState (c_npc self, int itemInstance, int state); - НПС self использует предмет itemInstance до указанного состояния state (-1 – используется полностью).
void AI_TakeMob (c_npc self, string name); - НПС self берет (принимает) MOB (рюкзак, корзину и т.д.) с именем name.***
void AI_DropMob (c_npc self); - НПС self выбрасывает на землю или на пол имеющийся MOB.***
int AI_UseMob (c_npc self, string schemeName, int targetState); - НПС self использует MOB с именем schemeName до указанного состояния targetState. Если указанное состояние у MOBа уже имеется, НПС self приближается к нему, но ничего не делает.
void AI_Waitms (c_npc self, int msec); - НПС self переводится на msec миллисекунд в состояние ожидания, в этом состоянии он не делает ничего, но наносимый ущерб регистрируется и работает пассивное восприятие.***
void AI_CanSeeNpc (c_npc self, c_npc other, func see); - НПС self может увидеть НПС other, где see – какая-то функция (описания не нашел).***
void AI_SetWalkmode (c_npc n, int n0); - установить режим передвижения n0 для НПС n. Определены следующие режимы: NPC_RUN – бег, NPC_WALK – ходьба шагом, NPC_SNEAK – подкрадывание, NPC_RUN_WEAPON – бег с оружием, NPC_WALK_WEAPON – ходьба с оружием, NPC_SNEAK_WEAPON – подкрадывание с оружием.
void AI_GotoWP (c_npc n0, string s0); - НПС n0 перемещается в указанную WP s0.
void AI_GotoFP (c_npc self, string fpName); - НПС n0 перемещается в указанную FP fpName, расположенную в пределах 20 метров. Критерий поиска FP аналогичен используемому в функции Wld_IsFPAvailable.
void AI_GotoNextFP (c_npc self, string fpName); - работает аналогично предыдущей функции, только критерий поиска FP аналогичен используемому в функции Wld_IsNextFPAvailable.
void AI_GotoNpc (c_npc self, c_npc other); - НПС self перемещается к НПС other.
void AI_GotoItem (c_npc self, c_item item); - НПС self перемещается к предмету item.
void AI_GotoSound (c_npc n0); - НПС self перемещается к источнику звука.
void AI_Teleport (c_npc self, string waypoint); - телепортирует НПС self в новую локацию waypoint.
void AI_TurnToNpc (c_npc n0, c_npc n1); - НПС n0 поварачивается к НПС n1 лицом.
void AI_TurnAway (c_npc n0, c_npc n1); - НПС n0 поварачивается к НПС n1 спиной.
void AI_WhirlAround (c_npc self, c_npc other); - НПС self быстро поварачивается к НПС other лицом. (Делает оборот).
void AI_WhirlAroundToSource (c_npc self); - НПС self быстро поварачивается лицом к какому-то источнику.*** (Описания не нашел).
void AI_TurnToSound (c_npc self); - НПС self поварачивается лицом к источнику звука.
void AI_AlignToWP (c_npc self); - НПС self выравнивается в WP точке по направлению стрелки, заданной в Spacer.
void AI_AlignToFP (c_npc self); - НПС self выравнивается в FP точке по направлению стрелки, заданной в Spacer.***
void AI_Dodge (c_npc npc); - НПС npc отклоняется назад. (Способ защиты при атаке противника).
void AI_PlayAniBS (c_npc npc, string aniname, int bodystate); - для НПС npc проигрывается файл анимации aniname для определенного состояния тела bodystate.
void AI_PlayCutscene (c_npc self, string csName); - для НПС self проигрывается Cutscene с именем csName, заданная в скриптах.
void AI_DrawWeapon (c_npc n0); - НПС n0 вытаскивает оружие, которым экипирован.
void AI_RemoveWeapon (c_npc n0); - НПС n0 прячет оружие.
void AI_ReadyMeleeWeapon (c_npc self); - НПС self готовит оружие ближнего радиуса поражения к бою.
void AI_ReadyRangedWeapon (c_npc self); - НПС self готовит оружие дальнего радиуса поражения к бою.
void AI_Attack (c_npc self); - НПС self начинает сражение (эта функция должна вызываться внутри ZS_Attack_Loop). Атакуется внутренняя цель, которая была задана функцией Npc_SetTarget или Npc_GetNextTarget.
void AI_FinishingMove (c_npc self, c_npc other); - логическое завершение операции приближения (поворота) НПС self к НПС other.
void AI_Defend (c_npc self); - НПС self парирует удар противника (защищается). Выполняется только во время атаки противника.
void AI_Flee (c_npc self); - НПС self убегает от противника (эта функция должна вызываться внутри ZS_Loop). Предварительно функцией Npc_SetTarget должна быть установлена внутренняя цель, от которой НПС self должен убежать.
void AI_AimAt (c_npc attacker, c_npc target); - НПС attacker целится из оружия дальнего радиуса поражения в НПС target.
void AI_StopAim (c_npc attacker); - НПС attacker прекращает целиться из оружия дальнего радиуса поражения.
void AI_ShootAt (c_npc attacker, c_npc target); - НПС attacker стреляет из оружия дальнего радиуса поражения в НПС target.
void AI_CombatReactToDamage (c_npc self); - реакция НПС self на повреждение во время боя.***
void AI_LookForItem (c_npc self, int instance); - функция показывает определенный предмет instance, который имеется у НПС self. (Например: золотой меч разрушения).
void AI_EquipBestMeleeWeapon (c_npc self); - в инвентаре НПС self ищется самое лучшее оружие ближнего радиуса поражения и вешается на пояс.
void AI_EquipBestRangedWeapon (c_npc self); - в инвентаре НПС self ищется самое лучшее оружие дальнего радиуса поражения и вешается на спину.
void AI_EquipBestArmor (c_npc self); - в инвентаре НПС self ищутся и одеваются самые лучшие доспехи.
void AI_UnequipWeapons (c_npc self); - все экипированное оружие НПС self убирается в инвентарь.
void AI_UnequipArmor (c_npc self); - одетые доспехи НПС self убираются в инвентарь.
void AI_EquipArmor (c_npc self, int armor); - НПС self одевает доспехи armor, которые должны находиться в его инвентаре.***
void AI_ReadySpell (c_npc self, int spellID, int investMana); - НПС self берет в руку заклинание spellID со стоимостью маны investMana.
void AI_UnreadySpell (c_npc self); - НПС self прячет в инвентарь заклинание, которое имеет в руке.
void AI_Output (c_npc self, c_npc target, string outputName); - данная функция реализует диалог, НПС self говорит фразу outputName для НПС target. Текст фразы должен располагаться в скриптах в виде комментария к функции. (например: AI_Output () //текст фразы).
void AI_OutputSVM (c_npc self, c_npc target, string svmname); - данная функция реализует SVM (Standart Voice Module) диалог, НПС self говорит фразу svmname для НПС target. Текст фразы должен располагаться в скриптах в файле svm.d (в одном из соответствующих SVM_ модулей) в виде комментария к строке с именем svmname. (например: StopMagic = svmname; //текст фразы).
void AI_OutputSVM_Overlay (c_npc self, c_npc target, string svmname); -выполняется аналогично предыдущей функции, фраза выдается быстро, нет ожидания при разговоре следующей AI_ команды. Используется для комментариев перед сражением и во время сражения.
void AI_WaitTillEnd (c_npc self, c_npc other); - НПС self ждет от НПС other ответа на свою фразу. (Не выполняется перед функцией AI_OutputSVM_Overlay).
void AI_Ask (c_npc self, func answerYes, func answerNo); - определяет, как НПС self будет отвечать на сказанную фразу, при выборе ответа «Да» - выполняется функция answerYes, иначе – функция answerNo. Эти функции должны быть описаны заранее.
void AI_AskText (c_npc self, func funcYes, func funcNo, string strYes, string strNo); - работает аналогично предыдущей функции, только для вариантов ответов (кроме функций) могут быть заданы фразы ответов strYes, strNo.
void AI_WaitForQuestion (c_npc self, func scriptFunc); - НПС self ждет ответа или вопроса в течение 20 секунд, если в это время он поступает, то выполняется функция scriptFunc.
void AI_ProcessInfos (c_npc self); - эта функция запускает диалог для НПС self с возможностью выбора вариантов ответов/вопросов.***
void AI_StopProcessInfos (c_npc npc); - режим диалога НПС npc, начатый предыдущей функцией, заканчивается.
void AI_StartState (c_npc self, func what, int stateBehaviour, string wpName); - переводит НПС self в соответствующее состояние, описанное функцией what, где stateBehaviour = 0 – выполняется последовательность состояний, 1 – выполняется только функция конечного состояния, wpName – имя WP точки (если "", то состояние изменяется на месте расположения НПС).
void AI_SetNpcsToState (c_npc self, func aiStateFunc, int radius); - переводит всех НПС, находящихся от НПС self на расстоянии radius сантиметров, в соответствующее состояние, описанное функцией aiStateFunc.
void AI_ContinueRoutine (c_npc self); - продолжает выполнение распорядка дня НПС self.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема седьмая: Встроенные функции Готики 2.

В основном в Готике 2 используются функции Готики 1, но есть несколько дополнительных функций, их мы и рассмотрим.
int AI_PrintScreen (string msg, int posx, int posy, string font, int timeSec); - выводит на экран строку текста msg (имя шрифта – font) с координатами posx, posy (диапазон от 0 до 99% размера экрана, -1 означает вывод по центру соответствующей оси экрана) на время timeSec (в секундах).
void AI_Snd_Play (c_npc self, string s0); - воспроизвести звуковой файл с именем s0 для НПС self.
void AI_Snd_Play3D (c_npc self, c_npc n0, string s0); - воспроизвести звуковой файл с именем s0 для НПС self.
void AI_PlayFX (c_npc self, c_npc n0, string s0); - воспроизвести видео-файл с именем s0 для НПС self.
void AI_StopFX (c_npc self, string s0); - остановить воспроизведение видео-файла с именем s0 для НПС self.
int PlayVideoEx (string video, int aa, int bb); - показать видео файл video (c расширением BIK), возвращает 1, если видео показано, 0 – в случае ошибки. Трактование параметров aa и bb не знаю, в скриптах они имеют значение TRUE и FALSE.
void ExitSession () – используется вместо функции ExitGame (), хотя она тоже сохранена.
int GameInitGerman () – просто всегда возвращает 1.
В английской версии экзешника еще есть функции - int GameInitEnglish () и int GameInitEngintl (), их назначение мне неизвестно.
int Wld_DetectNpcExAtt (c_npc self, int instance, func aiState, int guild, int detectPlayer, int xxx); - эта функция инициализирует глобальную переменную скриптов other, отличную от НПС self, где instance – производная от класса c_npc, которая должна быть найдена и проинициализирована (-1 – любая производная), guild – гильдия, членом которой должен быть искомый НПС (-1 – любая гильдия), aiState – функция AI состояния, в котором должен находится искомый НПС (NOFUNC – любое AI состояние). Функция возвращает 1 в случае успешного завершения (other инициализирован найденным НПС), 0 – неудача (other не определен), параметр detectPlayer указывает, исключить ли игрока (ГГ) из поиска (0 – исключить, 1 – нет). В этой функции, по сравнению с Wld_DetectNpcEx, добавлен параметр ххх, к сожалению мне про него ничего не известно (возможно это какой-нибудь атрибут).
int Wld_IsRaining (); – возвращает 1, если идет дождь, иначе – 0.
void Wld_StopEffect (string name); - останавливает проигрывание эффекта с именем name, запущенного функцией Wld_PlayEffect.
void Doc_SetLevelCoords (int Document, int Left, int Top, int Right, int Bottom); - устанавливает границы области, отображаемой на карте (границы задаются в абсолютных координатах уровня), где: Document – обрабатываемый документ, Left, Top, Right и Bottom – задаваемые границы.
int Npc_GetLastHitSpellID (c_npc self); - возвращает номер заклинания, которое НПС self применил последним.
int Npc_GetLastHitSpellCat (c_npc self); - возвращает категорию заклинания, которое НПС self применил последним.
int Npc_GetActiveSpellIsScroll (c_npc self); - проверяет, является ли активное заклинание у НПС self свитком, если да – возвращает 1, иначе – 0.
void Npc_ClearInventory (c_npc self); - очищает весь инвентарь у НПС self.
int Npc_GetHeightToNpc (c_npc npc1, c_npc npc2); - возвращает расстояние в см. по высоте между НПС npc1 и npc2.
int Npc_GetHeightToItem (c_npc self, c_item item); - возвращает расстояние в см. по высоте между НПС self и предметом item.
c_npc Npc_GetLookAtTarget (c_npc self); - инициализирует глобальную переменную target ссылкой на НПС, на которого смотрит НПС self.
void Npc_StopAni (c_npc self, string name); - остановить проигрывание файла анимации с именем name для НПС self.
int Npc_IsDrawingWeapon (c_npc self); - возвращает номер оружия, которое НПС self держит в руках, иначе – 0.
int Npc_IsDrawingSpell (c_npc self); - возвращает номер заклинания, которое применяет НПС self, иначе – 0.
int Npc_IsInPlayersRoom (c_npc self); - возвращает 1, если НПС self находится в помещении, которое принадлежит ГГ, иначе – 0.
c_npc Npc_GetPortalOwner (c_npc self); - возвращает НПС-владельца помещения (области), в котором находится НПС self.
int Npc_GetPortal Guild (c_npc self); - возвращает номер гильдии владельца помещения (области), в котором находится НПС self.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Уроки скриптологии, часть 2.
Тема первая: Глобальные константы.

Практически все глобальные константы описаны в файле ..\_intern\constants.d
// Шрифты для функции PrintScreen
const string FONT_Screen = "FONT_OLD_20_WHITE.TGA"; //обычный экранный шрифт
const string FONT_ScreenSmall = "FONT_OLD_10_WHITE.TGA"; //мелкий экранный шрифт
const string FONT_Book = "FONT_10_BOOK.TGA"; //шрифт текста документов
const string FONT_BookHeadline = "FONT_20_BOOK.TGA"; //шрифт заголовков документов
// Стоимость маны для всех свитков заклинаний
const int SPL_Cost_Scroll = 5;
// Индексы атрибутов НПС
const int ATR_HITPOINTS = 0; //Текущая жизнь
const int ATR_HITPOINTS_MAX = 1; //Макс. жизнь
const int ATR_MANA = 2; //Текущая мана
const int ATR_MANA_MAX = 3; //Макс. мана
const int ATR_STRENGTH = 4; //Сила
const int ATR_DEXTERITY = 5; //Ловкость
const int ATR_REGENERATEHP = 6; //Регенерация жизни в секунду
const int ATR_REGENERATEMANA = 7; //Регенерация маны в секунду
const int ATR_INDEX_MAX = 8; //Макс. размерность массива атрибутов НПС
// Флаги НПС
const int NPC_FLAG_FRIEND = 1 << 0; //Друг (не используется, заменен на aivar[])
const int NPC_FLAG_IMMORTAL = 1 << 1; //Неуязвимый
const int NPC_FLAG_GHOST = 1 << 2; //Полупрозрачный (эквивалентен флагу 'GhostAlpha' в Gothic.ini секция [INTERNAL])
// Режимы борьбы
const int FMODE_NONE = 0; //Выключен
const int FMODE_FIST = 1; //Кулачный бой
const int FMODE_MELEE = 2; //Оружие ближнего радиуса поражения
const int FMODE_FAR = 5; //Оружие дальнего радиуса поражения
const int FMODE_MAGIC = 7; //Магия
// Режимы передвижения
const int NPC_RUN = 0; //Бег
const int NPC_WALK = 1; //Ходьба
const int NPC_SNEAK = 2; //Подкрадывание
const int NPC_RUN_WEAPON = 0 + 128; //Бег с оружием
const int NPC_WALK_WEAPON = 1 + 128; //Ходьба с оружием
const int NPC_SNEAK_WEAPON = 2 + 128; //Подкрадывание с оружием
// Флаги брони
const int WEAR_TORSO = 1; //Верхняя часть туловища (Доспехи)
const int WEAR_HEAD = 2; //Голова (Шлем)
const int WEAR_EFFECT = 16; //Оказывает эффект при ношении
// Категории инвентаря
const int INV_WEAPON = 1; //Оружие
const int INV_ARMOR = 2; //Броня
const int INV_RUNE = 3; //Руны
const int INV_MAGIC = 4; //Магия
const int INV_FOOD = 5; //Продукты питания
const int INV_POTION = 6; //Напитки
const int INV_DOC = 7; //Документы
const int INV_MISC = 8; //Разное
const int INV_CAT_MAX = 9; //Макс. размерность категорий инвентаря
// Вместимость инвентаря (программой игнорируется, инвентарь неограниченный!)
const int INV_MAX_WEAPONS = 6;
const int INV_MAX_ARMORS = 2;
const int INV_MAX_RUNES = 1000;
const int INV_MAX_FOOD = 15;
const int INV_MAX_DOCS = 1000;
const int INV_MAX_POTIONS = 1000;
const int INV_MAX_MAGIC = 1000;
const int INV_MAX_MISC = 1000;
// Кол-во строк текста описания предметов
const int ITM_TEXT_MAX = 6;
// Флаги предметов
// (категории)

const int ITEM_KAT_NONE = 1 << 0; //Прочее
const int ITEM_KAT_NF = 1 << 1; //Оружие ближнего радиуса поражения
const int ITEM_KAT_FF = 1 << 2; //Оружие дальнего радиуса поражения
const int ITEM_KAT_MUN = 1 << 3; //Боеприпасы (мульти)
const int ITEM_KAT_ARMOR = 1 << 4; //Броня
const int ITEM_KAT_FOOD = 1 << 5; //Продукты питания (мульти)
const int ITEM_KAT_DOCS = 1 << 6; //Документы
const int ITEM_KAT_POTIONS = 1 << 7; //Напитки
const int ITEM_KAT_LIGHT = 1 << 8; //Источники света
const int ITEM_KAT_RUNE = 1 << 9; //Руны/Свитки заклинаний
const int ITEM_KAT_MAGIC = 1 << 31; //Кольца/Амулеты/Пояса
const int ITEM_KAT_KEYS = ITEM_KAT_NONE; //Ключи
// (типы оружия)
const int ITEM_DAG = 1 << 13; //Клинок (не используется)
const int ITEM_SWD = 1 << 14; //Меч
const int ITEM_AXE = 1 << 15; //Топор
const int ITEM_2HD_SWD = 1 << 16; //Друручный меч
const int ITEM_2HD_AXE = 1 << 17; //Двуручный топор
const int ITEM_SHIELD = 1 << 18; //Щит (не используется)
const int ITEM_BOW = 1 << 19; //Лук
const int ITEM_CROSSBOW = 1 << 20; //Арбалет
// (типы магических предметов)
const int ITEM_RING = 1 << 11; //Кольцо
const int ITEM_AMULET = 1 << 22; //Амулет
const int ITEM_BELT = 1 << 24; //Пояс
// (атрибуты предметов)
const int ITEM_DROPPED = 1 << 10; //Выброшенный предмет (внутренний флаг!)
const int ITEM_MISSION = 1 << 12; //Предмет миссии
const int ITEM_MULTI = 1 << 21; //Складываемый по несколько штук
const int ITEM_NFOCUS = 1 << 23; //Не в фокусе (внутренний флаг!)
const int ITEM_CREATEAMMO = 1 << 25; //Боеприпасы производятся сами (магически)
const int ITEM_NSPLIT = 1 << 26; //Неделимый предмет
const int ITEM_DRINK = 1 << 27; //Можно пить (не используется)
const int ITEM_TORCH = 1 << 28; //Факел
const int ITEM_THROW = 1 << 29; //Можно бросить (не используется)
const int ITEM_ACTIVE = 1 << 30; //Активный (внутренний флаг!)
// Типы наносимых повреждений
const int DAM_INVALID = 0; //(применения не нашел)
const int DAM_BARRIER = 1; //(применения не нашел)
const int DAM_BLUNT = DAM_BARRIER << 1; //Повреждение тупым оружием (молоты, дубины, кулаки)
const int DAM_EDGE = DAM_BLUNT << 1; //Повреждение острым оружием (мечи, шпаги, топоры)
const int DAM_FIRE = DAM_EDGE << 1; //Повреждение огнем
const int DAM_FLY = DAM_FIRE << 1; //Повреждение нокаутом (после удара НПС отлетает и падает)
const int DAM_MAGIC = DAM_FLY << 1; //Повреждение магией
const int DAM_POINT = DAM_MAGIC << 1; //Точечное повреждение (луки, арбалеты)
const int DAM_FALL = DAM_POINT << 1; //Повреждение от падения
// Индексы значений массива наносимых повреждений (имена индексов соответствуют именам типов)
const int DAM_INDEX_BARRIER = 0;
const int DAM_INDEX_BLUNT = DAM_INDEX_BARRIER + 1;
const int DAM_INDEX_EDGE = DAM_INDEX_BLUNT + 1;
const int DAM_INDEX_FIRE = DAM_INDEX_EDGE + 1;
const int DAM_INDEX_FLY = DAM_INDEX_FIRE + 1;
const int DAM_INDEX_MAGIC = DAM_INDEX_FLY + 1;
const int DAM_INDEX_POINT = DAM_INDEX_MAGIC + 1;
const int DAM_INDEX_FALL = DAM_INDEX_POINT + 1;
const int DAM_INDEX_MAX = DAM_INDEX_FALL + 1; //Макс. размерность массива наносимых повреждений
// Другие константы наносимых повреждений
const int NPC_ATTACK_FINISH_DISTANCE = 180; //???
const int NPC_BURN_TICKS_PER_DAMAGE_POINT = 1000; //???
const int NPC_BURN_DAMAGE_POINTS_PER_INTERVALL = 50; //???
const int DAM_CRITICAL_MULTIPLIER = 2; //Коэффициент умножения для критического повреждения (не употребляется)
const int BLOOD_SIZE_DIVISOR = 1000; //???
const int BLOOD_DAMAGE_MAX = 200; //???
const int DAMAGE_FLY_CM_MAX = 2000; //???
const int DAMAGE_FLY_CM_MIN = 300; //???
const int DAMAGE_FLY_CM_PER_POINT = 5; //???
const int NPC_DAM_DIVE_TIME = 100; //???
const int IMMUNE = -1; //Иммунитет к повреждению
// На каком расстоянии НПС перестают сражаться
// Коэффициент к дистанции (BASE + дистанция поражения оружием)

const float NPC_COLLISION_CORRECTION_SCALER = 0.75;
// Типы защиты (имена соответствуют типам наносимых повреждений)
const int PROT_BARRIER = DAM_INDEX_BARRIER;
const int PROT_BLUNT = DAM_INDEX_BLUNT;
const int PROT_EDGE = DAM_INDEX_EDGE;
const int PROT_FIRE = DAM_INDEX_FIRE;
const int PROT_FLY = DAM_INDEX_FLY;
const int PROT_MAGIC = DAM_INDEX_MAGIC;
const int PROT_POINT = DAM_INDEX_POINT;
const int PROT_FALL = DAM_INDEX_FALL;
const int PROT_INDEX_MAX = DAM_INDEX_MAX; //Макс. размерность массива защиты
// Активные восприятия
const int PERC_ASSESSPLAYER = 1; //Восприятие ГГ
const int PERC_ASSESSENEMY = 2; //Восприятие врага
const int PERC_ASSESSFIGHTER = 3; //Восприятие в сражении
const int PERC_ASSESSBODY = 4; //Восприятие тела
const int PERC_ASSESSITEM = 5; //Восприятие предмета
// Чувства
const int SENSE_SEE = 1 << 0; //Зрение
const int SENSE_HEAR = 1 << 1; //Слух
const int SENSE_SMELL = 1 << 2; //Обоняние
// Пассивные восприятия
const int PERC_ASSESSMURDER = 6; //Восприятие убийства
const int PERC_ASSESSDEFEAT = 7; //Восприятие поражения
const int PERC_ASSESSDAMAGE = 8; //Восприятие повреждения
const int PERC_ASSESSOTHERSDAMAGE = 9; //Восприятие других повреждений
const int PERC_ASSESSTHREAT = 10; //Восприятие угрозы
const int PERC_ASSESSREMOVEWEAPON = 11; //Восприятие от "зачехления" оружия
const int PERC_OBSERVEINTRUDER = 12; //Восприятие наблюдения злоумышленника
const int PERC_ASSESSFIGHTSOUND = 13; //Восприятие звука сражения
const int PERC_ASSESSQUIETSOUND = 14; //Восприятие тихих звуков
const int PERC_ASSESSWARN = 15; //Восприятие предупреждения
const int PERC_CATCHTHIEF = 16; //Восприятие выгоды воровства
const int PERC_ASSESSTHEFT = 17; //Восприятие воровства
const int PERC_ASSESSCALL = 18; //Восприятие обращения (речь)
const int PERC_ASSESSTALK = 19; //Восприятие разговора
const int PERC_ASSESSGIVENITEM = 20; //Восприятие торговли
const int PERC_ASSESSFAKEGUILD = 21; //Восприятие "поддельной гильдии" (посылается при превращении НПС)
const int PERC_MOVEMOB = 22; //Восприятие передвижения объекта (не НПС)
const int PERC_MOVENPC = 23; //Восприятие передвижения НПС
const int PERC_DRAWWEAPON = 24; //Восприятие вытаскивания оружия
const int PERC_OBSERVESUSPECT = 25; //Восприятие наблюдения подозреваемого
const int PERC_NPCCOMMAND = 26; //Восприятие команды НПС
const int PERC_ASSESSMAGIC = 27; //Восприятие магии
const int PERC_ASSESSSTOPMAGIC = 28; //Восприятие прекращения колдовства
const int PERC_ASSESSCASTER = 29; //Восприятие колдующего (посылается при изменении маны)
const int PERC_ASSESSSURPRISE = 30; //Восприятие неожиданности
const int PERC_ASSESSENTERROOM = 31; //Восприятие входа в помещение (область)
const int PERC_ASSESSUSEMOB = 32; //Восприятие использования объекта (открытие двери, сундука)
// Способы распространения новостей
const int NEWS_DONT_SPREAD = 0; //Новости не распространяются
const int NEWS_SPREAD_NPC_FRIENDLY_TOWARDS_VICTIM = 1; //Друзьями жертвы
const int NEWS_SPREAD_NPC_FRIENDLY_TOWARDS_WITNESS = 2; //Друзьями свидетеля
const int NEWS_SPREAD_NPC_FRIENDLY_TOWARDS_OFFENDER = 3; //Друзьями обидчика
const int NEWS_SPREAD_NPC_SAME_GUILD_VICTIM = 4; //Гильдией жертвы
// Константы новостей
const int IMPORTANT = 1; //Важная новость
// Статусы информации

const int INF_TELL = 0; //Сказанная информация
const int INF_UNKNOWN = 2; //Источник информации неизвестен
// Статусы миссий

const int LOG_RUNNING = 1; //Миссия выполняется
const int LOG_SUCCESS = 2; //Миссия успешно завершена
const int LOG_FAILED = 3; //Миссия провалена
const int LOG_OBSOLETE = 4; //Миссия завершена в другом направлении (был выбор вариантов завершения)
// Отношения
const int ATT_FRIENDLY = 3; //Друг
const int ATT_NEUTRAL = 2; //Нейтральный
const int ATT_ANGRY = 1; //Сердитый, злой
const int ATT_HOSTILE = 0; //Враг
// Гильдии
const int GIL_NONE = 0; //Отсутствует
const int GIL_HUMAN = 1; //Люди (специальная гильдия, набор констант для этой гильдии описан в файле Species.d)
const int GIL_PAL = 1; //Паладины
const int GIL_MIL = 2; //Милиционеры
const int GIL_VLK = 3; //Горожане
const int GIL_KDF = 4; //Маги огня
const int GIL_NOV = 5; //Маги послушники
const int GIL_DJG = 6; //Охотники на драконов
const int GIL_SLD = 7; //Ополчение
const int GIL_BAU = 8; //Крестьяне
const int GIL_BDT = 9; //Бандиты
const int GIL_STRF = 10; //Заключенные
const int GIL_DMT = 11; //Черные маги
const int GIL_OUT = 12; //Чужеземцы
const int GIL_PIR = 13; //Пираты
const int GIL_KDW = 14; //Маги воды
const int GIL_EMPTY_D = 15; //(пусто)
//-----------------------------------------------
const int GIL_PUBLIC = 15; //Публичная гильдия
//-----------------------------------------------

const int GIL_SEPERATOR_HUM = 16; //Разделитель между людьми и животными
const int GIL_MEATBUG = 17; //Мясной жук
const int GIL_SHEEP = 18; //Овца
const int GIL_GOBBO = 19; //Гоблин / Черный гоблин
const int GIL_GOBBO_SKELETON = 20; //Скелет гоблина
const int GIL_SUMMONED_GOBBO_SKELETON = 21; //Вызванный Скелет гоблина
const int GIL_SCAVENGER = 22; //Падальщик / Зубастик
const int GIL_GIANT_RAT = 23; //Крыса
const int GIL_GIANT_BUG = 24; //Полевой жук
const int GIL_BLOODFLY = 25; //Кровяной шершень
const int GIL_WARAN = 26; //Ящерица / Огненная ящерица
const int GIL_WOLF = 27; //Волк / Варг
const int GIL_SUMMONED_WOLF = 28; //Вызванный Волк
const int GIL_MINECRAWLER = 29; //Ползун / Воин ползунов
const int GIL_LURKER = 30; //Шныг
const int GIL_SKELETON = 31; //Скелет
const int GIL_SUMMONED_SKELETON = 32; //Вызванный Скелет
const int GIL_SKELETON_MAGE = 33; //Маг скелетов
const int GIL_ZOMBIE = 34; //Зомби
const int GIL_SNAPPER = 35; //Глорх / Остер / Расчленитель
const int GIL_SHADOWBEAST = 36; //Мракорис
const int GIL_SHADOWBEAST_SKELETON = 37; //Скелет мракориса
const int GIL_HARPY = 38; //Гарпия
const int GIL_STONEGOLEM = 39; //Каменный голем
const int GIL_FIREGOLEM = 40; //Огненный голем
const int GIL_ICEGOLEM = 41; //Ледяной голем
const int GIL_SUMMONED_GOLEM = 42; //Вызванный Голем
const int GIL_DEMON = 43; //Демон / Лорд демонов
const int GIL_SUMMONED_DEMON = 44; //Вызванный Демон
const int GIL_TROLL = 45; //Троль / Черный троль
const int GIL_SWAMPSHARK = 46; //Болотожор
const int GIL_DRAGON = 47; //Дракон
const int GIL_MOLERAT = 48; //Кротокрыс
const int GIL_ALLIGATOR = 49; //Алигатор
const int GIL_SWAMPGOLEM = 50; //Болотный голем
const int GIL_Stoneguardian = 51; //Каменный сторож
const int GIL_Gargoyle = 52; //Пантера / Огненный дух мракориса
const int GIL_Empty_A = 53; //(пусто)
const int GIL_SummonedGuardian = 54; //Вызванный Каменный сторож
const int GIL_SummonedZombie = 55; //Вызванный Зомби
const int GIL_EMPTY_B = 56; //(пусто)
const int GIL_EMPTY_C = 57; //(пусто)
const int GIL_SEPERATOR_ORC = 58; //Разделитель животных от орков
const int GIL_ORC = 59; //Орк / Шаман орков / Воин орков
const int GIL_FRIENDLY_ORC = 60; //Ур-Шак
const int GIL_UNDEADORC = 61; //Орк нежить
const int GIL_DRACONIAN = 62; //Ящер
const int GIL_EMPTY_X = 63; //(пусто)
const int GIL_EMPTY_Y = 64; //(пусто)
const int GIL_EMPTY_Z = 65; //(пусто)
const int GIL_MAX = 66; //Макс. количество гильдий
// Класс описания гильдий
class c_gilvalues
{
var int WATER_DEPTH_KNEE [GIL_MAX]; //Глубина воды до колена
var int WATER_DEPTH_CHEST [GIL_MAX]; //Глубина воды до груди
var int JUMPUP_HEIGHT [GIL_MAX]; //Высота прыжка
// var int JUMPUP_FORCE [GIL_MAX];

var int SWIM_TIME [GIL_MAX]; //Время плавания
var int DIVE_TIME [GIL_MAX]; //Время пребывания под водой
var int STEP_HEIGHT [GIL_MAX]; //Ширина шага
var int JUMPLOW_HEIGHT [GIL_MAX]; //Высота низкого прыжка
var int JUMPMID_HEIGHT [GIL_MAX]; //Высота среднего прыжка
var int SLIDE_ANGLE [GIL_MAX]; //Угол начала скольжения на наклонной плоскости
var int SLIDE_ANGLE2 [GIL_MAX]; //???
var int DISABLE_AUTOROLL [GIL_MAX]; //???
var int SURFACE_ALIGN [GIL_MAX]; //???
var int CLIMB_HEADING_ANGLE [GIL_MAX]; //Какие-то углы подъема
var int CLIMB_HORIZ_ANGLE [GIL_MAX]; //
var int CLIMB_GROUND_ANGLE [GIL_MAX]; //
var int FIGHT_RANGE_BASE [GIL_MAX]; //Какие-то диапазоны борьбы
var int FIGHT_RANGE_FIST [GIL_MAX]; //
var int FIGHT_RANGE_G [GIL_MAX]; //
var int FIGHT_RANGE_1HS [GIL_MAX]; //
var int FIGHT_RANGE_1HA [GIL_MAX]; //
var int FIGHT_RANGE_2HS [GIL_MAX]; //
var int FIGHT_RANGE_2HA [GIL_MAX]; //
var int FALLDOWN_HEIGHT [GIL_MAX]; //Высота падения без повреждения
var int FALLDOWN_DAMAGE [GIL_MAX]; //Повреждение от падения с высоты
var int BLOOD_DISABLED [GIL_MAX]; //Уровень показа крови
var int BLOOD_MAX_DISTANCE [GIL_MAX]; //Макс. радиус брызг крови в см.
var int BLOOD_AMOUNT [GIL_MAX]; //Количество крови
var int BLOOD_FLOW [GIL_MAX]; //???
var string BLOOD_EMITTER [GIL_MAX]; //Источник крови
var string BLOOD_TEXTURE [GIL_MAX]; //Текстура крови
var int TURN_SPEED [GIL_MAX]; //Скорость разворота
};
// Типы звуков
const int NPC_SOUND_DROPTAKE = 1; //Звук капель
const int NPC_SOUND_SPEAK = 3; //Звук разговора
const int NPC_SOUND_STEPS = 4; //Звук шагов
const int NPC_SOUND_THROWCOLL = 5; //Звук летящей стрелы, болта
const int NPC_SOUND_DRAWWEAPON = 6; //Звук доставаемого оружия
const int NPC_SOUND_SCREAM = 7; //Звук крика
const int NPC_SOUND_FIGHT = 8; //Звук сражения
// Типы материалов
const int MAT_WOOD = 0; //Деревянный
const int MAT_STONE = 1; //Каменный
const int MAT_METAL = 2; //Металлический
const int MAT_LEATHER = 3; //Кожаный
const int MAT_CLAY = 4; //Глиняный
const int MAT_GLAS = 5; //Стеклянный
// Записи дневника
const int LOG_MISSION = 0; //Миссии
const int LOG_NOTE = 1; //Заметки
// Другие константы
const int TIME_INFINITE = -1000000 / 1000; //Бесконечное время ???
const int NPC_VOICE_VARIATION_MAX = 10; //Макс. кол-во голосов НПС
const float TRADE_VALUE_MULTIPLIER = 0.15; //Коэффициент стоимости предмета, которую платит торговец
const string TRADE_CURRENCY_INSTANCE = "ITMI_GOLD"; //Имя валюты для расчетов
//************************************
// Заклинания
//************************************
// Константы категорий

const int SPELL_GOOD = 0; //Хорошее
const int SPELL_NEUTRAL = 1; //Нейтральное
const int SPELL_BAD = 2; //Плохое
// Константы управления
const int SPL_DONTINVEST = 0; //Дальнейшее инвестирование маны на зарядку заклинания невозможно (мало или нет маны)
const int SPL_RECEIVEINVEST = 1; //Нужное количество маны израсходовано на зарядку (заклинание готово к действию)
const int SPL_SENDCAST = 2; //Старт заклинания с действием
const int SPL_SENDSTOP = 3; //Заклинание заканчивается без эффекта (мало маны)
const int SPL_NEXTLEVEL = 4; //Переход на следующий уровень зарядки заклинания
const int SPL_STATUS_CANINVEST_NO_MANADEC = 8; //Инвестированного количества маны недостаточно для перехода на следующий уровень
const int SPL_FORCEINVEST = 1 << 16; //Какой-то флаг управляющий инвестированием маны ???
// Константы цели
const int TARGET_COLLECT_NONE = 0; //Цель определяется самим заклинанием
const int TARGET_COLLECT_CASTER = 1; //Цель - кастующий
const int TARGET_COLLECT_FOCUS = 2; //Цель - визуальный объект в фокусе
const int TARGET_COLLECT_ALL = 3; //Цель - все объекты в радиусе поражения
const int TARGET_COLLECT_FOCUS_FALLBACK_NONE = 4; //Цель - визуальный объект в фокусе, при потере фокуса траектория устанавливается заклинанием
const int TARGET_COLLECT_FOCUS_FALLBACK_CASTER = 5; //Цель - визуальный объект в фокусе, при потере фокуса целью становится кастующий
const int TARGET_COLLECT_ALL_FALLBACK_NONE = 6; //Цель - все объекты в радиусе поражения, если объектов нет траектория устанавливается заклинанием
const int TARGET_COLLECT_ALL_FALLBACK_CASTER = 7; //Цель - все объекты в радиусе поражения, если объектов нет целью становится кастующий
const int TARGET_TYPE_ALL = 1; //Цель - все и всё
const int TARGET_TYPE_ITEMS = 2; //Цель - предмет
const int TARGET_TYPE_NPCS = 4; //Цель - НПС
const int TARGET_TYPE_ORCS = 8; //Цель - орк
const int TARGET_TYPE_HUMANS = 16; //Цель - человек
const int TARGET_TYPE_UNDEAD = 32; //Цель - неуязвимый
// Идентификаторы заклинаний (ID)
// Руны Паладинов

const int SPL_PalLight = 0; //Святой свет
const int SPL_PalLightHeal = 1; //Малое лечение
const int SPL_PalHolyBolt = 2; //Святая стрела
const int SPL_PalMediumHeal = 3; //Среднее лечение
const int SPL_PalRepelEvil = 4; //Разогнать дьяволов
const int SPL_PalFullHeal = 5; //Сильное лечение
const int SPL_PalDestroyEvil = 6; //Уничтожить дьяволов
// Руны Телепортации
const int SPL_PalTeleportSecret = 7; //Телепорт
const int SPL_TeleportSeaport = 8; //Телепорт в гавань
const int SPL_TeleportMonastery = 9; //Телепорт к монастырю
const int SPL_TeleportFarm = 10; //Телепорт к помещику
const int SPL_TeleportXardas = 11; //Телепорт к Ксардасу
const int SPL_TeleportPassNW = 12; //Телепорт к проходу в Хоринисе
const int SPL_TeleportPassOW = 13; //Телепорт к проходу в рудниковой долине
const int SPL_TeleportOC = 14; //Телепорт в замок
const int SPL_TeleportOWDemonTower = 15; //Телепорт в старую башню демонов
const int SPL_TeleportTaverne = 16; //Телепорт к таверне
const int SPL_Teleport_3 = 17; //(не используется)
// Круг 1
const int SPL_Light = 18; //Свет
const int SPL_Firebolt = 19; //Огненная стрела
const int SPL_LightHeal = 21; //Лечить легкое ранение
const int SPL_SummonGoblinSkeleton = 22; //Вызвать скелет гоблина
const int SPL_Zap = 24; //Молния
// Круг 2
const int SPL_Icebolt = 20; //Ледяная стрела
const int SPL_InstantFireball = 23; //Огненный шар
const int SPL_SummonWolf = 25; //Вызвать волка
const int SPL_WindFist = 26; //Порыв ветра
const int SPL_Sleep = 27; //Сон
// Круг 3
const int SPL_MediumHeal = 28; //Лечить среднее ранение
const int SPL_LightningFlash = 29; //Удар молнии
const int SPL_ChargeFireball = 30; //Большой огненный шар
const int SPL_SummonSkeleton = 31; //Вызвать скелет
const int SPL_Fear = 32; //Страх
const int SPL_IceCube = 33; //Ледяная глыба
// Круг 4
const int SPL_ChargeZap = 34; //Шаровая молния
const int SPL_SummonGolem = 35; //Вызвать голема
const int SPL_DestroyUndead = 36; //Уничтожить нежить
const int SPL_Pyrokinesis = 37; //Большая огненная буря (ошибка перевода ???)
// Круг 5
const int SPL_Firestorm = 38; //Малая огненная буря (ошибка перевода ???)
const int SPL_IceWave = 39; //Ледяная волна
const int SPL_SummonDemon = 40; //Вызвать демона
const int SPL_FullHeal = 41; //Лечить сильное ранение
// Круг 6
const int SPL_Firerain = 42; //Огненный дождь
const int SPL_BreathOfDeath = 43; //Дым смерти
const int SPL_MassDeath = 44; //Волна смерти
const int SPL_ArmyOfDarkness = 45; //Армия мрака
const int SPL_Shrink = 46; //Уменьшить монстра
// Свитки
const int SPL_TrfSheep = 47; //Превращение в овцу
const int SPL_TrfScavenger = 48; //Превращение в падальщика
const int SPL_TrfGiantRat = 49; //Превращение в крысу
const int SPL_TrfGiantBug = 50; //Превращение в полевого жука
const int SPL_TrfWolf = 51; //Превращение в волка
const int SPL_TrfWaran = 52; //Превращение в ящерицу
const int SPL_TrfSnapper = 53; //Превращение в глорха
const int SPL_TrfWarg = 54; //Превращение в варга
const int SPL_TrfFireWaran = 55; //Превращение в огненную ящерицу
const int SPL_TrfLurker = 56; //Превращение в шныга
const int SPL_TrfShadowbeast = 57; //Превращение в мракориса
const int SPL_TrfDragonSnapper = 58; //Превращение в остера
const int SPL_Charm = 59; //Забыть
// Круг 5
const int SPL_MasterOfDisaster = 60; //Святой удар
// ???

const int SPL_Deathbolt = 61; //Стрела смерти
const int SPL_Deathball = 62; //Шар смерти
const int SPL_ConcussionBolt = 63; //Стрела сотрясения
const int SPL_Reserved_64 = 64; //
const int SPL_Reserved_65 = 65; //
const int SPL_Reserved_66 = 66; //
const int SPL_Reserved_67 = 67; //
const int SPL_Reserved_68 = 68; //
const int SPL_Reserved_69 = 69; //
// Заклинания магов воды
const int SPL_Thunderstorm = 70; //Шторм
const int SPL_Whirlwind = 71; //Смерч
const int SPL_WaterFist = 72; //Кулак воды
const int SPL_IceLance = 73; //Ледяное копье
const int SPL_Inflate = 74; //Раздуть
const int SPL_Geyser = 75; //Гейзер
const int SPL_Waterwall = 76; //Водяная стена
const int SPL_Reserved_77 = 77;
const int SPL_Reserved_78 = 78;
const int SPL_Reserved_79 = 79;
// Заклинания Майя
const int SPL_Plague = 80; //Чума
const int SPL_Swarm = 81; //Рой
const int SPL_GreenTentacle = 82; //Зеленые щупальца
const int SPL_Earthquake = 83; //Землетрясение
const int SPL_SummonGuardian = 84; //Создать стража
const int SPL_Energyball = 85; //Шар энергии
const int SPL_SuckEnergy = 86; //Украсть энергию
const int SPL_Skull = 87; //Крик мертвых
const int SPL_SummonZombie = 88; //Создать зомби
const int SPL_SummonMud = 89; //Вызвать Муда
// ...
const int SPL_Reserved_90 = 90;
const int SPL_Reserved_91 = 91;
const int SPL_Reserved_92 = 92;
const int SPL_Reserved_93 = 93;
const int SPL_Reserved_94 = 94;
const int SPL_Reserved_95 = 95;
const int SPL_Reserved_96 = 96;
const int SPL_Reserved_97 = 97;
const int SPL_Reserved_98 = 98;
const int SPL_Reserved_99 = 99;
const int MAX_SPELL = 100; //59 (Gothic),68 (Gothic2),100 (G2Addon)
// Массив имен классов заклинаний
const string spellFxInstanceNames[MAX_SPELL] =
{
"PalLight", // 0 SPL_PalLight
"PalHeal", // 1 SPL_PalLightHeal
"PalHolyBolt", // 2 SPL_PalHolyBolt
"PalHeal", // 3 SPL_PalMediumHeal
"PalRepelEvil", // 4 SPL_PalRepelEvil
"PalHeal", // 5 SPL_PalFullHeal
"PalDestroyEvil", // 6 SPL_PalDestroyEvil
"Teleport", // 7 SPL_PalTeleportSecret
"Teleport", // 8 SPL_TeleportSeaport
"Teleport", // 9 SPL_TeleportMonastery
"Teleport", // 10 SPL_TeleportFarm
"Teleport", // 11 SPL_TeleportXardas
"Teleport", // 12 SPL_TeleportPassNW
"Teleport", // 13 SPL_TeleportPassOW
"Teleport", // 14 SPL_TeleportOC
"Teleport", // 15 SPL_TeleportOWDemonTower
"Teleport", // 16 SPL_TeleportTaverne
"Teleport", // 17 SPL_Teleport_3
"Light", // 18 SPL_Light
"Firebolt", // 19 SPL_Firebolt
"Icebolt", // 20 SPL_Icebolt
"Heal", // 21 SPL_LightHeal
"SummonGoblinSkeleton", // 22 SPL_SummonGoblinSkeleton
"InstantFireball", // 23 SPL_InstantFireball
"Zap", // 24 SPL_Zap
"SummonWolf", // 25 SPL_SummonWolf
"WindFist", // 26 SPL_WindFist
"Sleep", // 27 SPL_Sleep
"Heal", // 28 SPL_MediumHeal
"LightningFlash", // 29 SPL_LightningFlash
"ChargeFireball", // 30 SPL_ChargeFireball
"SummonSkeleton", // 31 SPL_SummonSkeleton
"Fear", // 32 SPL_Fear
"Icecube", // 33 SPL_IceCube
"ChargeZap", // 34 SPL_ChargeZap
"SummonGolem", // 53 SPL_SummonGolem
"DestroyUndead", // 36 SPL_DestroyUndead
"Pyrokinesis", // 37 SPL_Pyrokinesis
"Firestorm", // 38 SPL_Firestorm
"Icewave", // 39 SPL_IceWave
"SummonDemon", // 40 SPL_SummonDemon
"Heal", // 41 SPL_FullHeal
"Firerain", // 42 SPL_Firerain
"BreathOfDeath", // 43 SPL_BreathOfDeath
"MassDeath", // 44 SPL_MassDeath
"ArmyOfDarkness", // 45 SPL_ArmyOfDarkness
"Shrink", // 46 SPL_Shrink
"Transform", // 47 SPL_TrfSheep
"Transform", // 48 SPL_TrfScavenger
"Transform", // 49 SPL_TrfGiantRat
"Transform", // 50 SPL_TrfGiantBug
"Transform", // 51 SPL_TrfWolf
"Transform", // 52 SPL_TrfWaran
"Transform", // 53 SPL_TrfSnapper
"Transform", // 54 SPL_TrfWarg
"Transform", // 55 SPL_TrfFireWaran
"Transform", // 56 SPL_TrfLurker
"Transform", // 57 SPL_TrfShadowbeast
"Transform", // 58 SPL_TrfDragonSnapper
"Charm", // 59 SPL_Charm
"MasterOfDisaster", // 60 SPL_MasterOfDisaster
"Deathbolt", // 61 SPL_Deathbolt
"Deathball", // 62 SPL_Deathball
"Concussionbolt", // 63 SPL_Concussionbolt
"Light", // 64 SPL_Reserved_64
"Light", // 65 SPL_Reserved_65
"Light", // 66 SPL_Reserved_66
"Light", // 67 SPL_Reserved_67
"Light", // 68 SPL_Reserved_68
"Light", // 69 SPL_Reserved_69
"Thunderstorm", // 70 SPL_Thunderstorm
"Whirlwind", // 71 SPL_Whirlwind
"Waterfist", // 72 SPL_WaterFist
"IceLance", // 73 SPL_IceLance
"Sleep", // 74 SPL_Inflate
"Geyser", // 75 SPL_Geyser
"Firerain", // 76 SPL_Waterwall
"Light", // 77 SPL_Reserved_77
"Light", // 78 SPL_Reserved_78
"Light", // 79 SPL_Reserved_79
"Fear", // 80 SPL_Plague
"Swarm", // 81 SPL_Swarm
"Greententacle", // 82 SPL_GreenTentacle
"Firerain", // 83 SPL_Earthquake
"SummonGuardian", // 84 SPL_SummonGuardian
"Energyball", // 85 SPL_Energyball
"SuckEnergy", // 86 SPL_SuckEnergy
"Skull", // 87 SPL_Skull
"SummonZombie", // 88 SPL_SummonZombie
"SummonMud", // 89 SPL_SummonMud
"Light", // 90 SPL_Reserved_90
"Light", // 91 SPL_Reserved_91
"Light", // 92 SPL_Reserved_92
"Light", // 93 SPL_Reserved_93
"Light", // 94 SPL_Reserved_94
"Light", // 95 SPL_Reserved_95
"Light", // 96 SPL_Reserved_96
"Light", // 97 SPL_Reserved_97
"Light", // 98 SPL_Reserved_98
"Light" // 99 SPL_Reserved_99
};
// Массив имен анимаций заклинаний
const string spellFxAniLetters[MAX_SPELL] =
{
"SLE", // 0 SPL_PalLight
"HEA", // 1 SPL_PalLightHeal
"FBT", // 2 SPL_PalHolyBolt
"HEA", // 3 SPL_PalMediumHeal
"FBT", // 4 SPL_PalRepelEvil
"HEA", // 5 SPL_PalFullHeal
"FIB", // 6 SPL_PalDestroyEvil
"HEA", // 7 SPL_PalTeleportSecret
"HEA", // 8 SPL_TeleportSeaport
"HEA", // 9 SPL_TeleportMonastery
"HEA", // 10 SPL_TeleportFarm
"HEA", // 11 SPL_TeleportXardas
"HEA", // 12 SPL_TeleportPassNW
"HEA", // 13 SPL_TeleportPassOW
"HEA", // 14 SPL_TeleportOC
"HEA", // 15 SPL_TeleportOWDemonTower
"HEA", // 16 SPL_TeleportTaverne
"HEA", // 17 SPL_Teleport_3
"SLE", // 18 SPL_Light
"FBT", // 19 SPL_Firebolt
"FBT", // 20 SPL_Icebolt
"HEA", // 21 SPL_LightHeal
"SUM", // 22 SPL_SummonGoblinSkeleton
"FBT", // 23 SPL_InstantFireball
"FBT", // 24 SPL_Zap
"SUM", // 25 SPL_SummonWolf
"WND", // 26 SPL_WindFist
"SLE", // 27 SPL_Sleep
"HEA", // 28 SPL_MediumHeal
"WND", // 29 SPL_LightningFlash
"FIB", // 30 SPL_ChargeFireball
"SUM", // 31 SPL_SummonSkeleton
"FEA", // 32 SPL_Fear
"FRZ", // 33 SPL_IceCube
"FIB", // 34 SPL_ChargeZap
"SUM", // 35 SPL_SummonGolem
"FIB", // 36 SPL_DestroyUndead
"FIB", // 37 SPL_Pyrokinesis
"FIB", // 38 SPL_Firestorm
"FEA", // 39 SPL_IceWave
"SUM", // 40 SPL_SummonDemon
"HEA", // 41 SPL_FullHeal
"FEA", // 42 SPL_Firerain
"FIB", // 43 SPL_BreathOfDeath
"MSD", // 44 SPL_MassDeath
"SUM", // 45 SPL_ArmyOfDarkness
"SLE", // 46 SPL_Shrink
"TRF", // 47 SPL_TrfSheep
"TRF", // 48 SPL_TrfScavenger
"TRF", // 49 SPL_TrfGiantRat
"TRF", // 50 SPL_TrfGiantBug
"TRF", // 51 SPL_TrfWolf
"TRF", // 52 SPL_TrfWaran
"TRF", // 53 SPL_TrfSnapper
"TRF", // 54 SPL_TrfWarg
"TRF", // 55 SPL_TrfFireWaran
"TRF", // 56 SPL_TrfLurker
"TRF", // 57 SPL_TrfShadowbeast
"TRF", // 58 SPL_TrfDragonSnapper
"FIB", // 59 SPL_Charm
"FIB", // 60 SPL_MasterOfDisaster
"FBT", // 61 SPL_Deathbolt
"FBT", // 62 SPL_Deathball
"FBT", // 63 SPL_Concussionbolt
"XXX", // 64 SPL_Reserved_64
"XXX", // 65 SPL_Reserved_65
"XXX", // 66 SPL_Reserved_66
"XXX", // 67 SPL_Reserved_67
"XXX", // 68 SPL_Reserved_68
"XXX", // 69 SPL_Reserved_69
"STM", // 70 SPL_Thunderstorm
"WHI", // 71 SPL_Whirlwind
"WND", // 72 SPL_WaterFist
"FBT", // 73 SPL_IceLance
"SLE", // 74 SPL_Inflate
"WND", // 75 SPL_Geyser
"FEA", // 76 SPL_Waterwall
"XXX", // 77 SPL_Reserved_77
"XXX", // 78 SPL_Reserved_78
"XXX", // 79 SPL_Reserved_79
"FBT", // 80 SPL_Plague
"FBT", // 81 SPL_Swarm
"FRZ", // 82 SPL_GreenTentacle
"FEA", // 83 SPL_Earthquake
"SUM", // 84 SPL_SummonGuardian
"WND", // 85 SPL_Energyball
"WND", // 86 SPL_SuckEnergy
"WND", // 87 SPL_Skull
"SUM", // 88 SPL_SummonZombie
"SUM", // 89 SPL_SummonMud
"XXX", // 90 SPL_Reserved_90
"XXX", // 91 SPL_Reserved_91
"XXX", // 92 SPL_Reserved_92
"XXX", // 93 SPL_Reserved_93
"XXX", // 94 SPL_Reserved_94
"XXX", // 95 SPL_Reserved_95
"XXX", // 96 SPL_Reserved_96
"XXX", // 97 SPL_Reserved_97
"XXX", // 98 SPL_Reserved_98
"XXX" // 99 SPL_Reserved_99
};
// Таланты
const int NPC_TALENT_UNKNOWN = 0; //Отсутствует
const int NPC_TALENT_1H = 1; //Владение одноручным оружием
const int NPC_TALENT_2H = 2; //Владение двуручным оружием
const int NPC_TALENT_BOW = 3; //Владение луком
const int NPC_TALENT_CROSSBOW = 4; //Владение арбалетом
const int NPC_TALENT_PICKLOCK = 5; //Умение вскрывать замки
//const int NPC_TALENT_PICKPOCKET = 6; //Карманная кража (из Готики 1, не используется)
const int NPC_TALENT_MAGE = 7; //Маг
const int NPC_TALENT_SNEAK = 8; //Подкрадывание
const int NPC_TALENT_REGENERATE = 9; //Регенерация
const int NPC_TALENT_FIREMASTER = 10; //Владение огнем
const int NPC_TALENT_ACROBAT = 11; //Акробатика
const int NPC_TALENT_PICKPOCKET = 12; //Карманная кража
const int NPC_TALENT_SMITH = 13; //Кузнечное дело
const int NPC_TALENT_RUNES = 14; //Изготовление рун
const int NPC_TALENT_ALCHEMY = 15; //Алхимия
const int NPC_TALENT_TAKEANIMALTROPHY = 16; //Разделка животных
const int NPC_TALENT_FOREIGNLANGUAGE = 17; //Изучение иностранных языков
const int NPC_TALENT_WISPDETECTOR = 18; //Поиск предметов
const int NPC_TALENT_C = 19; //(пусто)
const int NPC_TALENT_D = 20; //(пусто)
const int NPC_TALENT_E = 21; //(пусто)
const int NPC_TALENT_MAX = 22; //Макс. число талантов
// Массив талантов изготовления рун
var int PLAYER_TALENT_RUNES[MAX_SPELL];
// Уровни знаний иностранных языков
const int LANGUAGE_1 = 0;
const int LANGUAGE_2 = 1;
const int LANGUAGE_3 = 2;
const int MAX_LANGUAGE = 3;
var int PLAYER_TALENT_FOREIGNLANGUAGE[MAX_LANGUAGE];
// Уровни поиска предметов
const int WISPSKILL_NF = 0; //Поиск оружия ближнего радиуса поражения
const int WISPSKILL_FF = 1; //Поиск оружия дальнего радиуса поражения
const int WISPSKILL_NONE = 2; //Поиск денег, ключей, предметов обихода
const int WISPSKILL_RUNE = 3; //Поиск рун и свитков
const int WISPSKILL_MAGIC = 4; //Поиск колец и амулетов
const int WISPSKILL_FOOD = 5; //Поиск питания и растений
const int WISPSKILL_POTIONS = 6; //Поиск напитков всех видов
const int MAX_WISPSKILL = 7; //Макс. количество уровней поиска
var int PLAYER_TALENT_WISPDETECTOR[MAX_WISPSKILL];
// Режимы поиска предметов
var int WispSearching;
const int WispSearch_Follow = 1; //Огонек следует за вами
const int WispSearch_ALL = 2; //Ищет все, что может найти
const int WispSearch_POTIONS = 3; //Ищет напитки
const int WispSearch_MAGIC = 4; //Ищет магические предметы
const int WispSearch_FOOD = 5; //Ищет питание
const int WispSearch_NF = 6; //Ищет оружия ближнего радиуса поражения
const int WispSearch_FF = 7; //Ищет оружия дальнего радиуса поражения
const int WispSearch_NONE = 8; //Ищет деньги
const int WispSearch_RUNE = 9; //Ищет руны
// Алхимия
const int POTION_Health_01 = 0; //Лечебная эссенция
const int POTION_Health_02 = 1; //Лечебный экстракт
const int POTION_Health_03 = 2; //Лечебный эликсир
const int POTION_Mana_01 = 3; //Эссенция маны
const int POTION_Mana_02 = 4; //Экстракт маны
const int POTION_Mana_03 = 5; //Эликсир маны
const int POTION_Speed = 6; //Напиток ускорения
const int POTION_Perm_STR = 7; //Эликсир силы
const int POTION_Perm_DEX = 8; //Эликсир ловкости
const int POTION_Perm_Mana = 9; //Постоянный напиток маны
const int POTION_Perm_Health = 10; //Постоянный лечебный напиток
const int POTION_MegaDrink = 11; //Эмбарла Фиргасто
const int CHARGE_Innoseye = 12; //Зарядить Глаз
const int POTION_Mana_04 = 13; //Чистая мана
const int POTION_Health_04 = 14; //Чистая жизненная энергия
const int MAX_POTION = 15; //Макс. количество видов алхимии
var int PLAYER_TALENT_ALCHEMY[MAX_POTION];
// Кузнечное дело
const int WEAPON_Common = 0; //Простой самокованный меч
const int WEAPON_1H_Special_01 = 1; //Рудный длинный клинок
const int WEAPON_2H_Special_01 = 2; //Рудный двуручник
const int WEAPON_1H_Special_02 = 3; //Рудный клинок чудовища
const int WEAPON_2H_Special_02 = 4; //Тяжелый рудный двуручник
const int WEAPON_1H_Special_03 = 5; //Рудный боевой клинок
const int WEAPON_2H_Special_03 = 6; //Тяжелый рудный боевой клинок
const int WEAPON_1H_Special_04 = 7; //Рудный потрошитель драконов
const int
WEAPON_2H_Special_04 = 8; //Большой рудный потрошитель драконов
const int WEAPON_1H_Harad_01 = 9; //Благородный меч
const int
WEAPON_1H_Harad_02 = 10; //Благородный длинный меч
const int
WEAPON_1H_Harad_03 = 11; //Рубиновый клинок
const int WEAPON_1H_Harad_04 = 12; //Благородный меч чудовища
const int MAX_WEAPONS = 13; //Макс. количество видов создаваемого оружия
var int
PLAYER_TALENT_SMITH[MAX_WEAPONS]; // Разделка животных
const int TROPHY_Teeth = 0; //Взять зубы
const int
TROPHY_Claws = 1; //Взять когти
const int TROPHY_Fur = 2; //Взять шкуру
const int
TROPHY_Heart = 3; //Взять сердце
const int
TROPHY_ShadowHorn = 4; //Взять рог мракориса
const int TROPHY_FireTongue = 5; //Взять огненный язык
const int
TROPHY_BFWing = 6; //Взять крылья кровяного шершня
const int TROPHY_BFSting = 7; //Взять жало кровяного шершня
const int TROPHY_Mandibles = 8; //Взять жвало
const int TROPHY_CrawlerPlate = 9; //Взять панцирь ползуна
const int TROPHY_DrgSnapperHorn = 10; //Взять рог остера
const int TROPHY_DragoNPCale = 11; //Взять чешую дракона
const int TROPHY_DragonBlood = 12; //Взять кровь дракона
const int
TROPHY_ReptileSkin = 13; //Взять кожу рептилии
const int
MAX_TROPHIES = 14; //Макс. количество трофеев
var int PLAYER_TALENT_TAKEANIMALTROPHY[MAX_TROPHIES];

//**************************************** // Шрифты для движка //****************************************

const string TEXT_FONT_20 = "Font_old_20_white.tga";
const string TEXT_FONT_10 = "Font_old_10_white.tga";
const string TEXT_FONT_DEFAULT = "Font_old_10_white.tga";
const string
TEXT_FONT_Inventory = "Font_old_10_white.tga";

//**************************************** // Задержка текста при выводе в режиме диалога в мс на символ //****************************************
const float
VIEW_TIME_PER_CHAR = 550;
//**************************************** // Области игрового мира //****************************************
const int NEWWORLD_ZEN = 1; //Хоринис с окрестностями
const int OLDWORLD_ZEN = 2; //Весь Миненталь
const int DRAGONISLAND_ZEN = 3; //Остров Драконов
const int
ADDONWORLD_ZEN = 4; //Яркендар

//****************************************
// Параметры камеры для показа предметов инвентаря
//****************************************

const int INVCAM_ENTF_RING_STANDARD = 400;
const int INVCAM_ENTF_AMULETTE_STANDARD = 150;
const int
INVCAM_ENTF_MISC_STANDARD = 200;
const int INVCAM_ENTF_MISC2_STANDARD = 250;
const int INVCAM_ENTF_MISC3_STANDARD = 500;
const int INVCAM_ENTF_MISC4_STANDARD = 650;
const int INVCAM_ENTF_MISC5_STANDARD = 850;
const int INVCAM_X_RING_STANDARD = 25;
const int
INVCAM_Z_RING_STANDARD = 45;
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Тема вторая: Искусственный интеллект.

Все функции, константы и переменные искусственного интеллекта находятся в папке ..\AI

1. Константы AI.

Они описаны в файле ..\AI_Intern\AI_Constants.d
//**************************
// AIVAR - Константы для людей
//**************************


// ------ Новости и память ---------------------

const int AIV_LastFightAgainstPlayer = 0; //Параметры последнего сражения с ГГ
const int FIGHT_NONE = 0; //Сражения с ГГ не было
const int FIGHT_LOST = 1; //Сражение проиграно (победа ГГ)
const int FIGHT_WON = 2; //Сражение выиграно (победа НПС)
const int FIGHT_CANCEL = 3; //Сражение прервано

const int AIV_NpcSawPlayerCommit = 1; //НПС видел какой криминал совершил ГГ
const int CRIME_NONE = 0; //Криминала не было
const int CRIME_SHEEPKILLER = 1; //ГГ убил овцу
const int CRIME_ATTACK = 2; //ГГ сражался с НПС (параметры в AIV_LastFightAgainstPlayer)
const int CRIME_THEFT = 3; //ГГ занимался воровством
const int CRIME_MURDER = 4; //ГГ совершил убийство

const int AIV_NpcSawPlayerCommitDay = 2; //День, когда ГГ совершил криминал

// ------ Восприятие диалога -------------------
const int AIV_NpcStartedTalk = 3; //Устанавливается в TRUE, если НПС с важной информацией обращается к другому НПС

// ------ Диалог -------------------------------
const int AIV_INVINCIBLE = 4; //Устанавливается в TRUE в начале диалога для обоих НПС
const int AIV_TalkedToPlayer = 5; //Устанавливается в TRUE, если НПС уже разговаривал с ГГ

// ------ Карманная кража ----------------------
const int AIV_PlayerHasPickedMyPocket = 6; //Устанавливается в TRUE, если ГГ залезал в карман НПС

// ------ Сражение -----------------------------
const int AIV_LASTTARGET = 7; //Ссылка на последнего атакованного НПС
const int AIV_PursuitEnd = 8; //Устанавливается в TRUE, если НПС закончил преследование

// ------ Причина нападения ------------
const int AIV_ATTACKREASON = 9; //Причина нападения (по приоритетам)
const int AR_NONE = 0; //Причины нет
const int AR_LeftPortalRoom = 1; //ГГ находится в помещении с ограниченным доступом
const int AR_ClearRoom = 2; //ГГ находится в помещении другого НПС
const int AR_GuardCalledToRoom = 3; //Вызвана охрана для защиты помещения
const int AR_MonsterVsHuman = 4; //Монстр сражается с человеком, ГГ помогает человеку
const int AR_MonsterMurderedHuman = 5; //Монстр убил человека
const int AR_SheepKiller = 6; //Овца была атакована и убита (человеком или монстром)
const int AR_Theft = 7; //ГГ что-то украл
const int AR_UseMob = 8; //ГГ использовал МОВ с флагом принадлежности другому НПС
const int AR_GuardCalledToThief = 9; //Вызвана стража по факту воровства ГГ
const int AR_ReactToWeapon = 10; //Преступник не убрал оружие после двукратного пердупреждения или пустился в бега
const int AR_ReactToDamage = 11; //Преступник ранил НПС
const int AR_GuardStopsFight = 12; //Охрана прекращает атаковать преступника
const int AR_GuardCalledToKill = 13; //Вызвана охрана по факту убийства
const int AR_GuildEnemy = 14; //НПС является врагом гильдии (человек или монстр)
const int AR_HumanMurderedHuman = 15; //Человек убил человека
const int AR_MonsterCloseToGate = 16; //Охрана ворот атакует враждебного монстра
const int AR_GuardStopsIntruder = 17; //Охрана ворот атакует незваного гостя
const int AR_SuddenEnemyInferno = 18; //Немедленная атака противника (невзирая на блокировку)
const int AR_KILL = 19; //ГГ убил НПС

// ------ Обыскивание трупов --------------------
const int AIV_RANSACKED = 10; //Устанавливается TRUE, если труп обыскивается

// ------ Смерть --------------------------------
const int AIV_DeathInvGiven = 11; //Устанавливается TRUE, если труп обыскан

// ------ Охрана --------------------------------
const int AIV_Guardpassage_Status = 12; //Статус предупреждений охраны
const int GP_NONE = 0; //Нет предупреждений
const int GP_FirstWarnGiven = 1; //НПС получил первое предупреждение
const int GP_SecondWarnGiven = 2; //НПС получил второе предупреждение
const int AIV_LastDistToWP = 13; //Расстояние от WP охраны до точки, в которой НПС получил предупреждение
const int AIV_PASSGATE = 14; //TRUE - проход возможен, FALSE - проход запрещен

// ------ Предоставление экспы ------------------
const int AIV_PARTYMEMBER = 15; //Если TRUE, то экспа за убитых монстров сопровождавшим идет ГГ.
const int AIV_VictoryXPGiven = 16; //Устанавливается TRUE, когда экспа за победу начислена

// ------ Пол -----------------------------------
const int AIV_Gender = 17; //Пол НПС
const int MALE = 0; //Мужской
const int FEMALE = 1; //Женский

// ------ Пища ----------------------------------
const int AIV_Food = 18; //Употребляемая пища
const int FOOD_Apple = 0; //Яблоко
const int FOOD_Cheese = 1; //Сыр
const int FOOD_Bacon = 2; //Бекон
const int FOOD_Bread = 3; //Хлеб

// ------ Вспомогательные параметры для ТА ------
const int AIV_TAPOSITION = 19; //Позиции выполненния ТА
const int ISINPOS = 0; //НПС в позиции выполнения ТА
const int NOTINPOS = 1; //НПС не в позиции выполнения ТА
const int NOTINPOS_WALK = 2; //НПС идет к точке выполнения ТА

// ------ Выбор заклинания ----------------------
const int AIV_SelectSpell = 20; //Случайное число, соответствующее заклинанию, выбранному НПС

// ------ Наблюдение ----------------------------
const int AIV_SeenLeftRoom = 21; //TRUE, если НПС наблюдает за своим помещением

//////////////////////////////////// //Переменные использующиеся при комментариях действий ГГ
var int Player_SneakerComment; //ГГ крадется
var int Player_LeftRoomComment; //ГГ зашел в чужое помещение
var int Player_DrawWeaponComment; //ГГ вытащил оружие
var int Player_GetOutOfMyBedComment; //ГГ лег на чужую кровать
////////////////////////////////////

// ------ Сражение со вторым противником --------
const int AIV_HitByOtherNpc = 22; //Расстояние до другого НПС
const int AIV_WaitBeforeAttack = 23; //Если != 0, то вводится задержка перед атакой
const int AIV_LastAbsolutionLevel = 24; //Репутация ГГ для конкретной локации

// ----------------------------------------------
const int AIV_ToughGuyNewsOverride = 25; //НПС не имеет новостей о "жестком парне" (ГГ)


//***************************
// AIVAR - Константы для монстров
//***************************

const int AIV_MM_ThreatenBeforeAttack = 26; //Монстр угрожает перед атакой
const int AIV_MM_FollowTime = 27; //Время преследования монстром в сек.
const int FOLLOWTIME_SHORT = 5; //Короткое преследование
const int FOLLOWTIME_MEDIUM = 10; //Среднее преследование
const int FOLLOWTIME_LONG = 20; //Длительное преследование
const int AIV_MM_FollowInWater = 28; //Полезет ли монстр за НПС в воду? (относится и к людям)
// ----------------------------------------------
const int AIV_MM_PRIORITY = 29; //Приоритет поведения монстра
const int PRIO_EAT = 0; //Пожирание падали
const int PRIO_ATTACK = 1; //Нападение на жертву
// ----------------------------------------------

const int AIV_MM_SleepStart = 30; //Время отхода монстра ко сну (час)
const int AIV_MM_SleepEnd = 31; //Время пробуждения
const int AIV_MM_RestStart = 32; //Время начала отдыха
const int AIV_MM_RestEnd = 33; //Время окончания отдыха
const int AIV_MM_RoamStart = 34; //Время начала брожения
const int AIV_MM_RoamEnd = 35; //Время окончания брожения
const int AIV_MM_EatGroundStart = 36; //Время начала кормежки
const int AIV_MM_EatGroundEnd = 37; //Время окончания кормежки
const int AIV_MM_WuselStart = 38; //Время начала активности
const int AIV_MM_WuselEnd = 39; //Время окончания активности
const int AIV_MM_OrcSitStart = 40; //Время, когда орк садится
const int AIV_MM_OrcSitEnd = 41; //Время, когда орк встает
const int OnlyRoutine = -1; //Время контролируется программой поведения монстра
// ----------------------------------------------
const int AIV_MM_ShrinkState = 42; //Состояние уменьшения монстра (коэффициент сжатия)
// ----------------------------------------------

const int AIV_MM_REAL_ID = 43; //Идентификатор монстра
const int ID_MEATBUG = 1; //Мясной жук
const int ID_SHEEP = 2; //Овца
const int ID_GOBBO_GREEN = 3; //Гоблин
const int ID_GOBBO_BLACK = 4; //Черный гоблин
const int ID_GOBBO_SKELETON = 5; //Скелет гоблина
const int ID_SUMMONED_GOBBO_SKELETON = 6; //Вызванный Скелет гоблина
const int ID_SCAVENGER = 7; //Падальщик
const int ID_SCAVENGER_DEMON = 8; //Зубастик
const int ID_GIANT_RAT = 8; //Крыса
const int ID_GIANT_BUG = 9; //Полевой жук
const int ID_BLOODFLY = 10; //Кровяной шершень
const int ID_WARAN = 11; //Ящерица
const int ID_FIREWARAN = 12; //Огненная ящерица
const int ID_WOLF = 13; //Волк
const int ID_WARG = 14; //Варг
const int ID_SUMMONED_WOLF = 15; //Вызванный Волк
const int ID_MINECRAWLER = 16; //Ползун
const int ID_MINECRAWLERWARRIOR = 17; //Воин ползунов
const int ID_LURKER = 18; //Шныг
const int ID_SKELETON = 19; //Скелет
const int ID_SUMMONED_SKELETON = 20; //Вызванный Скелет
const int ID_SKELETON_MAGE = 21; //Маг скелетов
const int ID_ZOMBIE = 22; //Зомби
const int ID_SNAPPER = 23; //Глорх
const int ID_DRAGONSNAPPER = 24; //Остер
const int ID_SHADOWBEAST = 25; //Мракорис
const int ID_SHADOWBEAST_SKELETON = 26; //Скелет мракориса
const int ID_HARPY = 27; //Гарпия
const int ID_STONEGOLEM = 28; //Каменный голем
const int ID_FIREGOLEM = 29; //Огненный голем
const int ID_ICEGOLEM = 30; //Ледяной голем
const int ID_SUMMONED_GOLEM = 31; //Вызванный Голем
const int ID_DEMON = 32; //Демон
const int ID_SUMMONED_DEMON = 33; //Вызванный Демон
const int ID_DEMON_LORD = 34; //Лорд демонов
const int ID_TROLL = 35; //Троль
const int ID_TROLL_BLACK = 36; //Черный троль
const int ID_SWAMPSHARK = 37; //Болотожор
const int ID_DRAGON_FIRE = 38; //Огненный дракон
const int ID_DRAGON_ICE = 39; //Ледяной дракон
const int ID_DRAGON_ROCK = 40; //Каменный дракон
const int ID_DRAGON_SWAMP = 41; //Болотный дракон
const int ID_DRAGON_UNDEAD = 42; //Дракон нежить
const int ID_MOLERAT = 43; //Кротокрыс
const int ID_ORCWARRIOR = 44; //Воин орков
const int ID_ORCSHAMAN = 45; //Шаман орков
const int ID_ORCELITE = 46; //Элитный воин орков
const int ID_UNDEADORCWARRIOR = 47; //Орк нежить
const int ID_DRACONIAN = 48; //Ящер
const int ID_WISP = 49; //Огонек

//-----Addon ------

const int ID_Alligator = 50; //Аллигатор
const int ID_Swampgolem = 51; //Болотный голем
const int ID_Stoneguardian = 52; //Каменный сторож
const int ID_Gargoyle = 53; //Огненный дух мракориса
const int ID_Bloodhound = 54; //Кровяная собака
const int ID_Icewolf = 55; //Ледяной волк
const int ID_OrcBiter = 56; //Зубастик
const int ID_Razor = 57; //Расчленитель
const int ID_Swarm = 58; //Рой
const int ID_Swamprat = 59; //Болотная крыса
const int ID_BLATTCRAWLER = 60; //Богомол
const int ID_SummonedGuardian = 61; //Вызванный Каменный страж
const int ID_SummonedZombie = 62; //Вызванный Зомби
const int ID_Keiler = 63; //Кабан
const int ID_SWAMPDRONE = 64; //Болотная вонючка

// ----------------------------------------------
const int AIV_LASTBODY = 44; //Ссылка на последнего сожранного монстра


//**********************
// Дальнейшие человеческие AIVARы
//**********************


// ------ Сражение с Альриком -------------------
const int AIV_ArenaFight = 45; //Параметры сражения
const int AF_NONE = 0; //Сражения не было
const int AF_RUNNING = 1; //В процессе сражения
const int AF_AFTER = 2; //После сражения
const int AF_AFTER_PLUS_DAMAGE = 3; //ГГ нечестно выиграл сражение

// ------ Криминал ------------------------------
const int AIV_CrimeAbsolutionLevel = 46; //Абсолютный уровень криминальной репутации ГГ

// ------ Атака ---------------------------------
const int AIV_LastPlayerAR = 47; //Причина последнего нападения ГГ

// ------ Без сознания --------------------------
const int AIV_DuelLost = 48; //TRUE, если НПС из ополчения был побит ГГ

// ------ Торговля ------------------------------
const int AIV_ChapterInv = 49; //Отвечает за обновление товаров у торговцев в начале главы

// ------ Стая монстров -------------------------
const int AIV_MM_Packhunter = 50; //TRUE, если монстры одного вида охотятся и атакуют стаей

// ------ Магия ---------------------------------
const int AIV_MagicUser = 51; //Использует ли НПС магию
const int MAGIC_NEVER = 0; //Не использует
const int MAGIC_ALWAYS = 1; //Всегда использует

// ------ Послушники ----------------------------
const int AIV_DropDeadAndKill = 52; //TRUE, если этого НПС разрешено убить

// ------ Магия заморозки -----------------------
const int AIV_FreezeStateTime = 53; //Время начала действия заклинаний заморозки

// ------ Игнорирование криминала ---------------
const int AIV_IGNORE_Murder = 54; //Игнорирование убийства
const int AIV_IGNORE_Theft = 55; //Игнорирование воровства
const int AIV_IGNORE_Sheepkiller = 56; //Игнорирование убийства овцы

// ------ Крутой парень -------------------------
const int AIV_ToughGuy = 57; //TRUE, если НПС имеет дело с "крутым парнем"

// ------ Отвергнутые новости -------------------
const int AIV_NewsOverride = 58; //TRUE, если НПС не знает никаких новостей

// ------ Атака монстров ------------------------
const int AIV_MaxDistToWp = 59; //Макс. дистанция, на которой монстр начинает атаковать
const int AIV_OriginalFightTactic = 60; //Тактика нападения монстра

// ------ Оценка врага --------------------------
const int AIV_EnemyOverride = 61; //TRUE, если врагов у НПС нет

// ------ Вызванные монстры ---------------------
const int AIV_SummonTime = 62; //Время от начала вызова монстра

// ------ Атака ---------------------------------
const int AIV_FightDistCancel = 63; //Дистанция, на которой прекращается сражение
const int AIV_LastFightComment = 64; //TRUE, если НПС комментировал последнее сражение

// ----------------------------------------------
const int AIV_LOADGAME = 65; //TRUE, если была загрузка игры (other не инициализирован)

// ------ Без сознания --------------------------
const int AIV_DefeatedByPlayer = 66; //TRUE, если НПС побежден ГГ

// ------ Смерть --------------------------------
const int AIV_KilledByPlayer = 67; //TRUE, если НПС убит ГГ

// ------ Различные функции ---------------------
const int AIV_StateTime = 68; //Время нахождения НПС в конкретном состоянии

// ----------------------------------------------
const int AIV_Dist = 69; //Дистанция между НПС
const int AIV_IgnoresFakeGuild = 70; //TRUE, если НПС игнорирует поддельную гильдию
const int AIV_NoFightParker = 71; //TRUE, если НПС не может атаковать
const int AIV_NPCIsRanger = 72; //TRUE, если НПС принадлежит к "Кольцу Воды"
const int AIV_IgnoresArmor = 73; //НПС не носит броню
const int AIV_StoryBandit = 74; //Бандиты, с которыми можно сражаться
const int AIV_StoryBandit_Esteban = 75; //НПС является охранником Эстебана

// ------ Смерч ---------------------------------
const int AIV_WhirlwindStateTime = 76; //Время начала запуска смерча

// ------ Вздутие -------------------------------
const int AIV_InflateStateTime = 77; //Время начала запуска вздутия

// ------ Рой -----------------------------------
const int AIV_SwarmStateTime = 78; //Время начала запуска роя

// ------ Опустошение ---------------------------
const int AIV_SuckEnergyStateTime = 79; //Время начала запуска опустошения

// ------ Пираты --------------------------------
const int AIV_FollowDist = 80; //Дистанция следования НПС друг за другом

// ------ Реальные атрибуты НПС -----------------
const int REAL_STRENGTH = 81; //Сила
const int REAL_DEXTERITY = 82; //Ловкость
const int REAL_MANA_MAX = 83; //Мана
const int REAL_TALENT_1H = 84; //Владение одноручником
const int REAL_TALENT_2H = 85; //Владение двуручником
const int REAL_TALENT_BOW = 86; //Владение луком
const int REAL_TALENT_CROSSBOW = 87; //Владение арбалетом

const int AIV_SpellLevel = 88; //Круг магии


//***************************************************
// Глобальные переменные для системы Доносов/Абсолютных уровней/Новостей
//***************************************************


// Абсолютные уровни
var int ABSOLUTIONLEVEL_OldCamp; //Миненталь
var int ABSOLUTIONLEVEL_City; //Хоринис
var int ABSOLUTIONLEVEL_Monastery; //Монастырь
var int ABSOLUTIONLEVEL_Farm; //Поместье Онара
var int ABSOLUTIONLEVEL_BL; //Лагерь бандитов

// Кол-во криминала в Минентале
var int PETZCOUNTER_OldCamp_Murder; //Убийства
var int PETZCOUNTER_OldCamp_Theft; //Воровство
var int PETZCOUNTER_OldCamp_Attack; //Нападения
var int PETZCOUNTER_OldCamp_Sheepkiller; //Убийство овец

// Кол-во криминала в Хоринисе
var int PETZCOUNTER_City_Murder;
var int PETZCOUNTER_City_Theft;
var int PETZCOUNTER_City_Attack;
var int PETZCOUNTER_City_Sheepkiller;

// Кол-во криминала в Монастыре
var int PETZCOUNTER_Monastery_Murder;
var int PETZCOUNTER_Monastery_Theft;
var int PETZCOUNTER_Monastery_Attack;
var int PETZCOUNTER_Monastery_Sheepkiller;

// Кол-во криминала в Поместье Онара
var int PETZCOUNTER_Farm_Murder;
var int PETZCOUNTER_Farm_Theft;
var int PETZCOUNTER_Farm_Attack;
var int PETZCOUNTER_Farm_Sheepkiller;

// Кол-во криминала в Лагере бандитов
var int PETZCOUNTER_BL_Murder;
var int PETZCOUNTER_BL_Theft;
var int PETZCOUNTER_BL_Attack;

//*******************************
// Константы локаций
//*******************************


const int LOC_NONE = 0; //Вне локаций
const int LOC_OLDCAMP = 1; //Миненталь
const int LOC_CITY = 2; //Хоринис
const int LOC_MONASTERY = 3; //Монастырь
const int LOC_FARM = 4; //Поместье Онара
const int LOC_BL = 5; //Лагерь бандитов
const int LOC_ALL = 6; //Все локации

//*******************************
// Константы Хориниса (кварталы)
//*******************************


const int Q_KASERNE = 1; //Казарма
const int Q_GALGEN = 2; //Виселица
const int Q_MARKT = 3; //Рынок
const int Q_TEMPEL = 4; //Замок
const int Q_UNTERSTADT = 5; //Нижний город
const int Q_HAFEN = 6; //Гавань
const int Q_OBERSTADT = 7; //Верхний город

//******************************
// Активное восприятие монстров
//******************************
//---------------------------------------------

const int PERC_DIST_SUMMONED_ACTIVE_MAX = 2000; //Макс. дальность действия активного восприятия вызываемых монстров
const int PERC_DIST_MONSTER_ACTIVE_MAX = 1500; //Макс. дальность действия активного восприятия других монстров
const int PERC_DIST_ORC_ACTIVE_MAX = 2500; //Макс. дальность действия активного восприятия орков
const int PERC_DIST_DRAGON_ACTIVE_MAX = 3500; //Макс. дальность действия активного восприятия драконов
//---------------------------------------------

const int FIGHT_DIST_MONSTER_ATTACKRANGE = 700; //Дистанция, с которой монстры начинают атаковать
const int FIGHT_DIST_MONSTER_FLEE = 300; //Дистанция, с которой монстр начинает преследование
const int FIGHT_DIST_DRAGON_MAGIC = 700; //Дистанция применения драконами магии
//---------------------------------------------

const int MONSTER_THREATEN_TIME = 4; //Кол-во секунд, которые монстр угрожает перед атакой
const int MONSTER_SUMMON_TIME = 60; //Время, на которое вызываются монстры

//************************************
// Константы дистанций для человека
//************************************
// --------------------------------------------

const int TA_DIST_SELFWP_MAX = 500; //Дистанция до объекта, на которой начинают выполняться функции распорядка дня
// --------------------------------------------

const int PERC_DIST_ACTIVE_MAX = 2000; //Макс. дальность действия активного восприятия
//---------------------------------------------

const int PERC_DIST_INTERMEDIAT = 1000; //Макс. дальность действия пассивного восприятия
const int PERC_DIST_DIALOG = 500; //Дистанция начала диалога
const int PERC_DIST_HEIGHT = 1000; //С какой разницы высот НПС не реагируют друг на друга
const int PERC_DIST_INDOOR_HEIGHT = 250; //Дистанция игнорирования через закрытые двери
//---------------------------------------------

const int FIGHT_DIST_MELEE = 600; //Дистанция атаки оружием ближнего радиуса действия
const int FIGHT_DIST_RANGED_INNER = 900; //Дистанция, ближе которой НПС выбирает оружие ближнего радиуса поражения
const int FIGHT_DIST_RANGED_OUTER = 1000; //Дистанция, дальше которой НПС выбирает оружие дальнего радиуса поражения
const int FIGHT_DIST_CANCEL = 3500; //На этой дистанции НПС перестают преследовать
//---------------------------------------------

const int WATCHFIGHT_DIST_MIN = 300 ; //Мин. дистанция наблюдения сражения между двумя НПС другим НПС (не милицией)
const int WATCHFIGHT_DIST_MAX = 2000; //Мах. дистанция наблюдения сражения между двумя НПС другим НПС (не милицией)
//---------------------------------------------

const int ZivilAnquatschDist = 400; //Дистанция, с которой к ГГ начинают обращаться граждане
//---------------------------------------------

const float RANGED_CHANCE_MINDIST = 1500; // (не используется)
const float RANGED_CHANCE_MAXDIST = 4500; // (не используется)

//*************************************
// Константы времени
//*************************************

const int NPC_ANGRY_TIME = 120; // (не используется)
// -------------------------------------------

const int HAI_TIME_UNCONPCIOUS = 20; //Время нахождения в бессознательном состоянии
// -------------------------------------------

const int NPC_TIME_FOLLOW = 10; //Время преследования монстрами

//*************************************
// Минимальные повреждения
//*************************************

const int NPC_MINIMAL_DAMAGE = 5; // (не используется)
const int NPC_MINIMAL_PERCENT = 10; // (не используется)

//*************************************
// AI константы сражения
//*************************************


//Тактика сражения
const int FAI_HUMAN_COWARD = 2; //Трус
const int FAI_HUMAN_NORMAL = 42; //Нормальный
const int FAI_HUMAN_STRONG = 3; //Сильный
const int FAI_HUMAN_MASTER = 4; //Мастер
//-----------------------------------------------

const int FAI_MONSTER_COWARD = 10; //Монстр трус
//-----------------------------------------------

const int FAI_NAILED = 1; //Тактика сражения охранников крепостных стен
//-----------------------------------------------
// Тактика атаки монстрами

const int FAI_GOBBO = 7; //Гоблины
const int FAI_SCAVENGER = 15; //Падальщики
const int FAI_GIANT_RAT = 11; //Крыса
const int FAI_GIANT_BUG = 31; //Полевой жук
const int FAI_BLOODFLY = 24; //Кровяной шершень
const int FAI_WARAN = 21; //Ящерицы
const int FAI_WOLF = 22; //Волк
const int FAI_MINECRAWLER = 5; //Ползуны
const int FAI_LURKER = 9; //Шныг
const int FAI_ZOMBIE = 23; //Зомби
const int FAI_SNAPPER = 18; //Глорх
const int FAI_SHADOWBEAST = 16; //Мракорис
const int FAI_HARPY = 36; //Гарпия
const int FAI_STONEGOLEM = 8; //Големы
const int FAI_DEMON = 6; //Демоны
const int FAI_TROLL = 20; //Троль
const int FAI_SWAMPSHARK = 19; //Болотожор
const int FAI_DRAGON = 39; //Драконы
const int FAI_MOLERAT = 40; //Кротокрыс
//-----------------------------------------------

const int FAI_ORC = 12; //Орки
const int FAI_DRACONIAN = 41; //Ящер

const int FAI_Alligator = 43; //Аллигатор
const int FAI_Gargoyle = 44; //Огненный дух мракориса
const int FAI_Bear = 45; //Медведь
const int FAI_Stoneguardian = 46; //Каменный сторож

//*************************************
// Общие константы
//*************************************

const int TRUE = 1; //Значение TRUE
const int FALSE = 0; //Значение FALSE

const int LOOP_CONTINUE = 0; //Значение продолжения цикла
const int LOOP_END = 1; //Значение выхода из цикла

const int DEFAULT = 0; //Значение по умолчанию

//*************************************
// Константы ГГ
//*************************************


const int LP_PER_LEVEL = 10; //Кол-во пунктов обучения за уровень
const int HP_PER_LEVEL = 12; //Кол-во пунктов жизни за уровень

const int XP_PER_VICTORY = 10; //Ко-во экспы за уровень побежденного противника

//*************************************
// Типы НПС
//*************************************


const int NPCTYPE_AMBIENT = 0; //Окружающий народ
const int NPCTYPE_MAIN = 1; //Значимые НПС
const int NPCTYPE_FRIEND = 2; //Друзья
const int NPCTYPE_OCAMBIENT = 3; //Окружающий народ в Минентале
const int NPCTYPE_OCMAIN = 4; //Значимые НПС в Минентале
const int NPCTYPE_BL_AMBIENT = 5; //Окружающий народ в Лагере бандитов
const int NPCTYPE_TAL_AMBIENT = 6; //Окружающий народ в Долине бандитов
const int NPCTYPE_BL_MAIN = 7; //Значимые НПС в Лагере бандитов

//**************************************
// MOBsi константы
//**************************************


const int MOBSI_NONE = 0; //Нет
const int MOBSI_SmithWeapon = 1; //Ковать оружие
const int MOBSI_SleepAbit = 2; //Способность спать
const int MOBSI_MakeRune = 3; //Изготовление рун
const int MOBSI_PotionAlchemy = 4; //Алхимия
const int MOBSI_PRAYSHRINE = 5; //Молитва
const int MOBSI_GOLDHACKEN = 6; //Милостыня
const int MOBSI_PRAYIDOL = 7; //Молитва идолу

var int PLAYER_MOBSI_PRODUCTION; //Переменная для значений MOBsi

//**************************************
// Константы текстур
//**************************************


// Для мужчин и женщин (по 4 штуки)
const int BodyTex_P = 0; //Бледнокожий
const int BodyTex_N = 1; //Европеец
const int BodyTex_L = 2; //Латиноамериканец
const int BodyTex_B = 3; //Негр
const int BodyTexBabe_P = 4; //Бледнокожая
const int BodyTexBabe_N = 5; //Европейка
const int BodyTexBabe_L = 6; //Латиноамериканка
const int BodyTexBabe_B = 7; //Негритянка
const int BodyTex_Player = 8; //ГГ

const int BodyTex_T = 10; //Татуированный мужик
const int BodyTexBabe_F = 11; //Татуированная женщина
const int BodyTexBabe_S = 12; //Чернокожий ребенок

const int NO_ARMOR = -1; //Без доспехов

// Лица мужчин
const int Face_N_Gomez = 0;
const int Face_N_Scar = 1;
const int Face_N_Raven = 2;
const int Face_N_Bullit = 3;
const int Face_B_Thorus = 4;
const int Face_N_Corristo = 5;
const int Face_N_Milten = 6;
const int Face_N_Bloodwyn = 7;
const int Face_L_Scatty = 8;
const int Face_N_YBerion = 9;
const int Face_N_CoolPock = 10;
const int Face_B_CorAngar = 11;
const int Face_B_Saturas = 12;
const int Face_N_Xardas = 13;
const int Face_N_Lares = 14;
const int Face_L_Ratford = 15;
const int Face_N_Drax = 16;
const int Face_B_Gorn = 17;
const int Face_N_Player = 18;
const int Face_P_Lester = 19;
const int Face_N_Lee = 20;
const int Face_N_Torlof = 21;
const int Face_N_Mud = 22;
const int Face_N_Ricelord = 23;
const int Face_N_Horatio = 24;
const int Face_N_Richter = 25;
const int Face_N_Cipher_neu = 26;
const int Face_N_Homer = 27;
const int Face_B_Cavalorn = 28;
const int Face_L_Ian = 29;
const int Face_L_Diego = 30;
const int Face_N_MadPsi = 31;
const int Face_N_Bartholo = 32;
const int Face_N_Snaf = 33;
const int Face_N_Mordrag = 34;
const int Face_N_Lefty = 35;
const int Face_N_Wolf = 36;
const int Face_N_Fingers = 37;
const int Face_N_Whistler = 38;
const int Face_P_Gilbert = 39;
const int Face_L_Jackal = 40;

// Бледнолицые
const int Face_P_ToughBald = 41;
const int Face_P_Tough_Drago = 42;
const int Face_P_Tough_Torrez = 43;
const int Face_P_Tough_Rodriguez = 44;
const int Face_P_ToughBald_Nek = 45;
const int Face_P_NormalBald = 46;
const int Face_P_Normal01 = 47;
const int Face_P_Normal02 = 48;
const int Face_P_Normal_Fletcher = 49;
const int Face_P_Normal03 = 50;
const int Face_P_NormalBart01 = 51;
const int Face_P_NormalBart_Cronos = 52;
const int Face_P_NormalBart_Nefarius = 53;
const int Face_P_NormalBart_Riordian = 54;
const int Face_P_OldMan_Gravo = 55;
const int Face_P_Weak_Cutter = 56;
const int Face_P_Weak_Ulf_Wohlers = 57;

// Европейцы
const int Face_N_Important_Arto = 58;
const int Face_N_ImportantGrey = 59;
const int Face_N_ImportantOld = 60;
const int Face_N_Tough_Lee_ähnlich = 61;
const int Face_N_Tough_Skip = 62;
const int Face_N_ToughBart01 = 63;
const int Face_N_Tough_Okyl = 64;
const int Face_N_Normal01 = 65;
const int Face_N_Normal_Cord = 66;
const int Face_N_Normal_Olli_Kahn = 67;
const int Face_N_Normal02 = 68;
const int Face_N_Normal_Spassvogel = 69;
const int Face_N_Normal03 = 70;
const int Face_N_Normal04 = 71;
const int Face_N_Normal05 = 72;
const int Face_N_Normal_Stone = 73;
const int Face_N_Normal06 = 74;
const int Face_N_Normal_Erpresser = 75;
const int Face_N_Normal07 = 76;
const int Face_N_Normal_Blade = 77;
const int Face_N_Normal08 = 78;
const int Face_N_Normal14 = 79;
const int Face_N_Normal_Sly = 80;
const int Face_N_Normal16 = 81;
const int Face_N_Normal17 = 82;
const int Face_N_Normal18 = 83;
const int Face_N_Normal19 = 84;
const int Face_N_Normal20 = 85;
const int Face_N_NormalBart01 = 86;
const int Face_N_NormalBart02 = 87;
const int Face_N_NormalBart03 = 88;
const int Face_N_NormalBart04 = 89;
const int Face_N_NormalBart05 = 90;
const int Face_N_NormalBart06 = 91;
const int Face_N_NormalBart_Senyan = 92;
const int Face_N_NormalBart08 = 93;
const int Face_N_NormalBart09 = 94;
const int Face_N_NormalBart10 = 95;
const int Face_N_NormalBart11 = 96;
const int Face_N_NormalBart12 = 97;
const int Face_N_NormalBart_Dexter = 98;
const int Face_N_NormalBart_Graham = 99;
const int Face_N_NormalBart_Dusty = 100;
const int Face_N_NormalBart16 = 101;
const int Face_N_NormalBart17 = 102;
const int Face_N_NormalBart_Huno = 103;
const int Face_N_NormalBart_Grim = 104;
const int Face_N_NormalBart20 = 105;
const int Face_N_NormalBart21 = 106;
const int Face_N_NormalBart22 = 107;
const int Face_N_OldBald_Jeremiah = 108;
const int Face_N_Weak_Ulbert = 109;
const int Face_N_Weak_BaalNetbek = 110;
const int Face_N_Weak_Herek = 111;
const int Face_N_Weak04 = 112;
const int Face_N_Weak05 = 113;
const int Face_N_Weak_Orry = 114;
const int Face_N_Weak_Asghan = 115;
const int Face_N_Weak_Markus_Kark = 116;
const int Face_N_Weak_Cipher_alt = 117;
const int Face_N_NormalBart_Swiney = 118;
const int Face_N_Weak12 = 119;

// Латиноамериканцы
const int Face_L_ToughBald01 = 120;
const int Face_L_Tough01 = 121;
const int Face_L_Tough02 = 122;
const int Face_L_Tough_Santino = 123;
const int Face_L_ToughBart_Quentin = 124;
const int Face_L_Normal_GorNaBar = 125;
const int Face_L_NormalBart01 = 126;
const int Face_L_NormalBart02 = 127;
const int Face_L_NormalBart_Rufus = 128;

// Негры
const int Face_B_ToughBald = 129;
const int Face_B_Tough_Pacho = 130;
const int Face_B_Tough_Silas = 131;
const int Face_B_Normal01 = 132;
const int Face_B_Normal_Kirgo = 133;
const int Face_B_Normal_Sharky = 134;
const int Face_B_Normal_Orik = 135;
const int Face_B_Normal_Kharim = 136;

// Лица женщин
const int FaceBabe_N_BlackHair = 137;
const int FaceBabe_N_Blondie = 138;
const int FaceBabe_N_BlondTattoo = 139;
const int FaceBabe_N_PinkHair = 140;
const int FaceBabe_L_Charlotte = 141;
const int FaceBabe_B_RedLocks = 142;
const int FaceBabe_N_HairAndCloth = 143;
const int FaceBabe_N_WhiteCloth = 144;
const int FaceBabe_N_GreyCloth = 145;
const int FaceBabe_N_Brown = 146;
const int FaceBabe_N_VlkBlonde = 147;
const int FaceBabe_N_BauBlonde = 148;
const int FaceBabe_N_YoungBlonde = 149;
const int FaceBabe_N_OldBlonde = 150;
const int FaceBabe_P_MidBlonde = 151;
const int FaceBabe_N_MidBauBlonde = 152;
const int FaceBabe_N_OldBrown = 153;
const int FaceBabe_N_Lilo = 154;
const int FaceBabe_N_Hure = 155;
const int FaceBabe_N_Anne = 156;
const int FaceBabe_B_RedLocks2 = 157;
const int FaceBabe_L_Charlotte2 = 158;

// Лицо Фортуно
const int Face_N_Fortuno = 159;

// Лица пиратов
const int Face_P_Greg = 160;
const int Face_N_Pirat01 = 161;
const int Face_N_ZombieMud = 162;
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
2. Состояния тела НПС, фокусы камеры и параметры гильдий.

Все состояния тела НПС описаны в файле ..\AI_Intern\BodyStates.d, правда многие из них в игре не используются.
//*************************************************
// Состояния тела
//*************************************************
// Флаги прерываний

const int BS_FLAG_INTERRUPTABLE = 32768; //Состояние прерываемо
const int BS_FLAG_FREEHANDS = 65536; //Свободные руки
//******************************************
// Флаги состояние тела
//******************************************

const int BS_STAND = 0 | BS_FLAG_INTERRUPTABLE | BS_FLAG_FREEHANDS; //Стоит
const int BS_WALK = 1 | BS_FLAG_INTERRUPTABLE; //Идет
const int BS_SNEAK = 2 | BS_FLAG_INTERRUPTABLE; //Подкрадывается
const int BS_RUN = 3; //Бежит
const int BS_SPRINT = 4; //Быстро бежит
const int BS_SWIM = 5; //Плывет
const int BS_CRAWL = 6; //Ползет
const int BS_DIVE = 7; //Ныряет
const int BS_JUMP = 8; //Прыгает
const int BS_CLIMB = 9 | BS_FLAG_INTERRUPTABLE; //Взбирается
const int BS_FALL = 10; //Падает
const int BS_SIT = 11 | BS_FLAG_FREEHANDS; //Сидит
const int BS_LIE = 12; //Лежит
const int BS_INVENTORY = 13; //Открывает инвентарь
const int BS_ITEMINTERACT = 14 | BS_FLAG_INTERRUPTABLE; //Действие с предметом
const int BS_MOBINTERACT = 15; //Действие с MOBом
const int BS_MOBINTERACT_INTERRUPT = 16 | BS_FLAG_INTERRUPTABLE; //Прерываемое действие с MOBом
const int BS_TAKEITEM = 17; //Берет предмет
const int BS_DROPITEM = 18; //Выкидывает предмет
const int BS_THROWITEM = 19; //Бросает предмет
const int BS_PICKPOCKET = 20 | BS_FLAG_INTERRUPTABLE; //Карманная кража
const int BS_STUMBLE = 21; //(не используется)
const int BS_UNCONPCIOUS = 22; //Без сознания
const int BS_DEAD = 23; //Мертвый
const int BS_AIMNEAR = 24; //Близкая цель
const int BS_AIMFAR = 25; //Далекая цель
const int BS_HIT = 26 | BS_FLAG_INTERRUPTABLE; //Удар
const int BS_PARADE = 27; //(не используется)
// Магия
const int BS_CASTING = 28; //Кастует
const int BS_PETRIFIED = 29; //Ошеломленный
const int BS_CONTROLLING = 30 | BS_FLAG_INTERRUPTABLE; //Управляемый
const int BS_MAX = 31; //Макс. кол-во состояний тела
// Модификаторы состояний

const int BS_MOD_HIDDEN = 128; //Скрытый
const int BS_MOD_DRUNK = 256; //Пьяный
const int BS_MOD_NUTS = 512; //???
const int BS_MOD_BURNING = 1024; //Горящий
const int BS_MOD_CONTROLLED = 2048; //Управляемый
const int BS_MOD_TRANSFORMED = 4096; //Трансформируемый
// имена MOBов

const string MOB_SIT = "BENCH,CHAIR,GROUND,THRONE";
const string MOB_LIE = "BED,BEDHIGH,BEDLOW";
const string MOB_CLIMB = "CLIMB,LADDER,RANKE";
const string MOB_NOTINTERRUPTABLE = "DOOR,LEVER,TOUCHPLATE,TURNSWITCH,VWHEEL,CHESTBIG,CHESTSMALL,HERB,IDOL,PAN,SMOKE,INNOS";
// Все другие MOBы, здесь не приведенные, являются прерываемыми, это:
// BOOK,BSANVIL,BSCOOL,BSFIRE,BSSHARP,CAULDRON,DRUM,GRAVE,LAB,ORE,REPAIR,RMAKER,BAU,MSAEGE,STOVE,SDW(Stein des Wissens)

В файле ..\AI_Intern\Focus.d описываются фокусы камеры (производные instance от класса c_focus) для следующих ситуаций:
Focus_Normal - обычный фокус камеры
Focus_Melee - фокус камеры при сражении оружием ближнег радиуса поражения
Focus_Ranged - фокус камеры при сражении оружием дальнего радиуса поражения
Focus_Throw_Item - фокус камеры при броске (метании) предмета
Focus_Throw_Mob - фокус камеры при броске (метании) МОВа
Focus_Magic - фокус камеры при кастовании заклинания

В файле ..\AI_Intern\Species.d описывается значение параметров всех гильдий
(производная instance gil_values от класса c_gilvalues)
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
3. Вывод отладочной информации.

Функции, ответственные за вывод отладочной информации, находятся в файле ..\AI_Intern\PrintDebug.d
К сожалению, все эти функции выводят информацию в окно zSpy с идентификатором определенного канала. На мой взгляд их применение очень проблематично и пользы от него мало. В скриптах по понятной причине вызов этих функций отсутствует, поэтому мы их рассматривать не будем.
В файле ..\AI_Intern\PrintPlus.d приведена функция вывода на экран строки текста со случайным числом в диапазоне от 0 до 100 в следующем формате: <text><random value 0-100>. Хоть эта функция и вызывается из одного файла, смысла ее применения я не вижу.
Эти файлы можно вообще исключить из компиляции.

Есть еще один файл ..\AI_Intern\NPC_SetToMad.d, правда он к отладке отношения не имеет, но заслуживает удаления по причине его бесполезности.

P.S. В скриптах очень много неиспользуемой и ненужной информации, для убыстрения работы игры и минимизации памяти все неиспользуемые функции и переменные можно удалить.
ВНИМАНИЕ!!! Нельзя удалять неиспользуемые поля в классах, а также добавлять новые, это потребует переделки экзешника!
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
4. Инициализация восприятий.

Функции инициализации восприятий описаны в файле ..\AI_Intern\Perception.d
//**************************************************
// Устанавливается дальность действия восприятий НПС
//**************************************************

func void InitPerceptions()
{
// Дальность действия всех активных восприятий определена константой PERC_DIST_ACTIVE_MAX, которая записывается в поле senses_range производной от класса c_npc.
// PERC_ASSESSPLAYER - восприятие ГГ другими НПС
// PERC_ASSESSENEMY - восприятие одного НПС другим НПС, у которого установлен флаг ATT_HOSTILE (враг), если Temp_Att != GilAtt, то возмется Temp_Att.
// PERC_ASSESSBODY - восприятие НПС мертвого тела, в настоящее время используется только в Monster-AI функциях.
// PERC_ASSESSFIGHTER - восприятие НПС ГГ с поднятым оружием или восприятие НПС всех монстров (они всегда находятся в режиме Fightmode)
// PERC_ASSESSITEM - восприятие НПС предметов
//*** ВНИМАНИЕ *** Активное восприятие работает только в случае, если у НПС активированы одно или несколько чувств. Зона действия активных восприятий 180° перед НПС по радиусу PERC_DIST_ACTIVE_MAX.
//*** ВНИМАНИЕ *** Зона действия пассивных восприятий 360° вокруг НПС на заданное расстояние.
// Сражение
Perc_SetRange(PERC_ASSESSDAMAGE,9999); //Посылается НПС, получившему повреждение. Дальность действия не используется.
Perc_SetRange(PERC_ASSESSOTHERSDAMAGE,PERC_DIST_INTERMEDIAT); //Посылается всем другим (other) НПС, если НПС получил повреждение
Perc_SetRange(PERC_ASSESSDEFEAT,WATCHFIGHT_DIST_MAX); //Посылается всем другим НПС, если НПС находится в бессознательном состоянии
Perc_SetRange(PERC_ASSESSMURDER,PERC_DIST_ACTIVE_MAX); //Посылается всем другим НПС, если НПС умер
Perc_SetRange(PERC_ASSESSTHREAT,PERC_DIST_INTERMEDIAT); //Посылается НПС в течении 2 секунд, если в него целится ГГ
Perc_SetRange(PERC_DRAWWEAPON,PERC_DIST_DIALOG); //Посылается всем другим НПС, если ГГ достает оружие
// Слух
Perc_SetRange(PERC_ASSESSFIGHTSOUND,3000); //Посылается всем другим НПС, если НПС на кого-то нападает с оружием
Perc_SetRange(PERC_ASSESSQUIETSOUND,PERC_DIST_INTERMEDIAT); //Посылается раз в секунду всем другим НПС, если ГГ идет или бежит, а также когда выброшен (уронен) какой-либо предмет
// Воровство
Perc_SetRange(PERC_ASSESSTHEFT,PERC_DIST_INTERMEDIAT); //Посылается всем другим НПС, если ГГ украл какой-либо предмет. При карманной краже обворованному не посылается. При телекинезе посылается всем.
Perc_SetRange(PERC_ASSESSUSEMOB,PERC_DIST_INTERMEDIAT); //Посылается всем другим НПС, если ГГ использует MOBsi
Perc_SetRange(PERC_ASSESSENTERROOM,PERC_DIST_INTERMEDIAT); //Посылается всем другим НПС, если ГГ входит в помещение
// Магия
Perc_SetRange(PERC_ASSESSMAGIC,9999); //Посылается НПС, против которого применена магия
Perc_SetRange(PERC_ASSESSSTOPMAGIC,9999); //Посылается НПС (жертве), если магия прекращает свое действие
// Разговор
Perc_SetRange(PERC_ASSESSTALK,PERC_DIST_DIALOG); //Посылается НПС, если у ГГ есть важная информация для разговора
// Взаимодействие НПС
Perc_SetRange(PERC_ASSESSWARN,PERC_DIST_INTERMEDIAT); //Чисто скриптовое восприятие, кому посылаем, тот и реагирует
// Открытие дверей
Perc_SetRange(PERC_MOVEMOB,PERC_DIST_DIALOG); //Посылается всем другим НПС, если ГГ открывает дверь (сундук)
// Превращение
Perc_SetRange(PERC_ASSESSSURPRISE,FIGHT_DIST_CANCEL); //Посылается всем другим НПС, если ГГ превращается в себя из животного
// Не используются!
Perc_SetRange(PERC_OBSERVEINTRUDER,100); //Посылается всем другим НПС, если ГГ останавливается (кроме режима подкрадывания)
Perc_SetRange(PERC_ASSESSREMOVEWEAPON,100); //Посылается всем другим НПС, если ГГ прячет оружие
Perc_SetRange(PERC_CATCHTHIEF,100); //Посылается всем другим НПС, если ГГ пойман на карманной краже
Perc_SetRange(PERC_ASSESSCALL,100); //Посылается НПС, если ГГ призывает его к разговору (дальняя дистанция)
Perc_SetRange(PERC_MOVENPC,100); //Посылается всем другим НПС, если ГГ идет вместе с НПС
Perc_SetRange(PERC_ASSESSCASTER,100); //Посылается всем другим НПС, если ГГ инвестирует ману
Perc_SetRange(PERC_NPCCOMMAND,100); //Чисто скриптовое восприятие, можно использовать по своему усмотрению
Perc_SetRange(PERC_OBSERVESUSPECT,100); //Посылается всем другим НПС, если ГГ подкрадывается (в движении)
//Мной не обнаружены упоминания о следующих восприятиях: PERC_ASSESSGIVENITEM, PERC_ASSESSFAKEGUILD
};
//*************************************************************
// Установка функций реакций НПС на нормальный набор восприятий для людей
//*************************************************************

func void Perception_Set_Normal()
{
// Активные чувства при каждом состоянии активизируются по-новому, т.к. они изменяются в функции ZS_Guide_Player
self.senses = SENSE_HEAR | SENSE_SEE;
self.senses_range = PERC_DIST_ACTIVE_MAX;
// Частота проверки активных восприятий
if(Npc_KnowsInfo(self,1) || C_NpcIsGateGuard(self)) //если НПС имеет важную информацию или НПС охраняет вход
{
Npc_SetPercTime(self,0.3); //восприятия проверяются раз в 0.3 секунды
}
else
{
Npc_SetPercTime(self,1); //иначе восприятия проверяются раз в секунду
};
// Активные восприятия (приоритет наивысший)
Npc_PercEnable(self,PERC_ASSESSPLAYER, B_AssessPlayer);
Npc_PercEnable(self,PERC_ASSESSENEMY, B_AssessEnemy);
// Пассивные восприятия (приоритет задается последовательностью регистрации)
Npc_PercEnable(self,PERC_ASSESSMAGIC, B_AssessMagic);
Npc_PercEnable(self,PERC_ASSESSDAMAGE, B_AssessDamage);
Npc_PercEnable(self,PERC_ASSESSMURDER, B_AssessMurder);
Npc_PercEnable(self,PERC_ASSESSTHEFT, B_AssessTheft);
Npc_PercEnable(self,PERC_ASSESSUSEMOB, B_AssessUseMob);
Npc_PercEnable(self,PERC_ASSESSENTERROOM, B_AssessPortalCollision);
Npc_PercEnable(self,PERC_ASSESSTHREAT, B_AssessThreat);
Npc_PercEnable(self,PERC_DRAWWEAPON, B_AssessDrawWeapon);
Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND, B_AssessFightSound);
Npc_PercEnable(self,PERC_ASSESSQUIETSOUND, B_AssessQuietSound);
Npc_PercEnable(self,PERC_ASSESSWARN, B_AssessWarn);
Npc_PercEnable(self,PERC_ASSESSTALK, B_AssessTalk);
Npc_PercEnable(self,PERC_MOVEMOB, B_MoveMob);
};
//********************************************************************
// Установка функций реакций НПС на минимальный набор восприятий для людей (всегда должны быть активны)
//********************************************************************

func void Perception_Set_Minimal()
{
self.senses = SENSE_HEAR | SENSE_SEE;
self.senses_range = PERC_DIST_ACTIVE_MAX;
Npc_PercEnable(self,PERC_ASSESSMAGIC, B_AssessMagic);
Npc_PercEnable(self,PERC_ASSESSDAMAGE, B_AssessDamage);
Npc_PercEnable(self,PERC_ASSESSMURDER, B_AssessMurder);
Npc_PercEnable(self,PERC_ASSESSTHEFT, B_AssessTheft);
Npc_PercEnable(self,PERC_ASSESSUSEMOB, B_AssessUseMob);
Npc_PercEnable(self,PERC_ASSESSENTERROOM, B_AssessPortalCollision);
};
//************************************************************
// Закрытие реакций НПС slf на восприятия для людей и монстров
//************************************************************

func void B_ClearPerceptions(var c_npc slf)
{
Npc_PercDisable(slf,PERC_ASSESSPLAYER);
Npc_PercDisable(slf,PERC_ASSESSENEMY);
Npc_PercDisable(slf,PERC_ASSESSBODY);
Npc_PercDisable(slf,PERC_ASSESSMAGIC);
Npc_PercDisable(slf,PERC_ASSESSDAMAGE);
Npc_PercDisable(slf,PERC_ASSESSMURDER);
Npc_PercDisable(slf,PERC_ASSESSTHEFT);
Npc_PercDisable(slf,PERC_ASSESSUSEMOB);
Npc_PercDisable(slf,PERC_ASSESSENTERROOM);
Npc_PercDisable(slf,PERC_ASSESSTHREAT);
Npc_PercDisable(slf,PERC_DRAWWEAPON);
Npc_PercDisable(slf,PERC_ASSESSFIGHTSOUND);
Npc_PercDisable(slf,PERC_ASSESSQUIETSOUND);
Npc_PercDisable(slf,PERC_ASSESSWARN);
Npc_PercDisable(slf,PERC_ASSESSTALK);
Npc_PercDisable(slf,PERC_MOVEMOB);
Npc_PercDisable(slf,PERC_ASSESSOTHERSDAMAGE);
Npc_PercDisable(slf,PERC_ASSESSSTOPMAGIC);
Npc_PercDisable(slf,PERC_ASSESSSURPRISE);
};
//*********************************************************
// Установка функций реакций монстров и орков на восприятия
//*********************************************************

func void Perception_Set_Monster_Rtn()
{
Npc_SetPercTime(self,1); //частота проверки восприятия раз в секунду
Npc_PercEnable(self,PERC_ASSESSENEMY, B_MM_AssessEnemy);
Npc_PercEnable(self,PERC_ASSESSBODY, B_MM_AssessBody);
Npc_PercEnable(self,PERC_ASSESSMAGIC, B_AssessMagic);
Npc_PercEnable(self,PERC_ASSESSDAMAGE, B_MM_AssessDamage);
Npc_PercEnable(self,PERC_ASSESSOTHERSDAMAGE, B_MM_AssessOthersDamage);
Npc_PercEnable(self,PERC_ASSESSMURDER, B_MM_AssessOthersDamage);
Npc_PercEnable(self,PERC_ASSESSWARN, B_MM_AssessWarn);
};
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
5. Функции обработки восприятий людей.

//*******************************************************
// Функция реакции НПС (людей) на ГГ (обработка активного восприятия PERC_ASSESSPLAYER).
// ГГ должен быть в поле зрения НПС (люди не имеют чувства обоняния)
// Макс. дистанция реакции на ГГ - PERC_DIST_ACTIVE_MAX.
//*******************************************************

func void B_AssessPlayer()
{
// other в функции - ГГ, self - НПС
// Тестовый режим: Игнорирование Инспектора уровня
var c_npc PCL;
PCL = Hlp_GetNpc(PC_Levelinspektor);
// Если ГГ является Инспектором уровня
if(Hlp_GetInstanceID(other) == Hlp_GetInstanceID(PCL))
{
return;
};
// Если ГГ находится в режиме диалога
if(other.aivar[AIV_INVINCIBLE] == TRUE)
{
return;
};
// Если ГГ мертв, без сознания или в магическом сне
if(C_NpcIsDown(other))
{
return;
};
// Если ГГ превращен в монстра
if(other.guild > GIL_SEPERATOR_HUM)
{
// Если НПС охранник, то он должен задержать любого монстра
if(C_NpcIsGateGuard(self))
{
// НПС встает
AI_StandUpQuick(self);
// вызов функции сражения
B_Attack(self,other,AR_MonsterCloseToGate,0);
return;
}
// если гильдии ГГ и НПС враждебны
else if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_HOSTILE)
{
// если НПС не сопровождает ГГ и НПС не является другом ГГ
if(self.aivar[AIV_PARTYMEMBER] == FALSE) && (self.npctype != NPCTYPE_FRIEND)
{
// вызов функции сражения
B_Attack(self,other,AR_GuildEnemy,0);
return;
};
};
};
// Если ГГ враг
if(B_AssessEnemy())
{
return;
};
// Если ГГ бандит и НПС не бандит
if(C_PlayerIsFakeBandit(self,other) && (self.guild != GIL_BDT))
{
// вызов функции сражения
B_Attack(self,other,AR_GuildEnemy,0);
};
// Если ГГ убийца и НПС должен атаковать убийцу и расстояние между ГГ и НПС <= PERC_DIST_INTERMEDIAT
if(B_GetPlayerCrime(self) == CRIME_MURDER) && C_WantToAttackMurder(self,other) && (Npc_GetDistToNpc(self,other) <= PERC_DIST_INTERMEDIAT)
{
// вызов функции сражения
B_Attack(self,other,AR_HumanMurderedHuman,0);
return;
};
// Если ГГ вошел в помещение, ему не принадлежащее
if(B_AssessEnterRoom())
{
return;
};
// Если оружие ГГ обнажено
if(B_AssessDrawWeapon())
{
return;
}
else // сброс флага комментирования обнаженного оружия
{
Player_DrawWeaponComment = FALSE;
};
// Если ГГ подкрадывается
if(C_BodyStateContains(other,BS_SNEAK))
{
// если НПС не наблюдает за ГГ и НПС должен реагировать на крадущегося ГГ
if(!Npc_IsInState(self,ZS_ObservePlayer) && C_WantToReactToSneaker(self,other))
{
// очистка AI команд НПС
Npc_ClearAIQueue(self);
// очистка восприятий НПС
B_ClearPerceptions(self);
// перевод НПС в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,1,"");
return;
};
}
else // ГГ не подкрадывается
{
// если ГГ не стоит
if(!C_BodyStateContains(other,BS_STAND))
{
// сброс флага комментирования крадущегося ГГ
Player_SneakerComment = FALSE;
};
};
// Если ГГ не лежит
if(!C_BodyStateContains(other,BS_LIE))
{
// сброс флага комментирования, что ГГ лег на чужую кровать
Player_GetOutOfMyBedComment = FALSE;
};
// Важная информация для окружающих черных магов (я так понимаю, что это ищущие)
B_AssignDementorTalk(self);
//*********** Диалог*************
// Если расстояние между ГГ и НПС <= дистанции начала разговора и НПС имеет важную информацию
if(Npc_GetDistToNpc(self,other) <= PERC_DIST_DIALOG) && (Npc_CheckInfo(self,1))
{
// Если НПС охраняет ворота
if(C_NpcIsGateGuard(self))
{
// установка флага для НПС при обращении с важной информацией к ГГ
self.aivar[AIV_NpcStartedTalk] = TRUE;
// функция диалога
B_AssessTalk();
return;
}
else //для других НПС
{
// если ГГ не падает и не плывет и не ныряет
if(!C_BodyStateContains(other,BS_FALL)) && (!C_BodyStateContains(other,BS_SWIM)) && (!C_BodyStateContains(other,BS_DIVE))
// и ГГ не занимается криминалом
&& (B_GetPlayerCrime(self) == CRIME_NONE)
// и ГГ не отказался от разговора с НПС
&& (C_RefuseTalk(self,other) == FALSE)
// и ГГ не является членом подставной гильдии
&& (C_PlayerHasFakeGuild(self,other) == FALSE)
{
// установка флага для НПС при обращении с важной информацией к ГГ
self.aivar[AIV_NpcStartedTalk] = TRUE;
// функция диалога
B_AssessTalk();
return;
};
};
};
//*********** Приветствие*************
// если НПС идет и расстояние между ГГ и НПС <= дистанции начала разговора

if (C_BodyStateContains(self,BS_WALK)) && (Npc_GetDistToNpc(self,other) <= PERC_DIST_DIALOG)
// и ГГ не отказался от диалога и НПС не охранник
&& (Npc_RefuseTalk(other) == FALSE) && (!C_NpcIsGateGuard(self))
// и ГГ не является членом подставной гильдии
&& (C_PlayerHasFakeGuild(self,other) == FALSE)
{
// НПС и ГГ смотрят друг на друга
B_LookAtNpc(self,other);
// звучит приветственная фраза
B_Say_GuildGreetings(self,other);
// НПС и ГГ перестают смотреть друг на друга
B_StopLookAt(self);
// отказ ГГ от диалога на 20 секунд
Npc_SetRefuseTalk(other,20);
};
//*********** Сброс предупреждений охраной*************
// если НПС охранник и расстояние между ГГ и НПС > дистанции начала разговора
if(C_NpcIsGateGuard(self)) && (Npc_GetDistToNpc(self,other) > PERC_DIST_DIALOG)
{
// Статус предупреждений охраны = Нет предупреждений
self.aivar[AIV_Guardpassage_Status] = GP_NONE;
};
return;
};


// ********************************************************************************
// Функция реакции НПС (людей) на врага (обработка активного восприятия PERC_ASSESSENEMY).
// враг должен быть в поле зрения НПС (люди не имеют чувства обоняния)
// Макс. дистанция реакции на врага - PERC_DIST_ACTIVE_MAX.
// ********************************************************************************
// Возвращает TRUE, если реакция НПС на врага закончилась сражением
// ********************************************************************************


func int B_AssessEnemy()
{
// other в функции - враг, self - НПС
// Тестовый режим: Игнорирование Инспектора уровня
var c_npc PCL;
PCL = Hlp_GetNpc(PC_Levelinspektor);
// Если враг является Инспектором уровня
if(Hlp_GetInstanceID(other) == Hlp_GetInstanceID(PCL))
{
return FALSE;
};
// Аддон
// Если (враг не ГГ и враг человек)
if((Hlp_GetInstanceID(other) != Hlp_GetInstanceID(hero)) && (other.guild < GIL_SEPERATOR_HUM)
// и (НПС не может атаковать или враг не может атаковать))
&& ((self.aivar[AIV_NoFightParker] == TRUE) || (other.aivar[AIV_NoFightParker] == TRUE)))
// или (враг монстр и враг не может атаковать)
|| ((other.guild > GIL_SEPERATOR_HUM) && (other.aivar[AIV_NoFightParker] == TRUE))
{
return FALSE;
};
// Аддон
// Если (враг плывет или враг ныряет) и НПС не хочет лезть в воду
if(C_BodyStateContains(other,BS_SWIM) || C_BodyStateContains(other,BS_DIVE)) && (self.aivar[AIV_MM_FollowInWater] == FALSE)
{
return FALSE;
};
// Если расстояние по высоте между НПС и врагом > дистанции реагирования по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT)
{
return FALSE;
};
// Если НПС член партии
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
// если дистанция между НПС и врагом > 1.5 метра
if(Npc_GetDistToNpc(self,other) > 1500)
{
return FALSE;
};
// если НПС не видит врага
if(!Npc_CanSeeNpc(self, other))
{
return FALSE;
};
};
// Если враг является переодетым бандитом и НПС бандит
if(C_PlayerisFakeBandit(self,other)) && (self.guild == GIL_BDT)
{
return FALSE;
};
// Магический Голем
var c_npc MGO; MGO = Hlp_GetNpc(MagicGolem);
// Ларес
var c_npc LAR; LAR = Hlp_GetNpc(VLK_449_Lares);
// Если НПС есть Ларес и враг есть Магический Голем
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(LAR)) && (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(MGO))
{
return FALSE;
};
// Если (врагов у НПС нет или врагов у врага нет) и враг человек
if((self.aivar[AIV_EnemyOverride] == TRUE) || (other.aivar[AIV_EnemyOverride] == TRUE)) && (other.guild < GIL_SEPERATOR_HUM)
{
return FALSE;
};
// Если отношения между НПС и врагом не вражеские
if(Npc_GetAttitude(self,other) != ATT_HOSTILE)
{
return FALSE;
};
// Если НПС охраняет ворота
if(C_NpcIsGateGuard(self))
{
return FALSE;
};

// Если враг есть ГГ и НПС ему друг
if(Npc_IsPlayer(other) && (self.npctype == NPCTYPE_FRIEND))
{
return FALSE;
};
// Если гильдии НПС и врага не враждуют между собой
if(Wld_GetGuildAttitude(self.guild,other.guild) != ATT_HOSTILE)
{
// Если НПС враждебен к врагу [Примечание, далее врагом может быть только ГГ, т.к. прочие НПС не имеют temp_att к другим НПС]
if(Npc_GetAttitude(self,other) == ATT_HOSTILE)
// и (НПС находится в текущем состоянии > 2 секунд или НПС наблюдает за ГГ)
&& ((Npc_GetStateTime(self) > 2) || Npc_IsInState(self,ZS_ObservePlayer))
// и дистанция между НПС и ГГ <= дальности действия пассивного восприятия
&& (Npc_GetDistToNpc(self,other) <= PERC_DIST_INTERMEDIAT)
{
// вызов функции сражения
B_Attack(self, other, self.aivar[AIV_LastPlayerAR], 0);
return TRUE;
}
else
{
return FALSE;
};
};
// В любом другом случае вызов функции сражения
B_Attack(self,other,AR_GuildEnemy,0);
return TRUE;
};


// ****************************************************************
// Функция реакции людей на повреждение
// ****************************************************************


func void B_AssessDamage()
{
// self - жертва, other - агрессор
var c_npc Quarho;
// Куарходрон
Quarho = Hlp_GetNpc(NONE_ADDON_111_Quarhodron);
var c_npc Rhadem;
// Радемес
Rhadem = Hlp_GetNpc(NONE_ADDON_112_Rhademes);
// Если жертва Куарходрон или Радемес
if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Quarho))) || ((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Rhadem)))
{
// вызов функции реакции на повреждение для призраков
B_GhostSpecialDamage(other,self);
return;
};
// вызов функции реакции на повреждение "Когтем Белиара"
B_BeliarsWeaponSpecialDamage(other,self);
// если жертва Альрик получает повреждение после того, как он сдался
if(self.aivar[AIV_ArenaFight] == AF_AFTER)
{
// ГГ нечестно выиграл сражение с Альриком
self.aivar[AIV_ArenaFight] = AF_AFTER_PLUS_DAMAGE;
};
// если у жертвы врагов не было
if(self.aivar[AIV_EnemyOverride] == TRUE)
{
var c_npc RAV;
// Равен
RAV = Hlp_GetNpc(BDT_1090_Addon_Raven);
// если Равен жертва
if(Hlp_GetInstanceID(self) == (Hlp_GetInstanceID(RAV)))
{
// теперь у Равена есть враг
self.aivar[AIV_EnemyOverride] = FALSE;
};
};
// если жертва находится в состоянии атаки
if(Npc_IsInState(self,ZS_Attack))
{
// если ГГ агрессор и жертва друг ГГ (Примечание: защита от нанесения повреждений ГГ своему другу, если они вместе с кем-то сражаются)
if(Npc_IsPlayer(other)) && (self.npctype == NPCTYPE_FRIEND)
{
return;
};
// если ГГ агрессор и жертва член партии ГГ
if(Npc_IsPlayer(other)) && (self.aivar[AIV_PARTYMEMBER] == TRUE)
{
return;
};
// если НПС агрессор не является НПС, атакованным жертвой
if(Hlp_GetInstanceID(other) != self.aivar[AIV_LASTTARGET])
{
// если удар жертве нанесен агрессором не первый раз или агрессор не ГГ
if(self.aivar[AIV_HitByOtherNpc] == Hlp_GetInstanceID(other)) || (Hlp_GetInstanceID(other) != Hlp_GetInstanceID(hero))
{
// смена цели (жертва будет атаковать агрессора)
Npc_SetTarget(self,other);
}
else
{
// при первом ударе жертве записывается ID агрессора
self.aivar[AIV_HitByOtherNpc] = Hlp_GetInstanceID(other);
};
};
return;
};
// реакция жертвы на врага
if(B_AssessEnemy())
{
return;
};
// если НПС агрессор не ГГ и причины нападать у него не было
if(!Npc_IsPlayer(other)) && (other.aivar[AIV_ATTACKREASON] == AR_NONE)
{
// жертва атакует НПС агрессора
B_Attack(self,other,AR_NONE,0);
return;
};
// если агрессор нападает с мечом или с кулаками или вышел из режима нападения (спрятал оружие)
if(Npc_IsInFightMode(other,FMODE_MELEE)) || (Npc_IsInFightMode(other,FMODE_FIST)) || (Npc_IsInFightMode(other,FMODE_NONE))
{
// если отношения между агрессором и жертвой дружеские или жертва является другом агрессора ГГ
if(Npc_GetAttitude(self,other) == ATT_FRIENDLY) || ((self.npctype == NPCTYPE_FRIEND) && Npc_IsPlayer(other))
{
// если жертва не находится в состоянии реакции на повреждение
if(!Npc_IsInState(self,ZS_ReactToDamage))
{
// очистка очереди состояний жертвы
Npc_ClearAIQueue(self);
// очистка восприятий жертвы
B_ClearPerceptions(self);
// перевод жертвы в состояние реакции на повреждение
AI_StartState(self,ZS_ReactToDamage,0,"");
return;
};
};
};
// жертва атакует агрессора
B_Attack(self,other,AR_ReactToDamage,0);
return;
};


// ****************************************************
// Функция реакции людей на убийство
// ****************************************************


func void B_AssessMurder()
{
// self - свидетель убийства, other - преступник (убийца), victim - жертва (труп)
// если свидетель убийца
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(other))
{
return;
};
// если расстояния между (свидетелем и преступником) и (свидетелем и жертвой) > макс. дальности действия восприятия
if(Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT) && (Npc_GetDistToNpc(self,victim) > PERC_DIST_INTERMEDIAT)
{
return;
};
// если расстояния по высоте между (свидетелем и преступником) и (свидетелем и жертвой) > дальности реакций НПС
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT) && (Npc_GetHeightToNpc(self,victim) > PERC_DIST_HEIGHT)
{
return;
};
// если свидетель не видит преступника и свидетель не видит жертву
if(!Npc_CanSeeNpcFreeLOS(self,other)) && (!Npc_CanSeeNpcFreeLOS(self,victim))
{
return;
};
// вызов функции реакции свидетеля на преступника (врага)
if(B_AssessEnemy())
{
return;
};
// если жертва овца и она убита не "крутым парнем"
if(victim.guild == GIL_SHEEP) && (victim.aivar[AIV_ToughGuy] == FALSE)
{
// если есть причина свидетелю атаковать преступника
if(C_WantToAttackSheepKiller(self,other))
{
// вызов функции атаки
B_Attack(self,other,AR_SheepKiller,0);
return;
}
else // в противном случае
{
// если свидетель является охранником ворот
if(C_NpcIsGateGuard(self))
{
// свидетель запоминает новость, что преступник убил овцу
B_MemorizePlayerCrime(self,other,CRIME_SHEEPKILLER);
};
};
};
// если преступник монстр и жертва монстр
if(other.guild > GIL_SEPERATOR_HUM) && (victim.guild > GIL_SEPERATOR_HUM)
{
return;
};
// если преступник монстр
if(other.guild > GIL_SEPERATOR_HUM)
{
// свидетель атакует монстра
B_Attack(self,other,AR_MonsterMurderedHuman,0);
return;
};
// если жертва монстр
if(victim.guild > GIL_SEPERATOR_HUM)
{
return;
};
// если у свидетеля врагов не было
if(self.aivar[AIV_EnemyOverride] == TRUE)
{
// теперь у свидетеля есть враг
self.aivar[AIV_EnemyOverride] = FALSE;
// свидетелю разрешено воспринимать все объекты в зоне действия восприятия
Npc_PerceiveAll(self);
// поиск свидетелем цели
Npc_GetNextTarget(self);
// если преступник существует и он не бессознателен
if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other))
{
// свидетель атакует преступника
B_Attack(self,other,AR_GuildEnemy,0);
return;
};
return;
};
// если (свидетель враждебен к жертве или свидетель зол на жертву)
if((Npc_GetAttitude(self,victim) == ATT_HOSTILE) || (Npc_GetAttitude(self,victim) == ATT_ANGRY))
// и (свидетель друг преступника или свидетель нейтрален к преступнику)
&& ((Npc_GetAttitude(self,other) == ATT_FRIENDLY) || (Npc_GetAttitude(self,other) == ATT_NEUTRAL))
{
return;
};
// если преступник ГГ и свидетель его друг
if(Npc_IsPlayer(other) && (self.npctype == NPCTYPE_FRIEND))
{
return;
};
// если свидетель не должен реагировать на убийство
if(!C_WantToAttackMurder(self,other))
{
// если свидетель является охранником ворот
if(C_NpcIsGateGuard(self))
{
// свидетель запоминает новость, что преступник убийца
B_MemorizePlayerCrime(self,other,CRIME_MURDER);
};
return;
};
// если преступник и жертва являются НПС, которым разрешено убить друг друга
if(other.aivar[AIV_DropDeadAndKill] == TRUE) || (victim.aivar[AIV_DropDeadAndKill] == TRUE)
{
return;
};
// если жертва черный маг (ищущий) или (жертва бандит и он не из Лагеря бандитов)
if(victim.guild == GIL_DMT) || ((victim.guild == GIL_BDT) && !C_NpcBelongsToBL(victim))
{
return;
};
// свидетель атакует преступника
B_Attack(self,other,AR_HumanMurderedHuman,0);
return;
};


// ***********************************************************
// Функция реакции людей на воровство
// ***********************************************************
// Вызывается в качестве реакции на пассивное восприятие PERC_ASSESSTHEFT
// в зоне действия PERC_DIST_INTERMEDIAT когда НПС поднимает какой-либо предмет
// ***********************************************************


func void B_AssessTheft()
{
// other - вор, self - свидетель
// если вор не ГГ
if(!Npc_IsPlayer(other))
{
return;
};
// если ГГ находится в доме, принадлежащим любой гильдии, и расстояние между свидетелем и вором > дистанции реакции через закрытые двери
if(Wld_GetPlayerPortalGuild() >= GIL_NONE) && (Npc_GetHeightToNpc(self,other) > PERC_DIST_INDOOR_HEIGHT)
{
return;
};
// если гильдии вора и свидетеля дружественны
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_FRIENDLY)
{
// если предмет существует и он принадлежит свидетелю
if(Hlp_IsValidItem(item)) && (Npc_OwnedByNpc(item,self))
{
// продолжаем анализ ситуации дальше
}
else
{
return;
};
};
// если предмет принадлежал ГГ ранее
if(!C_IsTakenItemMyPossession(self,other,item))
{
return;
};
// если свидетель не видит вора
if(!Npc_CanSeeNpc(self,other))
{
// если свидетель и ГГ находится в одном помещении и если (свидетель наблюдает за ГГ или свидетель находится в состоянии "незваного гостя")
if(Npc_IsInPlayersRoom(self)) && ((Npc_IsInState(self,ZS_ObservePlayer)) || (Npc_IsInState(self,ZS_ClearRoom)))
{
// продолжаем анализ ситуации дальше
}
else
{
return;
};
};
// если свидетель игнорирует вора
if(!C_WantToAttackThief(self,other))
{
// если свидетель является охранником ворот
if(C_NpcIsGateGuard(self))
{
// свидетель запоминает новость, что ГГ вор
B_MemorizePlayerCrime(self,other,CRIME_THEFT);
};
return;
};
// свидетель атакует вора
B_Attack(self,other,AR_Theft,0);
return;
};


// ****************************************************
// Функция реакции людей на использование МОB's
// ****************************************************


func void B_AssessUseMob()
{
// other - пользователь, self - свидетель
// если пользователь не ГГ
if(!Npc_IsPlayer(other))
{
return;
};
// если ГГ находится в доме, принадлежащим любой гильдии
if(Wld_GetPlayerPortalGuild() >= GIL_NONE)
{
// если расстояние между свидетелем и пользователем > дистанции реакции через закрытые двери
if (Npc_GetHeightToNpc(self,other) > PERC_DIST_INDOOR_HEIGHT)
{
return;
};
};
// если гильдии пользователя и свидетеля дружественны
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_FRIENDLY)
{
// если МОВ принадлежит свидетелю
if(Npc_IsDetectedMobOwnedByNpc(other,self))
{
// продолжаем анализ ситуации дальше
}
else
{
return;
};
};
// если МОВ принадлежал ГГ ранее
if(!C_IsUsedMobMyPossession(self,other))
{
return;
};
// если свидетель не видит пользователя
if(!Npc_CanSeeNpc(self,other))
{
// если свидетель и ГГ находятся в одном помещении и если (свидетель наблюдает за ГГ или свидетель находится в состоянии "незваного гостя")
if(Npc_IsInPlayersRoom(self)) && ((Npc_IsInState(self,ZS_ObservePlayer)) || (Npc_IsInState(self,ZS_ClearRoom)))
{
// продолжаем анализ ситуации дальше
}
else
{
return;
};
};
var string detMob;
// получить название МОВа, используемого ГГ
detMob = Npc_GetDetectedMob(other);
// если МОВ не "Большой сундук" и МОВ не "Маленький сундук"
if(Hlp_StrCmp(detMob,"CHESTBIG") == FALSE) && (Hlp_StrCmp(detMob,"CHESTSMALL") == FALSE)
{
return;
};
// если свидетель игнорирует пользователя
if(!C_WantToAttackThief(self,other))
{
// если свидетель является охранником ворот
if (C_NpcIsGateGuard(self))
{
// свидетель запоминает новость, что ГГ вор
B_MemorizePlayerCrime(self,other,CRIME_THEFT);
};
return;
};
// свидетель атакует пользователя
B_Attack(self,other,AR_UseMob,0);
return;
};


// ********************************************************************************
// Функция реакции людей на вход НПС в помещение
// ----------------------------------------
// Возвращает TRUE при реакции на вошедшего или FALSE, когда на вошедшего не реагируют
// ********************************************************************************


func int B_AssessEnterRoom()
{
// other - вошедший, self - свидетель
var int portalguild;
// получить номер гильдии, которой принадлежит помещение (-1 помещение никому не принадлежит)
portalguild = Wld_GetPlayerPortalGuild();
// если вошедший ГГ и комментарий входа уже был и помещение принадлежит какой-либо гильдии и помещение не публичное
if(Npc_IsPlayer(other)) && (Player_LeftRoomComment == TRUE) && (portalguild > GIL_NONE) && (portalguild != GIL_PUBLIC)
{
// сброс комментария входа
Player_LeftRoomComment = FALSE;
};
// если расстояние между вошедшим и свидетелем > 10м
if(Npc_GetDistToNpc(self,other) > 1000)
{
return FALSE;
};
// если свидетель и вошедший (ГГ) находятся не в одном помещении и свидетель находится не снаружи помещения
if(!Npc_IsInPlayersRoom(self)) && (!(Npc_GetPortalGuild(self) < GIL_NONE))
{
return FALSE;
};
// если свидетель находится в состоянии атаки
if(Npc_IsInState(self,ZS_Attack))
{
return FALSE;
};
// если свидетель является охранником ворот
if(C_NpcIsGateGuard(self))
{
return FALSE;
};
// если вошедший не ГГ
if(!Npc_IsPlayer(other))
{
return FALSE;
};
// если свидетель друг ГГ
if(self.npctype == NPCTYPE_FRIEND)
{
return FALSE;
};
// если отношения между свидетелем и ГГ дружеские
if(Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
return FALSE;
};
// если ГГ крадется или ГГ стоит
if(C_BodyStateContains(other,BS_SNEAK)) || (C_BodyStateContains(other,BS_STAND))
{
// если свидетель не видит ГГ и свидетель не наблюдает за ГГ
if(!Npc_CanSeeNpc(self,other)) && (!Npc_IsInState(self,ZS_ObservePlayer))
{
return FALSE;
};
};
// если свидетель не принадлежит к гильдии
if(self.guild == GIL_NONE)
{
return FALSE;
};
// если свидетель и ГГ находятся не в одном помещениии и свидетель спит
if(!Npc_IsInPlayersRoom(self)) && (Npc_IsInState(self,ZS_Sleep))
{
return FALSE;
};
// если помещение публично и свидетель находится в одном помещении с ГГ
if(portalguild == GIL_PUBLIC) && (Npc_IsInPlayersRoom(self))
{
// если свидетель наблюдает за ГГ
if(Npc_IsInState(self,ZS_ObservePlayer))
{
return FALSE;
};
// если свидетель лежит
if(C_BodyStateContains(self,BS_LIE))
{
// свидетель встает (Примечание: мне непонятно как он это делает)
B_MM_DeSynchronize();
};
// если свидетель
if(Npc_IsInState(self,ZS_Potion_Alchemy)) // занимается алхимией
|| (Npc_IsInState(self,ZS_Read_Bookstand)) // или читает книгу
|| (Npc_IsInState(self,ZS_Sit_Bench)) // или сидит на скамье
|| (Npc_IsInState(self,ZS_Sit_Campfire)) // или сидит у костра
|| (Npc_IsInState(self,ZS_Sit_Chair)) // или сидит на стуле
|| (Npc_IsInState(self,ZS_Sit_Throne)) // или сидит на троне
|| (Npc_IsInState(self,ZS_Sleep)) // или спит
|| (Npc_IsInState(self,ZS_Smalltalk)) // или ведет светскую беседу
|| (Npc_IsInState(self,ZS_Smoke_Joint)) // или курит
|| (Npc_IsInState(self,ZS_Stand_ArmsCrossed)) // или стоит со скрещенными руками
|| (Npc_IsInState(self,ZS_Stand_Drinking)) // или пьет
|| (Npc_IsInState(self,ZS_Stand_Eating)) // или ест
|| (Npc_IsInState(self,ZS_Stand_Guarding)) // или охраняет
|| (Npc_IsInState(self,ZS_Stand_WP)) // или стоит на вайпоинте
{
// очистка очереди состояний свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// если свидетель сидит
if(C_BodyStateContains(self,BS_SIT))
{
// перевод свидетеля в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,0,"");
}
else
{
// перевод свидетеля в состояние наблюдения за ГГ (выполняется только функция конца состояния)
AI_StartState(self,ZS_ObservePlayer,1,"");
};
return TRUE;
}
else
{
return FALSE;
};
};
// если ГГ находится в частном помещении
if(C_NpcIsBotheredByPlayerRoomGuild(self))
{
Npc_ClearAIQueue(self);
B_ClearPerceptions(self);
// перевод свидетеля в состояние "защиты помещения"
AI_StartState(self,ZS_ClearRoom,1,"");
return TRUE;
};
return FALSE;
};

// *************************************************************
// Функция реакции людей на вход НПС в помещение
// ------------------------------------------------
// Вызывается как реакция на пассивное восприятие PERC_ASSESSENTERROOM
// *************************************************************


func void B_AssessPortalCollision()
{
// other - вошедший, self - свидетель
var int formerportalguild;
// получить номер гильдии, которой принадлежит помещение в котором прежде находился ГГ (-1 помещение никому не принадлежит)
formerportalguild = Wld_GetFormerPlayerPortalGuild();
// если есть реакция на вошедшего в помещение
if(B_AssessEnterRoom())
{
return;
};
// если свидетель не видит вошедшего и (вошедший крадется или вошедший стоит)
if(!Npc_CanSeeNpc(self,other)) && (C_BodyStateContains(other,BS_SNEAK) || C_BodyStateContains(other,BS_STAND))
{
return;
};
// свидетелю разрешено воспринимать все объекты в зоне действия восприятия
Npc_PerceiveAll(self);
// если свидетель находит другого НПС в состоянии "защиты помещения"
if(Wld_DetectNpcEx(self,-1,ZS_ClearRoom,-1,FALSE))
{
return;
};
// если покинутое ГГ помещение принадлежит гильдии свидетеля или свидетель друг гильдии, которой принадлежит помещение
if(self.guild == formerportalguild) || (Wld_GetGuildAttitude(self.guild,formerportalguild) == ATT_FRIENDLY)
{
// если отношения между гильдиями ГГ и свидетеля дружеские или (вошедший ГГ и друг свидетеля)
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_FRIENDLY) || (Npc_IsPlayer(other) && (self.npctype == NPCTYPE_FRIEND))
{
return;
};
// если свидетель не принадлежит к гильдии
if(self.guild == GIL_NONE)
{
return;
};
// если (помещение принадлежит милиции или ополчению) и свидетель является другом этих гильдии
if((formerportalguild == GIL_MIL) || (formerportalguild == GIL_SLD)) && (Wld_GetGuildAttitude(self.guild,formerportalguild) == ATT_FRIENDLY)
{
// свидетель атакует ГГ
B_Attack(self,other,AR_LeftPortalRoom,0);
return;
}
else // иначе
{
// свидетель наблюдает за помещением
self.aivar[AIV_SeenLeftRoom] = TRUE;
// очистка очереди состояний свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,0,"");
return;
};
};
};


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


func void B_AssessThreat()
{
// other - ГГ, self - НПС цель
// если расстояние между ГГ и целью > макс. дальности действия пассивного восприятия
if(Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT)
{
return;
};
// если цель не видит ГГ
if(!Npc_CanSeeNpc(self,other))
{
return;
};
// если оружие, из которого целится ГГ, не может нанести урон цели
if(!C_NpcIsBotheredByWeapon(self,other))
{
return;
};
// очистка очереди состояний цели
Npc_ClearAIQueue(self);
// очистка восприятий цели
B_ClearPerceptions(self);
// переход цели в состояние реакции на оружие ГГ
AI_StartState(self,ZS_ReactToWeapon,0,"");
return;
};


// ***************************************************************
// Функция реакции НПС, когда ГГ достает оружие
// ---------------------------------------------------------------
// Вызывается как реакция на пассивное восприятие PERC_DRAWWEAPON и в некоторых других функциях
// ---------------------------------------------------------------
// Возвращает FALSE, если НПС не реагирует на оружие ГГ, в противном случае - TRUE.
// ***************************************************************


func int B_AssessDrawWeapon()
{
// other - ГГ, self - НПС
// если ГГ вышел из режима нападения (убрал оружие)
if(Npc_IsInFightMode(other,FMODE_NONE))
{
return FALSE;
};
// если расстояние между ГГ и НПС > дистанции начала диалога
if(Npc_GetDistToNpc(self,other) > PERC_DIST_DIALOG)
{
return FALSE;
};
// если оружие ГГ не может нанести урон НПС
if(!C_NpcIsBotheredByWeapon(self,other))
{
return FALSE;
};
// если НПС уже находится в состоянии реакции на оружие ГГ
if(Npc_IsInState(self,ZS_ReactToWeapon))
{
return FALSE;
};
// если НПС находится в состоянии наблюдения за ГГ и предыдущее состояние НПС было наблюдение за сражением ГГ
if(Npc_IsInState(self,ZS_ObservePlayer)) && (Npc_WasInState(self,ZS_WatchFight))
{
return FALSE;
};
// если НПС не видит ГГ
if(!Npc_CanSeeNpc(self,other))
{
return FALSE;
};
// очистка очереди состояний НПС
Npc_ClearAIQueue(self);
// очистка восприятий НПС
B_ClearPerceptions(self);
// переход НПС в состояние реакции на оружие ГГ
AI_StartState(self,ZS_ReactToWeapon,0,"");
return TRUE;
};


// ************************************************************
// Функция реакции НПС, наблюдающего сражение двух других НПС
// ------------------------------------------------------------
// Вызывается как реакция на пассивное восприятие PERC_ASSESSFIGHTSOUND
// ************************************************************


func void B_AssessFightSound()
{
// self - свидетель, other - нападающий, victim - жертва
// если жертва отсутствует
if(!Hlp_IsValidNpc(victim))
{
return;
};
// если расстояния между (свидетелем и жертвой) и (свидетелем и нападающим) > макс. дальности действия пассивного восприятия
if(Npc_GetDistToNpc(self,victim) > PERC_DIST_INTERMEDIAT) && (Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT)
{
// если (свидетель чужеземец или бандит) и (гильдии жертвы и свидетеля одинаковы или гильдии нападающего и свидетеля одинаковы)
if((self.guild == GIL_OUT) || (self.guild == GIL_BDT)) && ((victim.guild == self.guild) || (other.guild == self.guild))
{
// продолжение анализа
}
else
{
return;
};
};
// если свидетель боится воды
if(self.aivar[AIV_MM_FollowInWater] == FALSE)
{
// если нападающий плывет или ныряет или жертва плывет или ныряет
if(C_BodyStateContains(other,BS_SWIM) || C_BodyStateContains(other,BS_DIVE)
|| C_BodyStateContains(victim,BS_SWIM) || C_BodyStateContains(victim,BS_DIVE))
{
return;
};
};
// если нападающий или жертва являются охранниками крепостных стен
if(other.fight_tactic == FAI_NAILED) || (victim.fight_tactic == FAI_NAILED)
{
return;
};
// если расстояние по высоте между свидетелем и нападающим и свидетелем и жертвой > расстояния реакции по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT) && (Npc_GetHeightToNpc(self,victim) > PERC_DIST_HEIGHT)
{
return;
};
// если расстояние по высоте между свидетелем и нападающим > 5м и свидетель находится не более чем в 30м от "NW_MONASTERY_PLACE_04" (точка перед входом в главное здание монастыря)
if(Npc_GetHeightToNpc(self,other) > 500) && (Npc_GetDistToWP(self,"NW_MONASTERY_PLACE_04") <= 3000)
{
return;
};
// если жертва - наблюдатель или нападающий - наблюдатель (мое примечание: если это условие перенести вторым в теле функции, то общее быстродействие увеличится)
if(Hlp_GetInstanceID(victim) == Hlp_GetInstanceID(self)) || (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(self))
{
return;
};
// если жертва овца и она атакована не "крутым парнем"
if(victim.guild == GIL_SHEEP) && (victim.aivar[AIV_ToughGuy] == FALSE)
{
// если есть причина свидетеля атаковать нападающего на овец
if(C_WantToAttackSheepKiller(self,other))
{
// свидетель атакует нападающего на овец
B_Attack(self,other,AR_SheepKiller,0);
return;
}
else // в противном случае
{
// если свидетель охранник ворот
if(C_NpcIsGateGuard(self))
{
// свидетель запоминает новость, что было нападение на овцу
B_MemorizePlayerCrime(self,other,CRIME_SHEEPKILLER);
return;
};
};
return;
};
// если свидетель охранник ворот
if(C_NpcIsGateGuard(self))
{
return;
};
// если нападающий и жертва монстры
if(other.guild > GIL_SEPERATOR_HUM) && (victim.guild > GIL_SEPERATOR_HUM)
{
return;
};
// если нападающий монстр и свидетель не враг жертве
if(other.guild > GIL_SEPERATOR_HUM) && (Npc_GetAttitude(self,victim) != ATT_HOSTILE)
{
// свидетель атакует монстра
B_Attack(self,other,AR_MonsterVsHuman,0);
return;
};
// если жертва монстр и свидетель не враг нападающему и жертва жива
if(victim.guild > GIL_SEPERATOR_HUM) && (Npc_GetAttitude(self,other) != ATT_HOSTILE) && (!Npc_IsDead(victim))
{
// свидетель атакует жертву (помогает нападающему)
B_Attack(self,victim,AR_MonsterVsHuman,0);
return;
};
// если у свидетеля врагов не было
if(self.aivar[AIV_EnemyOverride] == TRUE)
{
// теперь у свидетеля есть враг
self.aivar[AIV_EnemyOverride] = FALSE;
// свидетелю разрешено воспринимать все объекты в зоне действия восприятия
Npc_PerceiveAll(self);
// поиск свидетелем цели
Npc_GetNextTarget(self);
// если нападающий существует и он не бессознателен
if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other))
{
// свидетель атакует нападающего
B_Attack(self,other,AR_GuildEnemy,0);
return;
};
return;
};
// --------------------------------------------------
// Дальше нападающий и жертва являются только людьми!
// --------------------------------------------------
// если нападающий ГГ является переодетым бандитом или жертва ГГ является переодетым бандитом
if((C_PlayerIsFakeBandit(self,other) == TRUE) || (C_PlayerIsFakeBandit(self,victim) == TRUE))
// и (нападающий бандит или жертва бандит)
&& ((other.guild == GIL_BDT) || (victim.guild == GIL_BDT))
{
// если свидетель бандит
if(self.guild == GIL_BDT)
{
// если свидетель и нападающий являются охранниками Эстебана
if(self.aivar[AIV_STORYBANDIT_ESTEBAN] == TRUE) && (other.aivar[AIV_STORYBANDIT_ESTEBAN] == TRUE)
{
// свидетель атакует жертву
B_Attack(self,victim,AR_NONE,0);
return;
};
// если свидетель и жертва являются охранниками Эстебана
if(self.aivar[AIV_STORYBANDIT_ESTEBAN] == TRUE) && (victim.aivar[AIV_STORYBANDIT_ESTEBAN] == TRUE)
{
// свидетель атакует нападающего
B_Attack(self,other,AR_NONE,0);
return;
};
// если нападающий и жертва не имели причины для сражения
if(other.aivar[AIV_ATTACKREASON] == AR_NONE) && (victim.aivar[AIV_ATTACKREASON] == AR_NONE)
{
// очистка очереди состояний свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения на сражением
AI_StartState(self,ZS_WatchFight,0,"");
return;
};
// если нападающий или жертва являются свободными (с которыми можно сражаться) бандитами
if(other.aivar[AIV_StoryBandit] == TRUE) || (victim.aivar[AIV_StoryBandit] == TRUE)
{
Npc_ClearAIQueue(self);
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения на сражением
AI_StartState(self,ZS_WatchFight,0,"");
return;
};
}
else // иначе (свидетель не бандит)
{
// продолжение анализа
};
};
// если нападающий имел причину для сражения
if((other.aivar[AIV_ATTACKREASON] == AR_GuardStopsIntruder) // охрана ворот атакует незваного гостя
|| (other.aivar[AIV_ATTACKREASON] == AR_MonsterCloseToGate) // охрана ворот атакует враждебного монстра
|| (other.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman) // человек убил человека
|| (other.aivar[AIV_ATTACKREASON] == AR_GuildEnemy) // НПС является врагом гильдии
|| (other.aivar[AIV_ATTACKREASON] == AR_GuardCalledToKill)) // охрана вызвана по факту убийства
// и свидетель друг нападающему
&& (Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardCalledToKill,0);
return;
};
// тоже самое, что и выше, только свидетель помогает жертве
if((victim.aivar[AIV_ATTACKREASON] == AR_GuardStopsIntruder)
|| (victim.aivar[AIV_ATTACKREASON] == AR_MonsterCloseToGate)
|| (victim.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman)
|| (victim.aivar[AIV_ATTACKREASON] == AR_GuildEnemy)
|| (victim.aivar[AIV_ATTACKREASON] == AR_GuardCalledToKill))
&& (Npc_GetAttitude(self,victim) == ATT_FRIENDLY)
{
B_Attack(self,other,AR_GuardCalledToKill,0);
return;
};
// если нападающий имел причину для сражения
if((other.aivar[AIV_ATTACKREASON] == AR_GuardStopsFight) // охрана прекратила атаковать преступника
|| (other.aivar[AIV_ATTACKREASON] == AR_ReactToDamage) // преступник ранил НПС
|| (other.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon)) // преступник не убрал оружие после двукратного предупреждения или пустился в бега
// свидетель друг нападающему
&& (Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
// если нападающий ополченец или охотник на драконов или не принадлежит к гильдиям
if((other.guild == GIL_SLD) || (other.guild == GIL_DJG) || (other.guild == GIL_NONE))
// и если жертва ополченец или охотник на драконов или не принадлежит к гильдиям
&& ((victim.guild == GIL_SLD) || (victim.guild == GIL_DJG) || (victim.guild == GIL_NONE))
{
// продолжение анализа
}
// иначе, если нападающий и жертва не ГГ
else if(!Npc_IsPlayer(other)) && (!Npc_IsPlayer(victim))
{
// продолжение анализа
}
else // иначе
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardStopsFight,0);
return;
};
};
// тоже самое, что и предыдущий if, только свидетель помогает жертве
if((victim.aivar[AIV_ATTACKREASON] == AR_GuardStopsFight)
|| (victim.aivar[AIV_ATTACKREASON] == AR_ReactToDamage)
|| (victim.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon))
&& (Npc_GetAttitude(self,victim) == ATT_FRIENDLY)
{
if((other.guild == GIL_SLD) || (other.guild == GIL_DJG) || (other.guild == GIL_NONE))
&& ((victim.guild == GIL_SLD) || (victim.guild == GIL_DJG) || (victim.guild == GIL_NONE))
{
}
else if(!Npc_IsPlayer(other)) && (!Npc_IsPlayer(victim))
{
}
else
{
// свидетель атакует нападающего
B_Attack(self,other,AR_GuardStopsFight,0);
return;
};
};
// если нападающий не имел причины к нападению или причиной было убийство НПС ГГ
if((other.aivar[AIV_ATTACKREASON] == AR_NONE) || (other.aivar[AIV_ATTACKREASON] == AR_KILL))
// и если жертва не имела причины к нападению или причиной было убийство НПС ГГ
&& ((victim.aivar[AIV_ATTACKREASON] == AR_NONE) || (victim.aivar[AIV_ATTACKREASON] == AR_KILL))
// и свидетель милиция
&& (self.guild == GIL_MIL)
{
// если свидетель друг нападающему и свидетель не друг жертве
if(Npc_GetAttitude(self,other) == ATT_FRIENDLY) && (Npc_GetAttitude(self,victim) != ATT_FRIENDLY)
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardStopsFight,0);
return;
}
// иначе, если свидетель друг жертве и свидетель не друг нападающему
else if(Npc_GetAttitude(self,victim) == ATT_FRIENDLY) && (Npc_GetAttitude(self,other) != ATT_FRIENDLY)
{
// свидетель атакует нападающего
B_Attack(self,other,AR_GuardStopsFight,0);
return;
}
else // иначе (или оба друга или оба не друга)
{
// если нападающий ГГ
if(Npc_IsPlayer(other))
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardStopsFight,0);
return;
}
// иначе, если жертва ГГ
else if(Npc_IsPlayer(victim))
{
// свидетель атакует нападающего
B_Attack(self,other,AR_GuardStopsFight,0);
return;
}
else // иначе
{
// свидетель атакует нападающего
B_Attack(self,other,AR_GuardStopsFight,0);
return;
};
};
};
// ***** помощь нападающему, сражающемуся с вором *****
// если нападающий имел причину для сражения
if((other.aivar[AIV_ATTACKREASON] == AR_UseMob) // использование чужого МОВа
|| (other.aivar[AIV_ATTACKREASON] == AR_Theft) // воровство
|| (other.aivar[AIV_ATTACKREASON] == AR_LeftPortalRoom)) // вход в чужое помещение
// и свидетель друг нападающему
&& (Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
// если у свидетеля есть причина атаковать вора жертву
if(C_WantToAttackThief(self,victim))
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardCalledToThief,0);
};
return;
};
// ***** помощь жертве, сражающейся с вором *****
// аналогично предыдущему if
if((victim.aivar[AIV_ATTACKREASON] == AR_UseMob)
|| (victim.aivar[AIV_ATTACKREASON] == AR_Theft)
|| (victim.aivar[AIV_ATTACKREASON] == AR_LeftPortalRoom))
&& (Npc_GetAttitude(self,victim) == ATT_FRIENDLY)
{
if(C_WantToAttackThief(self,other))
{
B_Attack(self,other,AR_GuardCalledToThief,0);
};
return;
};
// если нападающий имел причину для сражения как защита своего помещения и свидетель друг нападающему
if(other.aivar[AIV_ATTACKREASON] == AR_ClearRoom) && (Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
// свидетель атакует жертву
B_Attack(self,victim,AR_GuardCalledToRoom,0);
return;
};
// аналогично предыдущему, только свидетель помогает жертве
if(victim.aivar[AIV_ATTACKREASON] == AR_ClearRoom) && (Npc_GetAttitude(self,victim) == ATT_FRIENDLY)
{
B_Attack(self,other,AR_GuardCalledToRoom,0);
return;
};
// если расстояния между (свидетелем и жертвой) и (свидетелем и нападающим) > макс. дальности действия пассивного восприятия
if(Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT) && (Npc_GetDistToNpc(self,victim) > PERC_DIST_INTERMEDIAT)
{
return;
};
// если свидетель враг нападающему или жертве
if(Npc_GetAttitude(self,other) == ATT_HOSTILE) || (Npc_GetAttitude(self,victim) == ATT_HOSTILE)
{
// если свидетель бандит
if(self.guild == GIL_BDT)
{
// продолжение анализа
}
else
{
return;
};
};
// если свидетель не видит по прямой жертву
if(!Npc_CanSeeNpcFreeLOS(self,victim))
{
return;
};
// очистка очереди состояний свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения на сражением
AI_StartState(self,ZS_WatchFight,0,"");
return;
};


// *****************************************************************
// Функция реакции НПС на звук шагов ГГ или на звук упавшего предмета
// -----------------------------------------------------------------
// Вызывается в качестве реакции на пассивное восприятие PERC_ASSESSQUIETSOUND
// *****************************************************************


func void B_AssessQuietSound()
{
// other - НПС источник шума (ГГ), self - свидетель
// если источник шума отсутствует
if(!Hlp_IsValidNpc(other))
{
return;
};
// если расстояние по высоте между источником шума и свидетелем > дистанции реагирования по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT)
{
return;
};
// если ГГ находится в доме, принадлежащим любой гильдии, и расстояние по высоте между свидетелем и ГГ > дистанции реакции через закрытые двери
if(Wld_GetPlayerPortalGuild() >= GIL_NONE) && (Npc_GetHeightToNpc(self,other) > PERC_DIST_INDOOR_HEIGHT)
{
return;
};
};
// если есть реакция на вошедшего в помещение
if(B_AssessEnterRoom())
{
return;
};
// если свидетель является охранником ворот
if(C_NpcIsGateGuard(self))
{
return;
};
// если ГГ и свидетель не враги и свидетель не имеет для ГГ важной информации
if(Npc_GetAttitude(self,other) != ATT_HOSTILE) && (Npc_CheckInfo(self,1) == FALSE)
{
return;
};
// если ГГ и свидетель враги
if(Npc_GetAttitude(self,other) == ATT_HOSTILE)
// и (у свидетеля личных врагов не было или (ГГ переодетый бандит и свидетель бандит))
&& ((self.aivar[AIV_EnemyOverride] == TRUE) || (C_PlayerIsFakeBandit(self,other) && (self.guild == GIL_BDT)))
{
return;
};
// если свидетель видит источник звука (моё примечание: возможно здесь ошибка, необходимо поменять условие на противоположное???)
if(Npc_CanSeeSource(self))
{
return;
};
// очистка очереди AI команд свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,1,"");
return;
};


// **************************************************************
// Функция реакции НПС на предупреждение
// ---------------------------------------
// Предупреждение посылается только скриптами (вызов функции Npc_SendPassivePerc), ядром не испоьзуется
// **************************************************************


func void B_AssessWarn()
{
// self - свидетель, other - преступник, victim - жертва
// если свидетель жертва
if(Hlp_GetInstanceID(victim) == Hlp_GetInstanceID(self))
{
return;
};
// если свидетель находится в состоянии реакции на обнаженное оружие или наблюдает за ГГ
if(Npc_IsInState(self,ZS_ReactToWeapon)) || (Npc_IsInState(self,ZS_ObservePlayer))
{
return;
};
// если преступник монстр
if(other.guild > GIL_SEPERATOR_HUM)
{
return;
};
// если свидетель охранник ворот
if(C_NpcIsGateGuard(self))
{
return;
};
// очистка очереди AI команд свидетеля
Npc_ClearAIQueue(self);
// очистка восприятий свидетеля
B_ClearPerceptions(self);
// перевод свидетеля в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,0,"");
return;
};


// ****************************************************
// Функция реакции НПС на важную информацию для разговора
// ----------------------------------------------------
// Вызывается в качестве реакции на пассивное восприятие PERC_ASSESSTALK
// ****************************************************


func void B_AssessTalk()
{
// other - НПС приемник информации (обычно ГГ), self - НПС источник информации

// Тестовый кусок (можно выкинуть из скрипта) [не рассматриваю]
var c_npc PCL;
// Инспектор уровня
PCL = Hlp_GetNpc(PC_Levelinspektor);
var c_npc PCR;
// Рокфеллер
PCR = Hlp_GetNpc(PC_Rockefeller);
// если приемник информации Инспектор уровня или Рокфеллер
if(Hlp_GetInstanceID(other) == Hlp_GetInstanceID(PCL)) || (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(PCR))
{
PrintScreen(ConcatStrings("Stimme: ",IntToString(self.voice)),-1,70,FONT_Screen,2);
PrintScreen("KEIN HERO!",-1,-1,FONT_Screen,2);
PrintScreen(IntToString(self.aivar[AIV_FollowDist]),-1,70,FONT_Screen,2);
if(C_NpcIsInQuarter(self) == Q_KASERNE)
{
PrintScreen("Q_KASERNE",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_GALGEN)
{
PrintScreen("Q_GALGEN",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_MARKT)
{
PrintScreen("Q_MARKT",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_TEMPEL)
{
PrintScreen("Q_TEMPEL",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_UNTERSTADT)
{
PrintScreen("Q_UNTERSTADT",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_HAFEN)
{
PrintScreen("Q_HAFEN",-1,30,FONT_Screen,2);
};
if(C_NpcIsInQuarter(self) == Q_OBERSTADT)
{
PrintScreen("Q_OBERSTADT",-1,30,FONT_Screen,2);
};
return;
};

// Нормальное начала функции
// если источник информации монстр
if(self.guild > GIL_SEPERATOR_HUM)
{
// если монстр не имеет важной информации
if(Npc_CheckInfo(self,1) == FALSE)
{
// если монстру вообще нечего сказать
if(Npc_CheckInfo(self,0) == FALSE)
{
return;
};
};
};
// если источник информации человек
if(self.guild < GIL_SEPERATOR_HUM)
{

// если НПС источник информации враг ГГ
if(B_AssessEnemy())
{
return;
};
// если НПС источник информации знает, что ГГ убийца и у него есть причина атакоывать убийцу
if(B_GetPlayerCrime(self) == CRIME_MURDER) && (C_WantToAttackMurder(self,other))
{
// источник информации атакует ГГ убийцу
B_Attack(self,other,AR_HumanMurderedHuman,0);
return;
};
// если ГГ переодетый бандит и источник информации не бандит
if(C_PlayerIsFakeBandit(self,other) == TRUE) && (self.guild != GIL_BDT)
{
// источник информации атакует ГГ
B_Attack(self,other,AR_GuildEnemy,0);
return;
};
// если ГГ отказался от разговора
if(C_RefuseTalk(self,other))
{
// если ГГ член подставной гильдии
if(C_PlayerHasFakeGuild(self,other)
{
// очистка очереди AI состояний источника информации
Npc_ClearAIQueue(self);
// источник информации переходит в конечное состояние комментирования подставной гильдии
AI_StartState(self,ZS_CommentFakeGuild,1,"");
return;
}
else
{
// источник информации произносит SVM фразу "Оставь меня в покое!"
B_Say(self,other,"$NOTNOW");
return;
};
};
};
// если ГГ еще не говорил с источником информации
if(self.aivar[AIV_NpcStartedTalk] == FALSE)
{
// если источник идет или бежит
if(C_BodyStateContains(self,BS_WALK) || C_BodyStateContains(self,BS_RUN))
{
// ГГ произносит SVM фразу "Подожди!"
B_Say(other,self,"$SC_HEYWAITASECOND");
}
// иначе, если источник информации не видит ГГ
else if(!Npc_CanSeeNpc(self,other))
{
var int rnd;
// генерация случайного числа от 0 до 99
rnd = Hlp_Random(100);
// ГГ призносит фразу
if(rnd <= 25) { B_Say(other,self,"$SC_HEYTURNAROUND"); } // звучит SVM фраза "Эй ты!"
else if (rnd <= 50) { B_Say(other,self,"$SC_HEYTURNAROUND02"); } // звучит SVM фраза "Эй ты!"
else if (rnd <= 75) { B_Say(other,self,"$SC_HEYTURNAROUND03"); } // звучит SVM фраза "Эй!"
else if (rnd <= 99) { B_Say(other,self,"$SC_HEYTURNAROUND04"); }; // звучит SVM фраза "Эй!"
};
};
// очистка очереди AI состояний источника информации
Npc_ClearAIQueue(self);
// очистка восприятий источника информации
B_ClearPerceptions(self);
// если источник информации сидит
if(C_BodyStateContains(self,BS_SIT))
{
// если ГГ заговорил с источником информации
if(self.aivar[AIV_NpcStartedTalk] == TRUE)
{
// ГГ быстро останавливается
AI_StandUpQuick(other);
}
else // иначе
{
// ГГ останавливается
AI_StandUp(other);
};
// если источник информации видит ГГ
if(Npc_CanSeeNpc(self,other))
{
// источник информации переходит в состояние разговора, оставаясь сидеть
AI_StartState(self,ZS_Talk,0,"");
}
else // иначе (не видит ГГ)
{
// если источник информации наблюдал за ГГ
if(Npc_IsInState(self,ZS_ObservePlayer))
{
// источник информации встает
AI_StandUp(self);
};
// источник информации переходит в состояние разговора
AI_StartState(self,ZS_Talk,1,"");
};
return;
}
else // иначе (не сидит)
{
// если ГГ заговорил с источником информации
if(self.aivar[AIV_NpcStartedTalk] == TRUE)
{
// оба быстро останавливаются
AI_StandUpQuick(self);
AI_StandUpQuick(other);
}
else
{
// оба останавливаются
AI_StandUp(self);
AI_StandUp(other);
};
// источник информации переходит в состояние разговора
AI_StartState(self,ZS_Talk,0,"");
return;
};
};


// **************************************
// Функция реакции НПС на перемещение МОВа
// --------------------------------------
// Вызывается ядром системы как реакция на пассивное восприятие PERC_MOVEMOB
// **************************************


func void B_MoveMob()
{
// self - НПС перемещающий МОВ (ГГ)
var string door;
// получить имя перемещаемого МОВа
door = Npc_GetDetectedMob(self);
// если МОВ дверь
if(Hlp_StrCmp(door,"DOOR"))
{
// если дверь закрыта
if(Wld_GetMobState(self,door) == 0)
{
// очистка очереди AI состояний ГГ
Npc_ClearAIQueue (self);
// ГГ открывает дверь
AI_UseMob(self,door,1);
// зафиксировать состояние двери
AI_UseMob(self,door,-1);
};
}
else // иначе
{
return;
};
// ГГ продолжает свои дела
AI_ContinueRoutine(self);
};
Конец 5 параграфа.
Вот и все основные восприятия, на которые реагируют люди, есть еще дополнительные восприятия, которые инициализируются в функциях состояний, их мы рассмотрим позже.
Все файлы активных и пассивных восприятий людей находятся в директории ..\AI\Human\B_Human\ и имеют имена эквивалентные функциям восприятий. Файл восприятия магии находится в директории ..\AI\Magic\
Примечание: Файл ..\AI\Human\B_Human\B_AssessObserveSuspect.d можно удалить из скриптов, по причине его абсолютной бесполезности.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
6. Функции обработки восприятий монстров.
// **************************************************
// Функция реакции монстров на врага.
// --------------------------------------------------
// Вызывается ядром системы в качестве реакции на активное восприятие PERC_ASSESSENEMY.
// **************************************************


func void B_MM_AssessEnemy()
{
// self - НПС монстр, other - враг
// если монстр дракон и ГГ имеет "Заряженный глаз Инноса"
if(self.guild == GIL_DRAGON) && (Npc_HasItems(hero,ItMi_InnosEye_Mis) >= 1)
{
return;
};
// если монстр или враг не могут атаковать
if((self.aivar[AIV_NoFightParker] == TRUE) || (other.aivar[AIV_NoFightParker] == TRUE))
{
return;
};
// если личных врагов у монстра нет и враг человек
if(self.aivar[AIV_EnemyOverride] == TRUE) && (other.guild < GIL_SEPERATOR_HUM)
{
return;
};
// ------- TESTMODE: Levelinspektor wird ignoriert ------
var c_npc PCL;
// "Инспектор уровня"
PCL = Hlp_GetNpc(PC_Levelinspektor);
// если враг "Инспектор уровня"
if(Hlp_GetInstanceID(other) == Hlp_GetInstanceID(PCL))
{
return;
};
var c_npc MGO;
// Магический голем
MGO = Hlp_GetNpc(MagicGolem);
var c_npc LAR;
// Ларес
LAR = Hlp_GetNpc(VLK_449_Lares);
// если враг Ларес и монстр Магический голем
if(Hlp_GetInstanceID(other) == Hlp_GetInstanceID(LAR)) && (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(MGO))
{
return;
};
// если монстр находится не далее 5м от точки "OC_RAMP_07"
if(Npc_GetDistToWP(self,"OC_RAMP_07") <= 500)
{
return;
};
// если враг находится в режиме диалога
if(other.aivar[AIV_INVINCIBLE] == TRUE)
{
return;
};
// если враг (плывет или ныряет) и монстр не полезет в воду
if(C_BodyStateContains(other,BS_SWIM) || C_BodyStateContains(other,BS_DIVE)) && (self.aivar[AIV_MM_FollowInWater] == FALSE)
{
return;
};
// если расстояние по высоте между монстром и врагом > расстояния реакции по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT)
{
return;
};
// если ГГ враг и он превращен в монстра
if(Npc_IsPlayer(other)) && (other.guild > GIL_SEPERATOR_HUM)
{
// если гильдии монстра и превращенного ГГ не враждебны
if(Wld_GetGuildAttitude(self.guild,other.guild) != ATT_HOSTILE)
{
return;
};
};
// если дальность обоняния монстра > макс. дальности действия активного восприятия монстров
if(self.senses_range > PERC_DIST_MONSTER_ACTIVE_MAX)
{
// если расстояние между монстром и врагом > макс. дальности действия активного восприятия монстров
if(Npc_GetDistToNpc(self,other) > PERC_DIST_MONSTER_ACTIVE_MAX)
{
// если монстр не видит врага
if(!Npc_CanSeeNpc(self,other))
{
return;
};
};
};
// если монстр орк или дружественный орк
if(self.guild == GIL_ORC) || (self.guild == GIL_FRIENDLY_ORC)
{
// если враг подкрадавается или стоит
if(C_BodyStateContains(other,BS_SNEAK)) || (C_BodyStateContains(other,BS_STAND))
{
// если монстр не видит врага
if(!Npc_CanSeeNpc(self,other))
{
return;
};
};
};
// если монстр не видит врага по прямой (например, враг за стеной)
if(!Npc_CanSeeNpcFreeLOS(self,other))
{
return;
};
// если монстр является членом партии (вызванный)
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
// если враг монстра является другом НПС
if(other.npctype == NPCTYPE_FRIEND)
{
return;
};
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
// монстр выбирает цель
Npc_SetTarget(self,other);
// очистка восприятий монстра
B_ClearPerceptions(self);
// переход монстра в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
// если монстр не угрожает перед атакой (атакует сразу)
if(self.aivar[AIV_MM_ThreatenBeforeAttack] == FALSE)
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
B_ClearPerceptions(self);
// переход монстра в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
// если монстр находится в состоянии "пожирания падали"
if(Npc_IsInState(self,ZS_MM_EatBody))
{
// если расстояние между монстром и врагом <= дистанции атаки монстров
if(Npc_GetDistToNpc(self,other) <= FIGHT_DIST_MONSTER_ATTACKRANGE)
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
B_ClearPerceptions(self);
// переход монстра в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
return;
};
// если монстр находится в соостоянии охоты
if(Npc_IsInState(self,ZS_MM_Hunt))
{
// если расстояние между монстром и врагом <= дистанции атаки монстров
if(Npc_GetDistToNpc(self,other) <= FIGHT_DIST_MONSTER_ATTACKRANGE)
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
B_ClearPerceptions(self);
// переход монстра в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return;
}
else
{
return;
};
};
// если монстра устраивает добыча в виде врага
if(C_PredatorFoundPrey(self,other))
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
B_ClearPerceptions(self);
// переход монстра в состояние охоты на врага
AI_StartState(self,ZS_MM_Hunt,0,"");
return;
};
// если врага устраивает добыча в виде монстра
if(C_PredatorFoundPrey(other,self))
{
// если враг находится в соостоянии охоты и если расстояние между монстром и врагом <= дистанции преследования
if(!Npc_IsInState(other,ZS_MM_Hunt)) && (Npc_GetDistToNpc(self,other) <= FIGHT_DIST_MONSTER_FLEE)
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
B_ClearPerceptions(self);
// переход монстра в состояние преследования
AI_StartState(self,ZS_MM_Flee,0,"");
return;
}
else
{
return;
};
};
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
// очистка восприятий монстра
B_ClearPerceptions(self);
// переход монстра в состояние угрозы
AI_StartState(self,ZS_MM_ThreatenEnemy,0,"");
return;
};


// ******************************************
// Функция реакции монстров на мертвое тело
// ------------------------------------------
// Вызывается ядром системы в качестве реакции на пассивное восприятие PERC_ASSESSBODY
// ******************************************


func void B_MM_AssessBody()
{
// self - монстр, other - труп
// если монстр принадлежит к оркам
if(self.guild > GIL_SEPERATOR_ORC)
{
return;
};
// если расстояние по высоте между монстром и трупом > расстояния реакции по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT)
{
return;
};
// если приоритетом монстра является нападение
if(self.aivar[AIV_MM_PRIORITY] == PRIO_ATTACK)
{
return;
};
// если труп не нравится монстру
if(!C_WantToEat(self,other))
{
return;
};
// если монстр находится в состоянии атаки
if(Npc_IsInState(self,ZS_MM_Attack))
{
var c_npc stoerenfried;
// последний атакованный НПС
stoerenfried = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
// если расстояние между атакованным НПС и трупом <= дистанции атаки монстров
if(Npc_GetDistToNpc(stoerenfried,other) <= FIGHT_DIST_MONSTER_ATTACKRANGE)
{
return;
};
};
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
// очистка восприятий монстра
B_ClearPerceptions(self);
// переход в состояние пожирания трупа
AI_StartState(self,ZS_MM_EatBody,0,"");
return;
};


// ********************************************************
// Функция реакции монстра на повреждение
// --------------------------------------------------------
// Вызывается ядром системы в качестве реакции на пассивное восприятие PERC_ASSESSDAMAGE
// ********************************************************


func void B_MM_AssessDamage()
{
// self - монстр жертва, other - НПС агрессор
// установить монстру приоритет на атаку
self.aivar[AIV_MM_PRIORITY] = PRIO_ATTACK;
// вызов функции реакции на повреждение "Когтем Белиара"
B_BeliarsWeaponSpecialDamage(other,self);
// если агрессор имеет "Святой молот"
if(Npc_HasItems(other,Holy_Hammer_MIS) > 0)
{
var c_npc MagGol;
// Магический голем
MagGol = Hlp_GetNpc(MagicGolem);
// проинициализировать глобальную переменную item "Святым молотом"
Npc_GetInvItem(other,Holy_Hammer_MIS);
var c_item OthWeap;
// оружие, которое агрессор держит в руке
OthWeap = Npc_GetReadiedWeapon(other);
// если жертва Магический голем и оружие у агрессора в руке "Святой молот"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(MagGol)) && (Hlp_GetInstanceID(OthWeap) == Hlp_GetInstanceID(item))
{
// Жизнь Магического голема -= 1000 LP
Npc_ChangeAttribute(self,ATR_HITPOINTS,-1000);
return;
};
};
// если жертва Каменный сторож и у него нет врагов
if(self.guild == GIL_STONEGUARDIAN) && (self.aivar[AIV_EnemyOverride] == TRUE)
{
// пробуждение Каменного сторожа
B_AWAKE_STONEGUARDIAN(self);
};
// если агрессора устраивает добыча в виде жертвы
if(C_PredatorFoundPrey(other,self))
{
// очистка очереди AI состояний жертвы
Npc_ClearAIQueue(self);
// установка цели для жертвы
Npc_SetTarget(self,other);
// очистка восприятий жертвы
B_ClearPerceptions(self);
// жертва убегает от агрессора
AI_StartState(self,ZS_MM_Flee,0,"");
return;
};
// если жертва находится в состоянии атаки
if(Npc_IsInState(self,ZS_MM_Attack))
{
// если агрессор ГГ и жертва член партии
if(Npc_IsPlayer(other)) && (self.aivar[AIV_PARTYMEMBER] == TRUE)
{
return;
};
// если жертва скелет и агрессор маг скелетов
if(self.aivar[AIV_MM_REAL_ID] == ID_SKELETON) && (other.aivar[AIV_MM_REAL_ID] == ID_SKELETON_MAGE)
{
return;
};
// если агрессор не является НПС, атакованным жертвой
if(Hlp_GetInstanceID(other) != self.aivar[AIV_LASTTARGET])
{
// если удар жертве нанесен агрессором не первый раз
if(self.aivar[AIV_HitByOtherNpc] == Hlp_GetInstanceID(other))
{
// смена цели (жертва будет атаковать агрессора)
Npc_SetTarget(self,other);
}
else
{
// при первом ударе жертве записывается ID агрессора
self.aivar[AIV_HitByOtherNpc] = Hlp_GetInstanceID(other);
};
};
return;
};
// очистка очереди AI состояний жертвы
Npc_ClearAIQueue(self);
// установка цели для жертвы
Npc_SetTarget(self,other);
// очистка восприятий жертвы
B_ClearPerceptions(self);
// жертва атакует агрессора
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};


// ****************************************************************
// Функция реакции монстра на убийство и на повреждение других НПС
// ----------------------------------------------------------------
// Вызывается в качестве реакции на пассивные восприятия PERC_ASSESSOTHERSDAMAGE и PERC_ASSESSMURDER
// ****************************************************************


func void B_MM_AssessOthersDamage()
{
// self - монстр наблюдатель, other - агрессор, victim - жертва (труп)
// если расстояния между (наблюдателем и жертвой) и (наблюдателем и агрессором) > макс. дальности действия восприятия
if(Npc_GetDistToNpc(self,victim) > PERC_DIST_INTERMEDIAT) && (Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT)
{
return;
};
// если наблюдатель не видит жертву
if(!Npc_CanSeeNpcFreeLOS(self,victim))
{
return;
};
// если наблюдатель член партии
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
// если жертва ГГ
if(Npc_IsPlayer(victim))
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
// очистка восприятий наблюдателя
B_ClearPerceptions(self);
// установка в качестве цели агрессора
Npc_SetTarget(self,other);
// монстр наблюдатель атакует агрессора
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
// если агрессор ГГ и жертва жива
if(Npc_IsPlayer(other)) && (!Npc_IsDead(victim))
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
// очистка восприятий наблюдателя
B_ClearPerceptions(self);
// установка в качестве цели жертвы
Npc_SetTarget(self,victim);
// монстр наблюдатель атакует жертву
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
};
// если наблюдатель волк
if(self.guild == GIL_WOLF)
{
// если жертва волк и агрессор волк и волк агрессор есть ГГ и жертва убита
if(victim.guild == GIL_WOLF) && (other.guild == GIL_WOLF) && Npc_IsPlayer(other) && Npc_IsDead(victim)
{
Npc_ClearAIQueue(self);
B_ClearPerceptions(self);
// перевод наблюдателя в состояние вызванного монстра
self.start_aistate = ZS_MM_Rtn_Summoned;
AI_StartState(self,ZS_MM_Rtn_Summoned,0,"");
return;
};
};
// если наблюдатель каменный страж и жертва каменный страж и у наблюдателя нет врагов
if(self.guild == GIL_STONEGUARDIAN) && (victim.guild == GIL_STONEGUARDIAN) && (self.aivar[AIV_EnemyOverride] == TRUE)
{
// пробуждение каменного стража наблюдателя
B_AWAKE_STONEGUARDIAN(self);
};
// если гильдии наблюдателя и жертвы дружественны и гильдии наблюдателя и агрессора не дружественные
if(Wld_GetGuildAttitude(self.guild,victim.guild) == ATT_FRIENDLY) && (Wld_GetGuildAttitude(self.guild,other.guild) != ATT_FRIENDLY)
{
Npc_ClearAIQueue(self);
B_ClearPerceptions(self);
Npc_SetTarget(self,other);
// наблюдатель атакует агрессора
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
// если гильдии наблюдателя и агрессора дружественны и гильдии наблюдателя и жертвы не дружественные
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_FRIENDLY) && (Wld_GetGuildAttitude(self.guild,victim.guild) != ATT_FRIENDLY)
// и жертва не мертва
&& (!Npc_IsDead(victim))
{
Npc_ClearAIQueue(self);
B_ClearPerceptions(self);
Npc_SetTarget(self,victim);
// наблюдатель атакует жертву
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
};


// ******************************************************
// Функция реакции монстров на предупреждение
// ------------------------------------------------------
// Предупреждение посылается только скриптами (вызов функции Npc_SendPassivePerc), ядром не испоьзуется
// ******************************************************


func void B_MM_AssessWarn()
{
// self - наблюдатель, other - агрессор, victim - жертва
// если наблюдатель орк
if(self.guild > GIL_SEPERATOR_ORC)
{
// если наблюдатель находится в состоянии атаки
if(Npc_IsInState(self,ZS_MM_Attack))
{
return;
};
// если гильдия наблюдателя дружественна гильдии агрессора
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_FRIENDLY)
{
// очистка очереди AI команд наблюдателя
Npc_ClearAIQueue(self);
// установка жертвы в качестве цели наблюдателю
Npc_SetTarget(self,victim);
// очистка восприятий наблюдателя
B_ClearPerceptions(self);
// наблюдатель атакует жертву
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
return;
};
// если агрессор человек
if(other.guild < GIL_SEPERATOR_HUM)
{
return;
};
// если расстояние по высоте между наблюдателем и агрессором > дистанции реагирования по высоте
if(Npc_GetHeightToNpc(self,other) > PERC_DIST_HEIGHT)
{
return;
};
// если наблюдатель находится в состоянии атаки
if(Npc_IsInState(self,ZS_MM_Attack))
{
// если наблюдателя устраивает добыча в виде агрессора и приоритет наблюдателя "пожирание падали"
if(C_PredatorFoundPrey(self,other)) && (self.aivar[AIV_MM_PRIORITY] == PRIO_EAT)
{
// очистка очереди AI команд наблюдателя
Npc_ClearAIQueue(self);
// установка агрессора в качестве цели наблюдателю
Npc_SetTarget(self,other);
}
else // иначе цель не меняется
{
// возврат цели для наблюдателя (последняя бывшая цель)
other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
};
return;
};
// если гильдии наблюдателя и агрессора одинаковы и наблюдатель охотится стаей
if(self.guild == other.guild) && (self.aivar[AIV_MM_Packhunter] == TRUE)
{
// если наблюдатель волк и жертва волк и жертва ГГ (превращенный в волка)
if(self.guild == GIL_WOLF) && (victim.guild == GIL_WOLF) && Npc_IsPlayer(victim)
{
return;
};
// если агрессор находится в состоянии атаки
if(Npc_IsInState(other,ZS_MM_Attack))
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,victim);
B_ClearPerceptions(self);
// наблюдатель атакует жертву
AI_StartState(self,ZS_MM_Attack,0,"");
return;
};
// если агрессор находится в состоянии угрозы врагу
if(Npc_IsInState(other,ZS_MM_ThreatenEnemy))
{
// агрессор бежит
AI_SetWalkmode(self,NPC_RUN);
// к жертве
AI_GotoNpc(self,victim);
return;
};
};
return;
};


// ********************************************************
// Функция реакции монстров на ГГ
// --------------------------------------------------------
// Вызывается ядром системы в качестве реакции на активное восприятие PERC_ASSESSPLAYER
// Используется только конкретными монстрами
// ********************************************************


func void B_MM_AssessPlayer()
{
// other - ГГ, self - монстр
// если ГГ в состоянии диалога
if(other.aivar[AIV_INVINCIBLE] == TRUE)
{
return;
};
// если ГГ мертв, без сознания и т.д. (обездвижен)
if(C_NpcIsDown(other))
{
return;
};
// подготовка разговора ГГ с драконами
B_AssignDragonTalk(self);
// если расстояние между ГГ и монстром < 7м и монстр имеет важную информацию
if(Npc_GetDistToNpc(self,other) <= 700) && (Npc_CheckInfo(self,1))
{
// если монстр дракон или (монстр не дракон и расстояние между монстром и ГГ <= дистанции начала диалога)
if(self.guild == GIL_DRAGON) || ((self.guild != GIL_DRAGON) && (Npc_GetDistToNpc(self,other) <= PERC_DIST_DIALOG))
{
// если ГГ не падает и не плывет и не ныряет
if(!C_BodyStateContains(other,BS_FALL)) && (!C_BodyStateContains(other,BS_SWIM)) && (!C_BodyStateContains(other,BS_DIVE))
{
// у монстра устанавливается флаг начала разговора
self.aivar[AIV_NpcStartedTalk] = TRUE;
// реакция ГГ на предлагаемый разговор
B_AssessTalk();
return;
};
};
};
// если монстр член партии ГГ
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
// если расстояние между ГГ и монстром < 5м и монстр не стоит
if(Npc_GetDistToNpc(self,hero) < 500) && (!C_BodyStateContains(self,BS_STAND))
{
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
// монстр останавливается
AI_StandUp(self);
// и поворачивается к ГГ
AI_TurnToNpc(self,hero);
};
};
};
Все файлы активных и пассивных восприятий монстров находятся в директории ..\AI\Monster\B_Monster\ и имеют имена, эквивалентные функциям восприятий.
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
7. Описание обработчиков состояний НПС.

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

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
8. Функции состояний людей.

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


// Функция обработки вспомогательного восприятия PERC_ASSESSSURPRISE
// Вызывается ядром системы когда ГГ превращается в человека из животного

func void B_AssessSurprise()
{
// self - наблюдатель, other - ГГ
// целью наблюдателя становится ГГ
Npc_SetTarget(self,other);
// причина нападения наблюдателя на ГГ - ГГ враг гильдии
self.aivar[AIV_ATTACKREASON] = AR_GuildEnemy;
};

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

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

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


// *******************************************************
// Состояние защиты своего помещения
// *******************************************************
// Здесь: self - НПС хозяин помещения, other - "незванный гость" (ГГ)
// *******************************************************


// Функция обработки восприятия разговора (вызывается когда ГГ обращается к НПС хозяину)
func void B_ClearRoomTalk()
{
// если НПС хочет напасть на "гостя"
if(C_WantToAttackRoomIntruder(self))
{
// НПС предупреждает "гостя" (SVM фраза "Пошел вон!")
B_Say(self,other,"$GETOUTOFHERE");
}
else
{
// НПС спрашивает "гостя" (SVM фраза "Что ты тут ищешь!?")
B_Say(self,other,"$WHYAREYOUINHERE");
};
};

// Функция обработки восприятия выхода ГГ из помещения
// Возвращает TRUE если ГГ покинул помещение, иначе - FALSE

func int B_ExitIfRoomLeft()
{
var int portalguild;
// получить номер гильдии, которой принадлежит помещение (-1 помещение никому не принадлежит)
portalguild = Wld_GetPlayerPortalGuild();
// если ГГ покинул помещение или помещение публичное
if(!C_NpcIsBotheredByPlayerRoomGuild(self)) || (portalguild == GIL_PUBLIC)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// НПС перестает смотреть на ГГ
B_StopLookAt(self);
// если НПС хочет напасть на "гостя"
if(C_WantToAttackRoomIntruder(self))
{
// НПС говорит "гостю" (SVM фраза "Да, иди прочь!")
B_Say(self,other,"$YESGOOUTOFHERE");
}
else
{
// НПС говорит "гостю" (SVM фраза "Умный малый!")
B_Say(self,other,"$WISEMOVE");
};
// НПС продолжает выполнение распорядка дня
AI_ContinueRoutine(self);
return TRUE;
};
return FALSE;
};

// Инициализация состояния защиты помещения
func void ZS_ClearRoom()
{
// установить минимальный набор восприятий НПС
Perception_Set_Minimal();
// заменить восприятие входа в помещение на восприятие выхода "гостя" из помещения
Npc_PercEnable(self,PERC_ASSESSENTERROOM,B_ExitIfRoomLeft);
// включить восприятие на перемещение МОВа
Npc_PercEnable(self,PERC_MOVEMOB,B_MoveMob);
// заменить восприятие разговора НПС
Npc_PercEnable(self,PERC_ASSESSTALK,B_ClearRoomTalk);
// НПС встает
AI_StandUp(self);
// НПС смотрит на "гостя"
B_LookAtNpc(self,other);
// НПС бежит к "гостю"
AI_SetWalkmode(self,NPC_RUN);
// если НПС находится вне помещения
if(!Npc_IsInPlayersRoom(self))
{
// НПС бежит в точку, ближайшую к ГГ
AI_GotoWP(self,Npc_GetNearestWP(other));
};
// установка признака входа в цикл
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Функция цикла защиты помещения
func int ZS_ClearRoom_Loop()
{
// если осуществен первый вход в цикл
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// НПС поворачивается к "гостю"
B_TurnToNpc(self,other);
// если НПС хочет напасть на "гостя"
if(C_WantToAttackRoomIntruder(self))
{
// НПС выбирает соответствующее "гостю" оружие
B_SelectWeapon(self,other);
// НПС предупреждает "гостя" (SVM фраза "Пошел вон!")
B_Say(self,other,"$GETOUTOFHERE");
}
else
{
// если НПС не является другом "гостя"
if(Npc_GetAttitude(other,self) != ATT_FRIENDLY)
{
// НПС спрашивает "гостя" (SVM фраза "Что ты тут ищешь!?")
B_Say(self,other,"$WHYAREYOUINHERE");
};
};
// сброс времени нахождения НПС в этом состоянии
Npc_SetStateTime(self, 0);
// закрытие первого входа в цикл
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// если ГГ покинул помещение
if(B_ExitIfRoomLeft())
{
return LOOP_END;
};
// если НПС хочет напасть на "гостя"
if(C_WantToAttackRoomIntruder(self))
{
// если с момента входа в помещение прошло > 5 сек
if(Npc_GetStateTime(self) > 5)
{
// НПС атакует "гостя"
B_Attack(self,other,AR_ClearRoom,0);
return LOOP_END;
};
}
else // НПС не хочет нападать (повторяется каждые две секунды)
{
// если с момента входа в помещение прошло >= 2 сек
if(Npc_GetStateTime(self) >= 2)
{
// если НПС не видит "гостя" по прямой
if(!Npc_CanSeeNpcFreeLOS(self,other))
{
// НПС бежит в точку, ближайшую к ГГ
AI_GotoWP(self,Npc_GetNearestWP(other));
// НПС поворачивается к "гостю"
B_TurnToNpc(self,other);
}
// иначе, если НПС вообще не видит "гостя"
else if(!Npc_CanSeeNpc(self,other))
{
// НПС поворачивается в направлении "гостя"
B_TurnToNpc(self,other);
};
// сброс времени состояния
Npc_SetStateTime(self,0);
};
};
return LOOP_CONTINUE;
};

// Функция выхода из состояния защиты помещения
func void ZS_ClearRoom_End()
{
// НПС перестает смотреть на "гостя"
B_StopLookAt (self);
};


// ****************************************************
// Обработчик состояния когда НПС убегает от агрессора
// ----------------------------------------------------
// self - убегающий НПС, other - агрессор
// ****************************************************


// Функция инициализации состояния
func void ZS_Flee()
{
// разрешить восприятие примененной магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// получить other - агрессор
B_ValidateOther();
// если загрузки игры не было
if(self.aivar[AIV_LOADGAME] == FALSE)
{
// НПС кричит агрессору (SVM фраза "Я сматываюсь!")
B_Say_Overlay(self,other,"$RUNAWAY");
};
// НПС прячет оружие
AI_RemoveWeapon(self);
// НПС переходит на бег
AI_SetWalkmode(self,NPC_RUN);
// проигрывается анимация убегающего человека
Mdl_ApplyOverlayMds(self,"HUMANS_FLEE.MDS");
};

// Цикл состояния убегания
func int ZS_Flee_Loop()
{
// получить для НПС цель (инициализировать other агрессором)
Npc_GetTarget(self);
// если расстояние между НПС и агрессором > дистанции преследования
if(Npc_GetDistToNpc(self,other) > FIGHT_DIST_CANCEL)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
return LOOP_END;
};
// если агрессор обездвижен (мертв, без сознания и т.д.)
if(C_NpcIsDown(other))
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
return LOOP_END;
};
// НПС продолжает убегать
AI_Flee(self);
return LOOP_CONTINUE;
};

// Функция завершения состояния убегания
func void ZS_Flee_End()
{
// прекратить проигрывание анимации убегающего человека
Mdl_RemoveOverlayMDS(self,"HUMANS_FLEE.MDS");
// НПС останавливается
AI_StandUp(self);
// вызов функции завершения состояния лечения НПС
AI_StartState(self,ZS_HealSelf,1,"");
return;
};


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


// Инициализация состояния
func void ZS_HealSelf()
{
// разрешить НПС минимальный набор восприятий
Perception_Set_Minimal();
};

// Цикл состояния
func int ZS_HealSelf_Loop()
{
// если текущая жизнь НПС равняется максимальной
if(self.attribute[ATR_HITPOINTS] == self.attribute[ATR_HITPOINTS_MAX])
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
return LOOP_END;
};
// если НПС имеет "Лечебный эликсир"
if(Npc_HasItems(self,ItPo_Health_03) > 0)
{
// НПС пьет "Лечебный эликсир"
AI_UseItem(self,ItPo_Health_03);
return LOOP_CONTINUE;
}
// если НПС имеет "Лечебный экстракт"
else if(Npc_HasItems(self,ItPo_Health_02) > 0)
{
// НПС пьет "Лечебный экстракт"
AI_UseItem(self,ItPo_Health_02);
return LOOP_CONTINUE;
}
// если НРС имеет "Лечебную эссенцию"
else if(Npc_HasItems(self,ItPo_Health_01) > 0)
{
// НПС пьет "Лечебную эссенцию"
AI_UseItem(self,ItPo_Health_01);
return LOOP_CONTINUE;
}
else //иначе
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
return LOOP_END;
};
};

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


// *******************************************
// Обработчик состояния наблюдения НПС за ГГ
// -------------------------------------------
// self - наблюдающий НПС, other - ГГ
// *******************************************


// Инициализация наблюдения
func void ZS_ObservePlayer()
{
// установить НПС нормальный набор восприятий
Perception_Set_Normal();
// если НПС не сидит
if(!C_BodystateContains(self,BS_SIT))
{
// НПС останавливается
AI_StandUp(self);
// НПС смотрит на ГГ
B_LookAtNpc(self,other);
// НПС поворачивается к ГГ
B_TurnToNpc(self,other);
}
else // иначе (если НПС сидит)
{
// НПС смотрит на ГГ
B_LookAtNpc(self,other);
};
// если в предудущем состоянии НПС спал
if(Npc_WasInState(self,ZS_Sleep))
{
// НПС спрашивает ГГ (SVM фраза "Что случилось?")
B_Say(self,other,"$YOUDISTURBEDMYSLUMBER");
};
// если НПС наблюдает за своим помещением и other есть ГГ
if(self.aivar[AIV_SeenLeftRoom] == TRUE) && (Npc_IsPlayer(other))
{
// сброс наблюдения за своим помещением
self.aivar[AIV_SeenLeftRoom] = FALSE;
// если комментария входа в чужое помещение не было
if(Player_LeftRoomComment == FALSE)
{
// НПС говорит ГГ (SVM фраза "Чего ты там ищешь?")
B_Say(self,other,"$WHATDIDYOUDOINTHERE");
// установка флага состоявшегося комментария
Player_LeftRoomComment = TRUE;
};
};
// установить время нахождения НПС в этом состоянии (1 или 2 сек)
self.aivar[AIV_StateTime] = (Hlp_Random(2) + 1);
};

// Цикл состояния наблюдения
func int ZS_ObservePlayer_Loop ()
{
// если ГГ крадется и комментария подкрадывания не было
if(C_BodyStateContains(other,BS_SNEAK)) && (Player_SneakerComment == FALSE)
{
// установка флага состоявшегося комментария
Player_SneakerComment = TRUE;
// НПС показывает на ГГ
AI_PointAtNpc(self,other);
// НПС говорит ГГ (SVM фраза "Эй, ты! Что ты там шастаешь?")
B_Say(self,other,"$WHATSTHISSUPPOSEDTOBE");
// НПС перестает указывать на ГГ
AI_StopPointAt(self);
// НПС посылает ГГ предупреждение
Npc_SendPassivePerc(self,PERC_ASSESSWARN,self,other);
};
// если время нахождения в состоянии > 1 или 2 сек
if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime])
{
// если НПС не сидит
if(!C_BodystateContains(self,BS_SIT))
{
// НПС поворачивается к ГГ
B_TurnToNpc(self,other);
};
// установить время нахождения НПС в этом состоянии (1 или 2 сек)
self.aivar[AIV_StateTime] = (Hlp_Random(2) + 1);
// сброс времени состояния
Npc_SetStateTime(self,0);
};
// если расстояние между НПС и ГГ > дальности действия восприятия
if(Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT)
{
// очистка очереди состояний НПС
Npc_ClearAIQueue(self);
return LOOP_END;
}
else // [Прим. else здесь лишнее, можно просто: return LOOP_CONTINUE;]
{
return LOOP_CONTINUE;
};
};

// Выход из состояния наблюдения
func void ZS_ObservePlayer_End ()
{
// НПС перестает смотреть на ГГ
B_StopLookAt(self);
};


// *****************************************
// Обработчик состояния грабежа предметов с тел НПС
// -----------------------------------------
// self - грабитель, other - тело
// *****************************************


// Инициализация состояния
func void ZS_RansackBody()
{
// установить грабителю нормальный набор восприятий
Perception_Set_Normal();
// грабитель встает
AI_StandUp(self);
// грабитель идет к телу
AI_GotoNpc(self,other);
};

// Цикл грабежа
func int ZS_RansackBody_Loop()
{
return LOOP_END;
};

// Завершающая фаза грабежа
func void ZS_RansackBody_End()
{
// грабитель поворачивается к телу
B_TurnToNpc(self,other);

// включить анимацию грабежа
AI_PlayAni(self,"T_PLUNDER");
// если тело имеет "Святой молот" и грабитель "Гарвиг"
if(Npc_HasItems(other,Holy_Hammer_MIS) > 0) && (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Garwig))
{
// создать в инвентаре грабителя "Святой молот"
CreateInvItems(self,Holy_Hammer_MIS,1);
// удалить из инвентаря тела "Святой молот"
Npc_RemoveInvItems(other,Holy_Hammer_MIS,1);
};
// если тело имеет "Меч Рода" и грабитель "Род"
if(Npc_HasItems(other,ItMw_2h_Rod) > 0) && (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Rod))
{
// переместить "Меч Рода" из инвентаря тела в инвентарь грабителя
CreateInvItems(self,ItMw_2h_Rod,1);
Npc_RemoveInvItems(other,ItMw_2h_Rod,1);
// грабитель экипируется лучшим оружием ближнего радиуса поражения
AI_EquipBestMeleeWeapon(self);
};
// если тело имеет "Ключ к хибаре капитана Грега" и грабитель "Фрэнсис"
if(Npc_HasItems(other,ITKE_Greg_ADDON_MIS)) && (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Francis))
{
// передать предмет грабителю
CreateInvItems(self,ITKE_Greg_ADDON_MIS,1);
Npc_RemoveInvItems(other,ITKE_Greg_ADDON_MIS,1);
};
// если тело имеет "Золото"
if(Npc_HasItems(other,ItMi_Gold) > 0)
{
var int x;
// кол-во золота у тела
x = Npc_HasItems(other,ItMi_Gold);
// передать все золдото грабителю
CreateInvItems(self,ItMi_Gold,x);
Npc_RemoveInvItems(other,ItMi_Gold,x);
// грабитель говорит телу (SVM фраза "Спасибо за золото, герой!")
B_Say(self,other,"$ITOOKYOURGOLD");
}
else // иначе
{
// грабитель говорит телу (SVM фраза "Ты, жалкое ничтожество, разве у тебя нет золота!")
B_Say(self,other,"$SHITNOGOLD");
};
// грабителю разрешается воспринимать все объекты в зоне действия восприятий
Npc_PerceiveAll(self);
// если грабитель находит оружие ближнего или дальнего радиуса поражения
if(Wld_DetectItem(self,ITEM_KAT_NF) || Wld_DetectItem(self,ITEM_KAT_FF))
{
// если ссылка на предмет item существует
if(Hlp_IsValidItem(item))
{
// если расстояние от грабителя до предмета < 5 метров
if(Npc_GetDistToItem(self,item) < 500)
{
// грабитель берет предмет
AI_TakeItem(self,item);
// грабитель говорит сам себе (SVM фраза "Твое оружие я возьму с собой.")
B_Say(self,self,"$ITAKEYOURWEAPON");
// экипировка лучшим оружием
AI_EquipBestMeleeWeapon(self);
AI_EquipBestRangedWeapon(self);
};
};
};
// если жизнь грабителя < половинной
if(self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
{
// переход в состояние самолечения
AI_StartState(self,ZS_HealSelf,0,"");
return;
};
};


// ***********************************************
// Обработчик состояния когда Джек забирает сырое мясо у жертвы
// -----------------------------------------------
// self - НПС Джек, other - тело
// ***********************************************


// Инициализация состояния
func void ZS_GetMeat()
{
// разрешить минимальный набор восприятий
Perception_Set_Minimal();
// НПС встает
AI_StandUp(self);
// идет к телу
AI_GotoNpc(self,other);
// поворачивается к телу
AI_TurnToNpc(self,other);
// проигрывание анимации грабежа
AI_PlayAni(self,"T_PLUNDER");
var int x;
// кол-во "Сырого мяса" у тела
x = Npc_HasItems(other,ItFoMuttonRaw);
// передать мясо от тела НПС
CreateInvItems(self,ItFoMuttonRaw,x);
Npc_RemoveInvItems(other,ItFoMuttonRaw,x);
// если жизнь НПС < половинной
if(self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX]/2))
{
// переход в состояние самолечения
AI_StartState(self,ZS_HealSelf,0,"");
return;
};
};


// ************************************************************
// Обработчик состояния реакции НПС на повреждение
// ------------------------------------------------------------
// self - НПС, получивший повреждение, other - агрессор
// ************************************************************


// Инициализация состояния
func void ZS_ReactToDamage()
{
// разрешить НПС нормальный набор восприятий
Perception_Set_Normal();
// НПС смотрит на агрессора
B_LookAtNpc(self,other);
// НПС выбирает оружие для поражения агрессора
B_SelectWeapon(self,other);
// НПС поворачивается к агрессору
B_TurnToNpc(self,other);
// НПС говорит агрессору (SVM фраза "Парень, никогда так больше не делай!")
B_Say (self, other, "$WHATAREYOUDOING");
// очистка счетчика секунд
self.aivar[AIV_StateTime] = 0;
};

// Цикл состояния
func int ZS_ReactToDamage_Loop()
{
// если прошла одна секунда
if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime])
{
// если НПС не видит агрессора
if(!Npc_CanSeeNpc(self,other))
{
// НПС поворачивается к агрессору
AI_TurnToNpc(self,other);
};
// счетчик секунд ++
self.aivar[AIV_StateTime] = self.aivar[AIV_StateTime] + 1;
};
// если прошло более 10 секунд
if(Npc_GetStateTime (self) > 10)
{
return LOOP_END;
}
else // [Примечание: else можно убрать, просто - return LOOP_CONTINUE;]
{
return LOOP_CONTINUE;
};
};

// Завершения состояния
func void ZS_ReactToDamage_End()
{
// НПС убирает оружие
AI_RemoveWeapon(self);
// перестает смотреть на агрессора
B_StopLookAt(self);
};


// ********************************************
// Обработчик состояния реакции НПС на оружие
// --------------------------------------------
// self - реагирующий НПС, other - агрессор
// ********************************************


// Инициализация состояния
func void ZS_ReactToWeapon()
{
// разрешить НПС минимальный набор восприятий
Perception_Set_Minimal();
// разрешить НПС восприятие сражения двух других НПС
Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND,B_AssessFightSound);
// реакция НПС на врага агрессора
if(B_AssessEnemy())
{
return;
};
// НПС встает
AI_StandUp(self);
// смотрит на агрессора
B_LookAtNpc(self,other);
// выбирает оружие
B_SelectWeapon(self,other);
// поворачивается к агрессору
B_TurnToNpc(self,other);
// если НПС выиграл последнее сражение с ГГ и была причина сражения с ГГ и агрессор ГГ
if(self.aivar[AIV_LastFightAgainstPlayer] == FIGHT_WON) && (self.aivar[AIV_LastPlayerAR] != AR_NONE) && (Npc_IsPlayer(other))
{
// НПС говорит ГГ (SVM фраза "Хочешь еще получить?")
B_Say(self,other,"$LOOKINGFORTROUBLEAGAIN");
}
// иначе, если комментария обнаженного оружия не было
else if(Player_DrawWeaponComment == FALSE)
{
// если агрессор хочет применить магию
if(Npc_IsInFightMode(other,FMODE_MAGIC))
{
// НПС говорит агрессору (SVM фраза "Перестань колдовать!")
B_Say(self,other,"$STOPMAGIC");
}
else // иначе
{
// НПС говорит агрессору (SVM фраза "Убери оружие!")
B_Say(self,other,"$WEAPONDOWN");
};
// установка флага состоявшегося комментария
Player_DrawWeaponComment = TRUE;
};
// НПС посылает предупреждение агрессору
Npc_SendPassivePerc(self,PERC_ASSESSWARN,self,other);
// сброс флага второго предупреждения
self.aivar[AIV_TAPOSITION] = FALSE;
// сброс счетчика времени
self.aivar[AIV_StateTime] = 0;
};

// Цикл состояния
func int ZS_ReactToWeapon_Loop()
{
// если расстояние между НПС и агрессором > дистанции действия восприятия
if(Npc_GetDistToNpc(self,other) > PERC_DIST_INTERMEDIAT)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС убирает оружие
AI_RemoveWeapon(self);
// перестает смотреть на агрессора
B_StopLookAt(self);
return LOOP_END;
};
// если агрессор убрал оружие
if(Npc_IsInFightMode(other,FMODE_NONE))
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС говорит агрессору (SVM фраза "Умный малый!")
B_Say(self,other,"$WISEMOVE");
// НПС убирает оружие
AI_RemoveWeapon(self);
// перестает смотреть на агрессора
B_StopLookAt (self);
return LOOP_END;
};
// если прошла одна секунда
if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime])
{
// если НПС не видит агрессора
if(!Npc_CanSeeNpc(self,other))
{
// НПС поворачивается к агрессору
B_TurnToNpc(self,other);
};
// счетчик времени ++
self.aivar[AIV_StateTime] = self.aivar[AIV_StateTime] + 1;
};
// если второго предупреждения не было и время в состоянии > 5 сек
if(self.aivar[AIV_TAPOSITION] == FALSE) && (Npc_GetStateTime(self) > 5)
{
// если агрессор хочет применить магию
if(Npc_IsInFightMode(other,FMODE_MAGIC))
{
// НПС говорит агрессору (SVM фраза "Убери свою магию! Ты что, оглох!?")
B_Say(self,other,"$ISAIDSTOPMAGIC");
}
else
{
// НПС говорит агрессору (SVM фраза "Да убери же чертово оружие!")
B_Say(self,other,"$ISAIDWEAPONDOWN");
};
// установить флаг второго предупреждения
self.aivar[AIV_TAPOSITION] = TRUE;
};
// если время в состоянии > 10 сек
if(Npc_GetStateTime(self) > 10)
{
// НПС атакует агрессора
B_Attack(self,other,AR_ReactToWeapon,0);
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_ReactToWeapon_End()
{
// НПС перестает смотреть на агрессора
B_StopLookAt(self);
// НПС переходит в заключительную фазу состояния наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,1,"");
};


// *****************************************
// Обработчик состояния разговора между НПС
// -----------------------------------------
// self - НПС источник информации, other - слушатель (всегда ГГ)
// *****************************************


var int zsTalkBugfix; // флаг выхода из разговора

// Инициализация состояния разговора
func void ZS_Talk()
{
// если ГГ уже с кем-то разговаривает
if(other.aivar[AIV_INVINCIBLE] == TRUE)
{
return;
};
// установка флагов начала разговора (для обоих участников)
self.aivar[AIV_INVINCIBLE] = TRUE;
other.aivar[AIV_INVINCIBLE] = TRUE;
// если НПС человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// если НПС сидит
if(C_BodyStateContains(self,BS_SIT))
{
var c_npc target;
// инициализация глобальной переменной target ссылкой на НПС, на которого смотрит источник информации
target = Npc_GetLookAtTarget(self);
// если target не существует
if(!Hlp_IsValidNpc(target))
{
// НПС смотрит на ГГ
AI_LookAtNpc(self,other);
};
}
else // иначе
{
// НПС смотрит на ГГ
B_LookAtNpc(self,other);
};
// НПС прячет оружие
AI_RemoveWeapon(self);
};
// если НПС не сидит
if(!C_BodystateContains(self,BS_SIT))
{
// НПС поворачивается к ГГ
B_TurnToNpc(self,other);
};
// если ГГ не сидит
if(!C_BodystateContains(other,BS_SIT))
{
// ГГ поворачивается к НПС
B_TurnToNpc(other,self);
// если расстояние между ГГ и НПС < 80 см
if(Npc_GetDistToNpc(other,self) < 80)
{
// ГГ отспупает назад
AI_Dodge(other);
};
};
// если НПС человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// если НПС сердит на ГГ или НПС враг ГГ
if(Npc_GetAttitude(self,other) == ATT_ANGRY) || (Npc_GetAttitude(self,other) == ATT_HOSTILE)
{
// если ГГ не переодет в бандита или НПС не бандит
if(!C_PlayerIsFakeBandit(self,other)) || (self.guild != GIL_BDT)
{
// включить "злую" анимацию лица НПС
Mdl_StartFaceAni(self,"S_ANGRY",1,-1);
};
};
// если НПС принадлежит к окружающему народу
if(self.npctype == NPCTYPE_AMBIENT) // общему
|| (self.npctype == NPCTYPE_OCAMBIENT) // или из Миненталя
|| (self.npctype == NPCTYPE_BL_AMBIENT) // или из Лагеря бандитов
|| (self.npctype == NPCTYPE_TAL_AMBIENT) // или из Долины бандитов
{
// инициализация диалога НПС об окружающей информации (сплетни)
B_AssignAmbientInfos(self);
// если НПС принадлежит городу
if(C_NpcBelongsToCity(self))
{
// инициализация диалога НПС о городской жизни
B_AssignCityGuide(self);
};
};
// если НПС является членом партии ГГ и...
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
&& (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Biff)) // НПС не Бифф
&& (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Biff_NW)) // и НПС не Бифф в Новом мире
&& (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Biff_DI)) // и НПС не Бифф на Острове драконов
&& (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Pardos)) // и НПС не Пардос
&& (Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Pardos_NW)) // и НПС не Пардос в Новом мире
{
// ГГ дает НПС напиток лечения
B_Addon_GivePotion(self);
};
// если НПС имеет дело с "крутым парнем" и НПС не имеет новостей о "крутом парне"
if(C_NpcIsToughGuy(self)) && (self.aivar[AIV_ToughGuyNewsOverride] == FALSE)
{
// инициализация диалога НПС о "крутом парне"
B_AssignToughGuyNEWS(self);
};
// если НПС имеет новости об окружающей жизни
if(C_NpcHasAmbientNews(self))
{
// инициализация диалога НПС об окружающих новостях
B_AssignAmbientNEWS(self);
};
};
// если НПС дракон
if (self.guild == GIL_DRAGON)
{
// проиграть анимацию дракона T_STAND_2_TALK
AI_PlayAni(self,"T_STAND_2_TALK");
};
// начать выбранный диалог
AI_ProcessInfos(self);
// сброс флага выхода из разговора
zsTalkBugfix = FALSE;
};

// Цикл состояния разговора
func int ZS_Talk_Loop ()
{
// если диалог закончен и флаг выхода установлен
if(InfoManager_HasFinished()) && (zsTalkBugfix == TRUE)
{
// сброс флагов разговора для обоих участников
self.aivar[AIV_INVINCIBLE] = FALSE;
other.aivar[AIV_INVINCIBLE] = FALSE;
// сброс флага важной информации
self.aivar[AIV_NpcStartedTalk] = FALSE;
// установка флага, что НПС говорил с ГГ
self.aivar[AIV_TalkedToPlayer] = TRUE;
// если НПС человек
if(self.guild < GIL_SEPERATOR_HUM)
{
// НПС перестает смотреть на ГГ
B_StopLookAt(self);
// сменить выражение лица НПС на обычное
Mdl_StartFaceAni(self,"S_NEUTRAL",1,-1);
};
// если НПС дракон
if(self.guild == GIL_DRAGON)
{
// запустить обычную анимацию стоящего дракона
AI_PlayAni(self,"T_TALK_2_STAND");
};
return LOOP_END;
}
else // иначе
{
// установить флаг выхода из разговора (нельзя завершить цикл разговора при первом вхождении)
zsTalkBugfix = TRUE;
return LOOP_CONTINUE;
};
};

// Окончание состояния разговора
func void ZS_Talk_End()
{
// отказ ГГ от других диалогов на 20 сек
Npc_SetRefuseTalk(other,20);
// когда НПС находится в своем помещении или (помещение публично и НПС не друг ГГ
if(C_NpcIsBotheredByPlayerRoomGuild(self)) || ((Wld_GetPlayerPortalGuild() == GIL_PUBLIC) && (Npc_GetAttitude(self,other) != ATT_FRIENDLY))
{
// НПС переходит в состояние наблюдения за ГГ
AI_StartState(self,ZS_ObservePlayer,0,"");
}
else // [лишнее, можно удалить]
{

};
};


// ***********************************************************
// Обработчик состояния наблюдения за сражением
// -----------------------------------------------------------
// self - НПС наблюдатель, other - агрессор, victim - жертва
// ***********************************************************


// Функция реакции НПС наблюдателя когда другой НПС получает повреждение
func void B_CheerFight()
{
// если время нахождения наблюдателя в этом состоянии <= 2 сек
if(Npc_GetStateTime(self) <= 2)
{
return;
};
// если агрессор монстр или жертва монстр
if((other.guild > GIL_SEPERATOR_HUM) || (victim.guild > GIL_SEPERATOR_HUM))
{
return;
};
// сброс времени нахождения в состоянии
Npc_SetStateTime(self,0);
// если наблюдатель имеет дело с "крутым парнем"
if(C_NpcIsToughGuy(self))
{
var int zufall;
// случайное число
zufall = Hlp_Random(3);
// если наблюдатель друг жертвы и наблюдатель не друг агрессору
if(Npc_GetAttitude(self,victim) == ATT_FRIENDLY) && (Npc_GetAttitude(self,other) != ATT_FRIENDLY)
{
// наблюдатель говорит сам себе (SVM фраза)
if(zufall == 0) { B_Say_Overlay(self,self,"$OOH01"); }; // "Смотри, не делай так!"
if(zufall == 1) { B_Say_Overlay(self,self,"$OOH02"); }; // "Вот тогда ты еще успеешь это сделать!"
if(zufall == 2) { B_Say_Overlay(self,self,"$OOH03"); }; // "Ох! Это же больно!"
// проиграть анимацию
AI_PlayAni(self,"T_WATCHFIGHT_OHNO");
}
else // иначе
{
// наблюдатель говорит сам себе (SVM фраза)
if(zufall == 0) { B_Say_Overlay(self,self,"$CHEERFRIEND01"); }; // "Да, это хорошо!"
if(zufall == 1) { B_Say_Overlay(self,self,"$CHEERFRIEND02"); }; // "Ну, сделай уже!"
if(zufall == 2) { B_Say_Overlay(self,self,"$CHEERFRIEND03"); }; // "Все просто здорово!"
// проиграть анимацию
AI_PlayAni(self,"T_WATCHFIGHT_YEAH");
};
};
};

// Функция реакции НПС наблюдателя когда другой НПС падает без сознания
func void B_AssessDefeat()
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
// если наблюдатель имеет дело с "крутым парнем" или (агрессор ГГ и наблюдатель друг ГГ)
if(C_NpcIsToughGuy(self)) || (Npc_IsPlayer(other) && (self.npctype == NPCTYPE_FRIEND))
{
// если наблюдатель друг ГГ
if(Npc_GetAttitude(self,other) == ATT_FRIENDLY)
{
// наблюдатель говорит ГГ (SVM фраза "Ну и показал же ты ему!")
B_Say(self,other,"$GOODVICTORY");
}
else // иначе
{
// наблюдатель говорит ГГ (SVM фраза "Неплохо...")
B_Say(self,other,"$NOTBAD");
};
}
else // иначе
{
// если у жертвы не было причины сражаться
if(victim.aivar[AIV_ATTACKREASON] != AR_NONE)
{
// наблюдатель говорит агрессору (SVM фраза "Боже мой! Какая жестокость...")
B_Say(self,other,"$OHMYGODHESDOWN");
// наблюдатель запоминает новость, что агрессор сражался с НПС жертвой
B_MemorizePlayerCrime(self,other,CRIME_ATTACK);
}
else // иначе
{
// наблюдатель говорит агрессору (SVM фраза "Неплохо...")
B_Say(self,other,"$NOTBAD");
};
};
};

// Инициализация состояния наблюдения за сражением
func void ZS_WatchFight ()
{
// разрешить наблюдателю локальное восприятие бессознательного состояния НПС
Npc_PercEnable(self,PERC_ASSESSDEFEAT,B_AssessDefeat);
// разрешить наблюдателю локальное восприятие если НПС получил повреждение
Npc_PercEnable(self,PERC_ASSESSOTHERSDAMAGE,B_CheerFight);
// разрешить минимальный набор восприятий
Perception_Set_Minimal();
// наблюдатель встает
AI_StandUp(self);
// поворачивается к жертве
B_TurnToNpc(self,victim);
// прячет оружие
AI_RemoveWeapon(self);
// если (расстояние между наблюдателем и агрессором или наблюдателем и жертвой < дистанции действия восприятия)
if((Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT) || (Npc_GetDistToNpc(self,victim) < PERC_DIST_INTERMEDIAT))
// и агрессор и жертва не без сознания
&& (!Npc_IsInState(other,ZS_UncoNPCious)) && (!Npc_IsInState(victim,ZS_UncoNPCious))
// и агрессор и жертва люди
&& ((other.guild < GIL_SEPERATOR_HUM) && (victim.guild < GIL_SEPERATOR_HUM))
{
// если наблюдатель имеет дело с "крутым парнем""
if(C_NpcIsToughGuy(self))
{
// наблюдатель говорит агрессору (SVM фраза "Ух ты, это же битва!")
B_Say(self,other,"$THERESAFIGHT");
}
else // иначе
{
// наблюдатель говорит агрессору (SVM фраза "Боже мой, вот это битва!")
B_Say(self,other,"$OHMYGODITSAFIGHT");
};
};
// сброс флага выхода из цикла
self.aivar[AIV_TAPOSITION] = NOTINPOS;
// очистить счетчик времени
self.aivar[AIV_StateTime] = 0;
};

// Цикл состояния наблюдения за сражением
func int ZS_WatchFight_Loop()
{
// если расстояние между наблюдателем и агрессором и наблюдателем и жертвой > дистанции наблюдения сражения
if(Npc_GetDistToNpc(self,other) > WATCHFIGHT_DIST_MAX) && (Npc_GetDistToNpc(self,victim) > WATCHFIGHT_DIST_MAX)
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
return LOOP_END;
};
// если (агрессор не атакует или не реагирует на повреждение)
if(!(Npc_IsInState(other,ZS_Attack) || Npc_IsInState(other,ZS_ReactToDamage)))
// и (жертва не атакует или не реагирует на повреждение)
&& (!(Npc_IsInState(victim,ZS_Attack) || Npc_IsInState(victim,ZS_ReactToDamage)))
// и время в состоянии > 0
&& (Npc_GetStateTime(self) > 0)
{
// если агрессор или жертва без сознания
if(Npc_IsInState(other,ZS_UncoNPCious)) || (Npc_IsInState(victim,ZS_UncoNPCious))
// или агрессор или жертва мертвы
|| (Npc_IsInState(other,ZS_Dead)) || (Npc_IsInState(victim,ZS_Dead))
{
// если флаг выхода из цикла сброшен
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// установить флаг
self.aivar[AIV_TAPOSITION] = ISINPOS;
return LOOP_CONTINUE;
}
else // иначе, флаг выхода из цикла установлен
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
// выход из цикла выполняется после второго прохода, если кто-либо из сражающихся мертв или без сознания (чтобы сработало соответствующее восприятие)
return LOOP_END;
};
}
else
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
return LOOP_END;
};
};
[COLOR=#
008080]// если наблюдатель имеет дело с "крутым парнем"[/COLOR]
if(C_NpcIsToughGuy(self))
{
// анимация удалена!!!
//AI_PlayAni(self,"T_STAND_2_WATCHFIGHT");
};
// если расстояние между наблюдателем и агрессором или наблюдателем и жертвой <= мин. дистанции наблюдения сражения
if(Npc_GetDistToNpc(self,other) <= WATCHFIGHT_DIST_MIN) || (Npc_GetDistToNpc(self,victim) <= WATCHFIGHT_DIST_MIN)
{
// очистка очереди AI состояний наблюдателя
Npc_ClearAIQueue(self);
// если расстояние между наблюдателем и агрессором <= расстояния между наблюдателем и жертвой
if(Npc_GetDistToNpc(self,other) <= Npc_GetDistToNpc(self,victim))
{
// наблюдатель поворачивается к жертве
B_TurnToNpc(self,victim);
}
else // иначе
{
// наблюдатель поворачивается к агрессору
B_TurnToNpc(self,other);
};
// наблюдатель делает шаг назад
AI_Dodge(self);
}
else // иначе (расстояние нормальное для наблюдения)
{
// если прошла секунда
if(Npc_GetStateTime(self) != self.aivar[AIV_StateTime])
{
// если если расстояние между наблюдателем и агрессором <= расстояния между наблюдателем и жертвой
if(Npc_GetDistToNpc(self,other) <= Npc_GetDistToNpc(self,victim))
{
// наблюдатель поворачивается к агрессору
B_TurnToNpc(self,other);
}
else // иначе
{
// наблюдатель поворачивается к жертве
B_TurnToNpc(self,victim);
};
// запись в счетчик текущего времени цикла
self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
};
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_WatchFight_End()
{
// анимация удалена!!!
//AI_PlayAni(self,"T_WATCHFIGHT_2_STAND");
};


// *****************************************************
// Обработчик состояния когда НПС находится без сознания
// Примечание: НПС в это состояние переводит ядро системы, когда у НПС кончается жизнь, а не скрипты!
// -----------------------------------------------------
// self - НПС без сознания, other - агрессор
// *****************************************************


// Инициализация состояния
func void ZS_UncoNPCious()
{
// разрешить НПС воспринимать магию
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// если НПС плыл или нырял
if(C_BodyStateContains(self,BS_SWIM)) || (C_BodyStateContains(self,BS_DIVE))
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// очистка всех восприятий
B_ClearPerceptions(self);
// переход НПС в состояние трупа (смерть)
AI_StartState(self,ZS_Dead,0,"");
return;
};
// сброс статуса предупреждения охраной
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(self.guild < GIL_SEPERATOR_HUM) && (Npc_IsPlayer(other))
{
// установить флаг, что НПС побежден ГГ
self.aivar[AIV_DefeatedByPlayer] = TRUE;
// установить, что НПС проиграл сражение с ГГ
self.aivar[AIV_LastFightAgainstPlayer] = FIGHT_LOST;
// если причины у НПС нападать на ГГ не было и ГГ этого НПС из наемников еще не бил и НПС наемник
if(self.aivar[AIV_LastPlayerAR] == AR_NONE) && (self.aivar[AIV_DuelLost] == FALSE) && (self.guild == GIL_SLD)
{
// увеличить счетчик для задания Торлофа (побить > 3 наемников)
Sld_Duelle_gewonnen = Sld_Duelle_gewonnen + 1;
// установить флаг, что наемник побит ГГ
self.aivar[AIV_DuelLost] = TRUE;
};
// если НПС сражался на арене с Альриком
if(self.aivar[AIV_ArenaFight] == AF_RUNNING)
{
// запись следующей фазы сражения на арене НПС
self.aivar[AIV_ArenaFight] = AF_AFTER;
};
};
// если НПС без сознания ГГ
if(Npc_IsPlayer(self))
{
// установить, что агрессор выиграл сражение с ГГ
other.aivar[AIV_LastFightAgainstPlayer] = FIGHT_WON;
// если ГГ сражался на арене с Альриком
if(other.aivar[AIV_ArenaFight] == AF_RUNNING)
{
// запись следующей фазы сражения на арене Альрику
other.aivar[AIV_ArenaFight] = AF_AFTER;
};
};
// удаление продаваемых предметов у торговцев
B_GiveTradeInv(self);
// удаление рун у НПС
B_ClearRuneInv(self);
// если (агрессор ГГ или агрессор член партии ГГ) и начисления экспы ГГ за победу над НПС не было
if(Npc_IsPlayer(other) || (other.aivar[AIV_PARTYMEMBER] == TRUE)) && (self.aivar[AIV_VictoryXPGiven] == FALSE)
{
// начисление ГГ экспы (уровень НПС * 10)
B_GivePlayerXP(self.level * XP_PER_VICTORY);
// установить НПС флаг начисления экспы
self.aivar[AIV_VictoryXPGiven] = TRUE;
};
// убрать оружие экипированное НПС
AI_UnequipWeapons(self);
// если НПС "Дар" и агрессор "Сайфер"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Dar)) && (Hlp_GetInstanceID(other) == Hlp_GetInstanceID(Cipher))
{
// установка флага для квеста с пакетом болотника
Dar_LostAgainstCipher = TRUE;
};
};

// Цикл состояния
func int ZS_UncoNPCious_Loop()
{
// если время цикла < времени нахождения в бессознательном состоянии
if(Npc_GetStateTime(self) < HAI_TIME_UNCONPCIOUS)
{
return LOOP_CONTINUE;
}
else // иначе
{
return LOOP_END;
};
};

// Завершение состояния
func void ZS_UncoNPCious_End()
{
// сброс флага, что тело обыскивалось
self.aivar[AIV_RANSACKED] = FALSE;
// НПС встает
AI_StandUp(self);
// если НПС ГГ
if(Npc_IsPlayer(self))
{
return;
};
// если НПС "Равен"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Raven))
{
// установка флага, что НПС всегда использует магию
self.aivar[AIV_MagicUser] = MAGIC_ALWAYS;
// Равен атакует ГГ
B_Attack(self,hero,AR_GuildEnemy,0);
return;
};
// если НПС видит агрессора по прямой и расстояние между НПС и агрессором < дистанции действия восприятия
if(Npc_CanSeeNpcFreeLOS(self,other)) && (Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT)
{
// НПС поворачивается к агрессору
B_TurnToNpc (self,other);
// если НПС имел дело с "крутым парнем" и НПС не враг агрессору и НПС не друг ГГ
if(C_NpcIsToughGuy(self)) && (Npc_GetPermAttitude(self,other) != ATT_HOSTILE) && (self.npctype != NPCTYPE_FRIEND)
{
// НПС говорит ГГ (SVM фраза "В следующий раз мы это увидим...")
B_Say(self,other,"$NEXTTIMEYOUREINFORIT");
}
else // иначе
{
// НПС говорит ГГ (SVM фраза "О, мой череп...")
B_Say(self,other,"$OHMYHEAD");
};
};
// разрешить НПС воспринимать все объекты в зоне действия восприятия
Npc_PerceiveAll(self);
// если НПС находит оружие ближнего или дальнего радиуса поражения
if(Wld_DetectItem(self,ITEM_KAT_NF)) || (Wld_DetectItem(self,ITEM_KAT_FF))
{
// если ссылка на предмет item существует
if(Hlp_IsValidItem(item))
{
// если расстояние от НПС до предмета < 5 метров
if(Npc_GetDistToItem(self,item) <= 500)
{
// НПС берет предмет
AI_TakeItem(self,item);
};
};
};
// экипировка лучшим оружием
AI_EquipBestMeleeWeapon(self);
AI_EquipBestRangedWeapon(self);
// переход НПС в состояние самолечения
AI_StartState(self,ZS_HealSelf,0,"");
return;
};


// *****************************************
// Обработчик состояния смерти НПС
// Примечание: НПС в это состояние переводит также и ядро системы, когда НПС добивают!
// -----------------------------------------
// self - мертвый НПС, other - убийца
// *****************************************


// Инициализация состояния смерти
func void ZS_Dead()
{
// сброс флага, что тело обыскивалось
self.aivar[AIV_RANSACKED] = FALSE;
// сброс флага, что НПС член партии
self.aivar[AIV_PARTYMEMBER] = FALSE;
// НПС перестает смотреть на кого-либо
B_StopLookAt(self);
// НПС прекращает на что-либо указывать
AI_StopPointAt(self);
// если (убийца ГГ или убийца член партии ГГ) и начисления экспы ГГ за убийство НПС не было
if(Npc_IsPlayer(other) || (other.aivar[AIV_PARTYMEMBER] == TRUE)) && (self.aivar[AIV_VictoryXPGiven] == FALSE)
{
// начисление ГГ экспы (уровень НПС * 10)
B_GivePlayerXP (self.level * XP_PER_VICTORY);
// установить НПС флаг начисления экспы
self.aivar[AIV_VictoryXPGiven] = TRUE;
};
// если убит "Расчленитель" в каньоне
if(C_IAmCanyonRazor(self) == TRUE)
{
// счетчик убитых расчленителей ++
CanyonRazorBodyCount = CanyonRazorBodyCount + 1;
// если квест Грега об очистке каньона в стадии выполнения
if(MIS_Addon_Greg_ClearCanyon == LOG_RUNNING)
{
// выдача на экран информации об убитых расчленителях
B_CountCanyonRazor();
};
};
// если убита "Болотная вонючка"
if(self.aivar[AIV_MM_REAL_ID] == ID_SWAMPDRONE)
{
// если расстояние между НПС и убийцей < 3 метров
if(Npc_GetDistToNpc(self,other) < 300)
{
// жизнь убийцы уменьшается на 50 пунктов
other.attribute[ATR_HITPOINTS] -= 50;
};
};
// если Диего убит в Рудниковой долине
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(DiegoOW))
{
// установить флаг "воскрешения" Диего в Хоринисе
Diego_IsDead = TRUE;
};
// если убийца ГГ
if(Npc_IsPlayer(other))
{
// установить флаг, что НПС убит ГГ
self.aivar[AIV_KilledByPlayer] = TRUE;
// если этого НПС не разрешалось убивать
if(C_DropUncoNPCious())
{
// счетчик невинно убитых ++
MadKillerCount = (MadKillerCount + 1);
};
// если убит "Полевой жук" и квест Фестера в стадии выполнения
if(self.guild == GIL_GIANT_BUG) && (MIS_Fester_KillBugs == LOG_RUNNING)
{
// увеличить счетчик убитых Полевых жуков
Festers_Giant_Bug_Killed = Festers_Giant_Bug_Killed + 1;
};
// если убита "Болотная крыса" и квест охоты с Аллигатором Джеком в стадии выполнения
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Swamprat)) && (MIS_KrokoJagd == LOG_Running)
{
// увеличить счетчик убитых Болотных крыс
AlligatorJack_KrokosKilled = AlligatorJack_KrokosKilled + 1;
};
// если убит "Рамон"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Ramon))
{
// установка флага, что ГГ может разговаривать с бандитами
Player_HasTalkedToBanditCamp = TRUE;
};
// если убит "Франко"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Franco))
{
// если квест "Охота на болотожоров с Логаном" в стадии выполнения
if(MIS_HlpLogan == LOG_RUNNING)
{
// квест завершается
MIS_HlpLogan = LOG_OBSOLETE;
};
// если квест "Найти Эдгора с каменной плиткой" в стадии выполнения
if(MIS_HlpEdgor == LOG_RUNNING)
{
// квест завершается
MIS_HlpEdgor = LOG_OBSOLETE;
};
};
// если убит "Фортуно"
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Fortuno))
{
// квест по "Поиску зеленого послушника" завершается
Log_SetTopicStatus(Topic_Addon_Fortuno,LOG_OBSOLETE);
};
};
// если убит "Ползун" в пещере (где должен появиться Блудвин)
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Goldminecrawler))
{
// если убито более 8 ползунов и Блудвина нет
if(Minecrawler_Killed >= 9) && (Bloodwyn_Spawn == FALSE)
{
// Блудвин появляется в точке ADW_MINE_TO_MC_03
AI_Teleport(Bloodwyn,"ADW_MINE_TO_MC_03");
// установить Блудвину распорядок дня
B_StartOtherRoutine(Bloodwyn,"MINE");
// начислить ГГ 500 экспы
B_GivePlayerXP(XP_Addon_Bloodywyn);
// установить флаг появления Блудвина
Bloodwyn_Spawn = TRUE;
}
else // иначе
{
// счетчик убитых ползунов ++
Minecrawler_Killed = (Minecrawler_Killed + 1);
};
};
// удаление продаваемых предметов у торговцев
B_GiveTradeInv(self);
// создать в инвентаре монстров добываемые предметы (в зависимости от способностей ГГ)
B_GiveDeathInv(self);
// удаление рун у НПС
B_ClearRuneInv(self);
// оставить счетчики криминала ГГ по локациям в старом состоянии
B_DeletePetzCrime(self);
// сброс флага криминала у НПС
self.aivar[AIV_NpcSawPlayerCommit] = CRIME_NONE;
// убрать оружие
AI_UnequipWeapons(self);
// сброс флага показа видео
self.aivar[AIV_TAPOSITION] = FALSE;
};

// Цикл смерти (выхода из него нет)
func int ZS_Dead_loop()
{
// если показа видео не было
if(self.aivar[AIV_TAPOSITION] == FALSE)
{
// показать видео соответствующее смерти НПС
B_DragonKillCounter(self);
// установить флаг показа видео
self.aivar[AIV_TAPOSITION] = TRUE;
};
return LOOP_CONTINUE;
};
 
Последнее редактирование:

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
9. Функции состояний монстров.

Все обработчики основных состояний монстров находятся в директории ..\AI\Monster\ZS_Monster\
Имена файлов соответствуют именам обработчиков.
// **************************************
// Обработчик состояния атаки
// --------------------------------------
// self - НПС агрессор, other - НПС цель
// **************************************


// Функция обработки вспомогательного восприятия PERC_ASSESSSURPRISE
// Вызывается ядром системы когда ГГ превращается в человека из животного

func void B_MM_AssessSurprise()
{
// целью агрессора становится ГГ
Npc_SetTarget(self,other);
};

// Мнициализация состояния атаки
func void ZS_MM_Attack()
{
// установка времени реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// разрешить восприятие мертвого тела
Npc_PercEnable(self,PERC_ASSESSBODY,B_MM_AssessBody);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_AssessDamage);
// разрешить восприятие предупреждения
Npc_PercEnable(self,PERC_ASSESSWARN,B_MM_AssessWarn);
// разрешить вспомогательное восприятие превращения
Npc_PercEnable(self,PERC_ASSESSSURPRISE,B_MM_AssessSurprise);
// инициализировать переменную other (последняя цель)
B_ValidateOther();
// если агрессор овца
if(self.guild == GIL_SHEEP)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// очистка восприятий
B_ClearPerceptions(self);
// установка цели
Npc_SetTarget(self,other);
// НПС убегает от цели
AI_StartState(self,ZS_MM_Flee,0,"");
return;
};
// НПС встает
AI_StandUp(self);
// включается режим передвижения - бег
AI_SetWalkmode(self,NPC_RUN);
// агрессору посылается предупреждение от цели
Npc_SendPassivePerc(self,PERC_ASSESSWARN,other,self);
// сброс флага окончания преследования
self.aivar[AIV_PursuitEnd] = FALSE;
// сброс счетчика времени нахождения в состоянии
self.aivar[AIV_StateTime] = 0;
// сброс флага первого удара
self.aivar[AIV_HitByOtherNpc] = 0;
// сброс выбранного заклинания
self.aivar[AIV_SelectSpell] = 0;
// сброс счетчика регенерации
self.aivar[AIV_TAPOSITION] = 0;
};

// Цикл состояния атаки
func int ZS_MM_Attack_Loop()
{
// повторно инициализировать other целью
Npc_GetTarget(self);
// если НПС дракон
if(self.guild == GIL_DRAGON)
{
// счетчик регенерации ++
self.aivar[AIV_TAPOSITION] += 1;
// если жизнь НПС < максимальной и счетчик регенерации >= 2 cек
if (self.attribute[ATR_HITPOINTS] < self.attribute[ATR_HITPOINTS_MAX]) && (self.aivar[AIV_TAPOSITION] >= 2)
{
// жизнь ++
self.attribute[ATR_HITPOINTS] += 1;
// сброс счетчика
self.aivar[AIV_TAPOSITION] = 0;
};
};
// если Равен убит и агрессор Каменный сторож
if(RavenIsDead == TRUE) && (self.guild == GIL_STONEGUARDIAN)
{
// агрессор умирает
B_KillNpc(self);
};
// если текущий уровень - Миненталь
if(CurrentLevel == OLDWORLD_ZEN)
{
// если расстояние от агрессора до точки OC_RAMP_07 <= 5 метров
if(Npc_GetDistToWP(self,"OC_RAMP_07") <= 500)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// проигрывается анимация T_WARN
AI_PlayAni(self,"T_WARN");
// установка флага окончания преследования
self.aivar[AIV_PursuitEnd] = TRUE;
return LOOP_END;
};
};
// если расстояние между НПС и целью > дистанции сражения
if(Npc_GetDistToNpc(self,other) > FIGHT_DIST_CANCEL)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
// установка флага окончания преследования
self.aivar[AIV_PursuitEnd] = TRUE;
return LOOP_END;
};
// если время преследования превышает допустимое и НПС преследует цель
if(Npc_GetStateTime(self) > self.aivar[AIV_MM_FollowTime]) && (self.aivar[AIV_PursuitEnd] == FALSE)
{
Npc_ClearAIQueue(self);
AI_StandUp(self);
// НПС закончил преследование
self.aivar[AIV_PursuitEnd] = TRUE;
// получить дистанцию до цели
self.aivar[AIV_Dist] = Npc_GetDistToNpc(self,other);
// обновить время состояния НПС
self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
// проиграть анимацию T_WARN
AI_PlayAni(self,"T_WARN");
};
// если НПС завершил преследование цели
if(self.aivar[AIV_PursuitEnd] == TRUE)
{
// если расстояние между НПС и целью > диапазона чувствительности НПС
if(Npc_GetDistToNpc(self,other) > self.senses_range)
{
return LOOP_END;
};
// если текущее время > предыдущего времени (прошла как минимум секунда)
if (Npc_GetStateTime (self) > self.aivar[AIV_StateTime])
{
// если расстояние между НПС и целью меньше дистанции, когда НПС прекратил преследование
if(Npc_GetDistToNpc(self,other) < self.aivar[AIV_Dist])
// или (цель не бежит и не прыгает)
|| ((!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP)))
{
// сброс флага окончания преследования
self.aivar[AIV_PursuitEnd] = FALSE;
// сброс времени нахождения НПС в этом состоянии
Npc_SetStateTime(self,0);
// сброс счетчика времени нахождения в состоянии
self.aivar[AIV_StateTime] = 0;
}
else
{
// НПС поворачивается к цели
AI_TurnToNpc(self,other);
// получить дистанцию до цели
self.aivar[AIV_Dist] = Npc_GetDistToNpc(self,other);
// обновить время состояния НПС
self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
};
};
return LOOP_CONTINUE;
};
// если (цель плывет или ныряет) и НПС не преследует цель в воде
if(C_BodyStateContains(other,BS_SWIM) || C_BodyStateContains(other,BS_DIVE)) && (self.aivar[AIV_MM_FollowInWater] == FALSE)
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
// если НПС выжидает перед атакой
if(self.aivar[AIV_WaitBeforeAttack] == 1)
{
// ожидание 0.8 сек
AI_Wait(self,0.8 );
// сброс флага задержки
self.aivar[AIV_WaitBeforeAttack] = 0;
};
// если уровень НПС == 0 (вызванный монстр)
if(self.level == 0)
{
// если текущее время > предыдущего времени (прошла как минимум секунда)
if(Npc_GetStateTime(self) > self.aivar[AIV_StateTime])
{
// время от начала вызова монстра ++
self.aivar[AIV_SummonTime] = (self.aivar[AIV_SummonTime] + 1);
// запомнить текущее время
self.aivar[AIV_StateTime] = Npc_GetStateTime(self);
};
// если время от начала вызова монстра >= времени жизни вызванных монстров
if(self.aivar[AIV_SummonTime] >= MONSTER_SUMMON_TIME)
{
// вызванный монстр умирает
Npc_ChangeAttribute(self,ATR_HITPOINTS,-self.attribute[ATR_HITPOINTS_MAX]);
};
};
// если цель не бежит и не прыгает и время в состоянии > 0
if((!C_BodyStateContains(other,BS_RUN)) && (!C_BodyStateContains(other,BS_JUMP))) && (Npc_GetStateTime(self) > 0)
{
// сброс времени текущего состояния
Npc_SetStateTime(self,0);
// сброс счетчика времени нахождения в состоянии
self.aivar[AIV_StateTime] = 0;
};
// если дистанция атаки > 0
if(self.aivar[AIV_MaxDistToWp] > 0)
{
// если расстояние между НПС и вайпоинтом НПС > дистанции атаки и расстояние между целью и вайпоинтом НПС > дистанции акаки
if(Npc_GetDistToWP(self,self.wp) > self.aivar[AIV_MaxDistToWp]) && (Npc_GetDistToWP(other,self.wp) > self.aivar[AIV_MaxDistToWp])
{
// установить НПС тактику защитников крепостных стен
self.fight_tactic = FAI_NAILED;
}
else // иначе (если НПС или цель близка к вайпоинту НПС)
{
// установить НПС родную тактику сражения
self.fight_tactic = self.aivar[AIV_OriginalFightTactic];
};
};
// если агрессор маг или
if(C_NpcIsMonsterMage(self))
|| (self.guild == GIL_SKELETON) // скелет
|| (self.guild == GIL_SUMMONED_SKELETON) // или вызванный скелет
|| (self.guild > GIL_SEPERATOR_ORC) // или орк
{
// создать боеприпасы
B_CreateAmmo(self);
// установить полную ману
Npc_ChangeAttribute(self,ATR_MANA,ATR_MANA_MAX);
// выбрать оружие, сответствующее цели
B_SelectWeapon(self,other);
};
// если цель существует и не обездвижена
if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other))
{
// если цель не в состоянии разговора
if(other.aivar[AIV_INVINCIBLE] == FALSE)
{
// НПС атакует цель (Примечание: функция AI_Attack работает только когда очередь AI состояний НПС пуста)
AI_Attack(self);
}
else
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
};
// запись НПС id последней цели
self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
return LOOP_CONTINUE;
}
else // иначе (если цель отсутствует или обездвижена)
{
// если приоритет агрессора на пожирание падали и агрессор может есть цель
if(self.aivar[AIV_MM_PRIORITY] == PRIO_EAT) && (C_WantToEat(self,other))
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
// разрешение воспринимать все объекты в зоне действия восприятий
Npc_PerceiveAll(self);
// поиск новой цели
Npc_GetNextTarget(self);
// если цель найдена и она не обездвижена
if(Hlp_IsValidNpc(other)) && (!C_NpcIsDown(other))
// и (расстояние между НПС и целью < дистанции действия восприятий или цель ГГ)
&& ((Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT) || (Npc_IsPlayer(other)))
// и цель не в состоянии разговора
&& (other.aivar[AIV_INVINCIBLE] == FALSE)
{
// запись НПС id последней цели
self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
return LOOP_CONTINUE;
}
else // иначе
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// НПС встает
AI_StandUp(self);
return LOOP_END;
};
};
};

// Завершение состояния атаки
func void ZS_MM_Attack_End()
{
// установить other на последнюю цель
other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
// если агрессор маг или
if(C_NpcIsMonsterMage(self))
|| (self.guild == GIL_SKELETON) // скелет
|| (self.guild == GIL_SUMMONED_SKELETON) // или вызванный скелет
|| (self.guild > GIL_SEPERATOR_ORC) // или орк
{
// НПС убирает оружие
AI_RemoveWeapon(self);
};
// если цель убита и агрессор может пожирать цель
if(Npc_IsDead(other)) && (C_WantToEat(self,other))
{
// очистка очереди AI состояний НПС
Npc_ClearAIQueue(self);
// переход в состояние пожирания добычи
AI_StartState(self,ZS_MM_EatBody,0,"");
return;
};
};


// *************************************************
// Обработчик состояния когда монстр поедает добычу
// -------------------------------------------------
// self - НПС монстр, other - добыча (труп)
// *************************************************


// Инициализация состояния
func void ZS_MM_EatBody()
{
// установка времени реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_AssessDamage);
// разрешить восприятие повреждения, нанесенного другому НПС
Npc_PercEnable(self,PERC_ASSESSOTHERSDAMAGE,B_MM_AssessOthersDamage);
// разрешить восприятие смерти
Npc_PercEnable(self,PERC_ASSESSMURDER,B_MM_AssessOthersDamage);
// монстр идет к телу
AI_GotoNpc(self,other);
// монстр поворачивается к добыче
AI_TurnToNpc(self,other);
// проигрывается анимация поедания
AI_PlayAni(self,"T_STAND_2_EAT");
// установить приоритет на поедание
self.aivar[AIV_MM_PRIORITY] = PRIO_EAT;
// ссылка на последнее съеденное тело
self.aivar[AIV_LASTBODY] = Hlp_GetInstanceID(other);
// сброс флага восприятия врага
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Цикл состояния
func int ZS_MM_EatBody_loop()
{
// если восприятие врага выключено
if (self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// разрешить восприятие врага
Npc_PercEnable(self,PERC_ASSESSENEMY,B_MM_AssessEnemy);
// установить флаг разрешения восприятия
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// если добыча съедена
if(!Hlp_IsValidNpc(other))
{
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_EatBody_end()
{
// прекратить анимацию поедания
AI_PlayAni(self,"T_EAT_2_STAND");
};

//****************************************************
// Обработчик состояния когда монстр убегает от врага
//----------------------------------------------------
// self - монстр, other - враг
//****************************************************


// Инициализация состояния
func void ZS_MM_Flee()
{
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// инициализировать переменную other врагом
B_ValidateOther();
// монстр встает
AI_StandUp(self);
// монстр переходит в режим бега
AI_SetWalkmode(self,NPC_RUN);
// монстру посылается предупреждение от врага
Npc_SendPassivePerc(self,PERC_ASSESSWARN,other,self);
// рассинхронизация [Примечание: мне непонятно зачем?]
B_MM_DeSynchronize();
};

// Цикл состояния
func int ZS_MM_Flee_Loop()
{
// обновить ссылку на врага
Npc_GetTarget(self);
// если расстояние между монстром и врагом < 20 метров
if(Npc_GetDistToNpc(self,other) < 2000)
{
// если прошла одна секунда
if(Npc_GetStateTime(self) > 0)
{
// враг посылает монстру предупреждение
Npc_SendPassivePerc(self,PERC_ASSESSWARN,other,self);
// сброс времени состояния
Npc_SetStateTime(self,0);
};
// монстр убегает от врага
AI_Flee(self);
return LOOP_CONTINUE;
}
else
{
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
return LOOP_END;
};
};

// Завершение состояния
func void ZS_MM_Flee_End()
{
}
;


// ********************************************
// Обработчик состояния охоты монстра
// --------------------------------------------
// self - монстр, other - жертва
// ********************************************


// Инициализация состояния охоты
func void ZS_MM_Hunt()
{
// разрешить базовые восприятия монстров
Perception_Set_Monster_Rtn();
// монстр встает
AI_StandUp(self);
// поворачивается к жертве
AI_TurnToNpc(self,other);
// переходит на шаг
AI_SetWalkmode(self,NPC_WALK);
// идет к жертве
AI_GotoNpc(self,other);
};

// Цикл состояния
func int ZS_MM_Hunt_Loop()
{
return LOOP_END;
};

// Завершение состояния
func void ZS_MM_Hunt_End()
{
}
;

// **************************************************
// Обработчик состояния когда монстр угрожает врагу
// --------------------------------------------------
// self - монстр, other - враг
// **************************************************


// Инициализация состояния угрозы
func void ZS_MM_ThreatenEnemy()
{
// установка времени реакции на восприятия 2 сек
Npc_SetPercTime(self,2);
// разрешить восприятие мертвого тела
Npc_PercEnable(self,PERC_ASSESSBODY,B_MM_AssessBody);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_AssessDamage);
// разрешить восприятие повреждения, нанесенного другому НПС
Npc_PercEnable(self,PERC_ASSESSOTHERSDAMAGE,B_MM_AssessOthersDamage);
// разрешить восприятие смерти
Npc_PercEnable(self,PERC_ASSESSMURDER,B_MM_AssessOthersDamage);
// монстр встает
AI_StandUp(self);
// враг посылает монстру предупреждение
Npc_SendPassivePerc(self,PERC_ASSESSWARN,other,self);
};

// Цикл состояния угрозы
func int ZS_MM_ThreatenEnemy_loop()
{
// если расстояние между монстром и врагом > дистанции действия активных восприятий
if(Npc_GetDistToNpc(self,other) > PERC_DIST_MONSTER_ACTIVE_MAX)
{
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
return LOOP_END;
};
// если расстояние между монстром и врагом <= дистанции начала атаки
if(Npc_GetDistToNpc(self,other) <= FIGHT_DIST_MONSTER_ATTACKRANGE)
{
// очистка очереди AI состояний монстра
Npc_ClearAIQueue(self);
// установка цели для монстра
Npc_SetTarget(self, other);
// переход в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return LOOP_END;
};
// если время в состоянии >= времени угрозы
if(Npc_GetStateTime(self) >= MONSTER_THREATEN_TIME)
{
Npc_ClearAIQueue(self);
Npc_SetTarget(self,other);
// переход в состояние атаки
AI_StartState(self,ZS_MM_Attack,0,"");
return LOOP_END;
};
// монстр поворачивается к врагу
AI_TurnToNpc(self,other);
// играется анимация угрозы
AI_PlayAni(self,"T_WARN");
return LOOP_CONTINUE;
};

// Завершение состояния угрозы
func void ZS_MM_ThreatenEnemy_end()
{
}
;
Системная функция AI_StartState может управлять последовательностью выполнения фаз состояний, за это отвечает параметр stateBehaviour, если он = 0, то сразу выполняется переход в указанное состояние, если он = 1, то переход в новое состояние выполнится только после полного завершения текущего состояния.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
10. Функции распорядка дня людей.

Все функции распорядка дня людей регистрируются в файле ..\AI\Human\TA.d
Шаблон регистрации любой функции:
func void TA_name(var int start_h,var int start_m,var int stop_h,var int stop_m,var string waypoint)
{
// регистрация обработчика состояния ZS_name с временами начала и конца работы в точке waypoint
TA_Min(self,start_h,start_m,stop_h,stop_m,ZS_name,waypoint);
};
где:
name - имя выполняемой функции,
start_h - час начала выполнения,
start_m - минута начала выполнения,
stop_h - час окончания выполнения,
stop_m - минута окончания выполнения,
waypoint - имя WP точки выполнения функции

Сами обработчики состояний функций распорядка дня людей находятся в директории ..\AI\Human\TA_Human\
Понятно, что вызов всех обработчиков состояний производится ядром системы в заданном интервале времени.
Обработчики состояний функций распорядка дня я рассматривать не буду, но если кому-то интересны некоторые обработчики, можно сделать заказ на их рассмотрение.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
11. Функции распорядка дня монстров.

Как таковой (по сравнению с людьми) распорядок дня у монстров отсутствует, есть функция планировщика суточного цикла монстров ZS_MM_AllScheduler, которая вызывает обработчики конкретных состояний.
Все файлы обработчиков суточных состояний монстров расположены в директории ..\AI\Monster\RTN_Monster
// **************************************
// Планировщик суточного цикла монстров
// **************************************


func void ZS_MM_AllScheduler()
{
// установить приоритет на питание вместо атаки
self.aivar[AIV_MM_PRIORITY] = PRIO_EAT;
// если НПС Каменный страж и Равен убит
if(self.guild == GIL_STONEGUARDIAN) && (RavenIsDead == TRUE)
{
// убить Каменного стража
B_KillNpc(self);
};
// если наступило время сна монстра или время контролируется программой поведения монстра
if(Wld_IsTime(self.aivar[AIV_MM_SleepStart],00,self.aivar[AIV_MM_SleepEnd]
,00) || (self.aivar[AIV_MM_SleepStart] == OnlyRoutine))
{
// перейти в состояние сна (обратить внимание на параметр stateBehaviour = 1, переход в состояние сна возможен только после полного завершения текущего состояния)
AI_StartState(self,ZS_MM_Rtn_Sleep,1,"");
}
// иначе, если наступило время отдыха монстра или время контролируется программой поведения монстра
else if(Wld_IsTime(self.aivar[AIV_MM_RestStart],00,self.aivar[AIV_MM_RestEnd],00) || (self.aivar[AIV_MM_RestStart] == OnlyRoutine))
{
// перейти в состояние отдыха
AI_StartState(self,ZS_MM_Rtn_Rest,1,"");
}
// иначе, если наступило время брожения монстра или время контролируется программой поведения монстра
else if(Wld_IsTime(self.aivar[AIV_MM_RoamStart],00,self.aivar[AIV_MM_RoamEnd],00) || (self.aivar[AIV_MM_RoamStart] == OnlyRoutine))
{
// перейти в состояние брожения
AI_StartState(self,ZS_MM_Rtn_Roam,1,"");
}
// иначе, если наступило время кормежки монстра или время контролируется программой поведения монстра
else if(Wld_IsTime(self.aivar[AIV_MM_EatGroundStart],00,self.aivar[AIV_MM_EatGroundEnd],00) || (self.aivar[AIV_MM_EatGroundStart] == OnlyRoutine))
{
// перейти в состояние кормежки
AI_StartState(self,ZS_MM_Rtn_EatGround,1,"");
}
// иначе, если наступило время резвости монстра или время контролируется программой поведения монстра
else if(Wld_IsTime(self.aivar[AIV_MM_WuselStart],00,self.aivar[AIV_MM_WuselEnd],00) || (self.aivar[AIV_MM_WuselStart] == OnlyRoutine))
{
// перейти в состояние резвости
AI_StartState(self,ZS_MM_Rtn_Wusel,1,"");
}
// иначе, если наступило время посидеть орку или время контролируется программой поведения монстра
else if(Wld_IsTime(self.aivar[AIV_MM_OrcSitStart],00,self.aivar[AIV_MM_OrcSitEnd],00) || (self.aivar[AIV_MM_OrcSitStart] == OnlyRoutine))
{
// перейти орку в сидячее состояние
AI_StartState(self,ZS_MM_Rtn_OrcSit,1,"");
}
else // иначе (по умолчанию)
{
// перейти в состояние отдыха
AI_StartState(self,ZS_MM_Rtn_Rest,1,"");
};
};


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


// Функция обработки локального восприятия тихих звуков во время сна
func void B_MM_AssessQuietSound_Sleep()
{
// если спящий монстр услышал врага
if(Wld_GetGuildAttitude(self.guild,other.guild) == ATT_HOSTILE)
{
// реакция монстра на врага
B_MM_AssessEnemy();
};
};

// Инициализация состояния сна
func void ZS_MM_Rtn_Sleep()
{
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_AssessDamage);
// разрешить восприятие повреждения, нанесенного другому НПС
Npc_PercEnable(self,PERC_ASSESSOTHERSDAMAGE,B_MM_AssessOthersDamage);
// разрешить восприятие смерти
Npc_PercEnable(self,PERC_ASSESSMURDER,B_MM_AssessOthersDamage);
// разрешить восприятие предупреждения
Npc_PercEnable(self,PERC_ASSESSWARN,B_MM_AssessWarn);
// разрешить восприятие тихих звуков (шаги, звон падающего предмета)
Npc_PercEnable(self,PERC_ASSESSQUIETSOUND,B_MM_AssessQuietSound_Sleep);
// установить режим передвижения шагом
AI_SetWalkmode (self, NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// если есть свободная точка с именем "FP_ROAM"
if(Wld_IsFPAvailable(self,"FP_ROAM"))
{
// монстр идет в эту точку
AI_GotoFP(self,"FP_ROAM");
};
// анимация "T_PERCEPTION"
AI_PlayAni(self,"T_PERCEPTION");
// анимация перехода ко сну
AI_PlayAniBS(self,"T_STAND_2_SLEEP",BS_LIE);
};

// Цикл состояния сна
func int ZS_MM_Rtn_Sleep_loop()
{
// если время сна истекло или время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_SleepStart],00,self.aivar[AIV_MM_SleepEnd],00)) && (self.aivar[AIV_MM_SleepStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Завершение состояния сна
func void ZS_MM_Rtn_Sleep_end()
{
// анимация пробуждения
AI_PlayAniBS(self,"T_SLEEP_2_STAND",BS_STAND);
};


// *************************************
// Обработчик состояния отдыха монстров
// *************************************


// Инициализация состояния отдыха
func void ZS_MM_Rtn_Rest()
{
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// режим пережвижения шагом
AI_SetWalkmode(self,NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// сброс флага достижения точки отдыха
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Цикл состояния отдыха
func int ZS_MM_Rtn_Rest_Loop()
{
// если НПС Каменный страж и Равен убит
if(self.guild == GIL_STONEGUARDIAN) && (RavenIsDead == TRUE)
{
// убить Каменного стража
B_KillNpc(self);
};
// если время отдыха истекло или время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_RestStart],00,self.aivar[AIV_MM_RestEnd],00)) && self.aivar[AIV_MM_RestStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
// если точка отдыха не достигнута
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// если есть свободная точка с именем "FP_ROAM"
if(Wld_IsFPAvailable(self,"FP_ROAM"))
{
// монстр идет в эту точку
AI_GotoFP(self,"FP_ROAM");
};
// если монстр дошел до точки
if(Npc_IsOnFP(self,"FP_ROAM"))
{
// установить флаг достижения точки отдыха
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
}
else // иначе (монстр находится в точке отдыха)
{
// с вероятностью 0,005 менять анимацию монстра
if(Hlp_Random(1000) <= 5)
{
var int randomMove;
randomMove = Hlp_Random(3);
if(randomMove == 0) { AI_PlayAni(self,"R_ROAM1"); };
if(randomMove == 1) { AI_PlayAni(self,"R_ROAM2"); };
if(randomMove == 2) { AI_PlayAni(self,"R_ROAM3"); };
};
};
return LOOP_CONTINUE;
};

// Завершение состояния отдыха
func void ZS_MM_Rtn_Rest_End()
{
}
;

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


// Инициализация состояния
func void ZS_MM_Rtn_Roam()
{
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// сброс флага чередования циклов (стоит или бродит)
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Цикл состояния брожения
func int ZS_MM_Rtn_Roam_loop()
{
// если время брожения истекло и время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_RoamStart],00,self.aivar[AIV_MM_RoamEnd],00)) && (self.aivar[AIV_MM_RoamStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
// фаза передвижения завершена
if (self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
var int wanderTime;
// время стояния
wanderTime = Hlp_Random(5);
// сброс времени цикла
Npc_SetStateTime(self,0);
// установить флаг стояния
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
// если время стояния закончилось
if(Npc_GetStateTime(self) > wanderTime)
{
// если есть свободная точка "FP_ROAM"
if(Wld_IsNextFPAvailable(self,"FP_ROAM"))
{
// монстр идет в эту мочку
AI_GotoNextFP(self,"FP_ROAM");
};
// сброс флага стояния
self.aivar[AIV_TAPOSITION] = NOTINPOS;
}
else // иначе (стояние)
{
// с вероятностью 0,005 менять анимацию монстра
if(Hlp_Random(1000) <= 5)
{
var int randomMove;
randomMove = Hlp_Random(3);
if(randomMove == 0) { AI_PlayAni(self,"R_ROAM1"); };
if(randomMove == 1) { AI_PlayAni(self,"R_ROAM2"); };
if(randomMove == 2) { AI_PlayAni(self,"R_ROAM3"); };
};
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_Roam_end()
{
}
;


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


// Инициализация состояния кормежки
func void ZS_MM_Rtn_EatGround()
{
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// режим пережвижения шагом
AI_SetWalkmode(self,NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// если есть свободная точка с именем "FP_ROAM"
if(Wld_IsFPAvailable(self,"FP_ROAM"))
{
// монстр идет в эту точку
AI_GotoFP(self,"FP_ROAM");
};
// анимация перехода в состояние кормежки
AI_PlayAni(self,"T_STAND_2_EAT");
// анимация кормежки
Mdl_ApplyRandomAni(self,"S_EAT","R_ROAM1");
Mdl_ApplyRandomAni(self,"S_EAT","R_ROAM2");
Mdl_ApplyRandomAni(self,"S_EAT","R_ROAM3");
Mdl_ApplyRandomAniFreq(self,"S_EAT",8.0);
};

// Цткл состояния кормежки
func int ZS_MM_Rtn_EatGround_Loop()
{
// если время кормежки истекло и время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_EatGroundStart],00,self.aivar[AIV_MM_EatGroundEnd],00)) && (self.aivar[AIV_MM_EatGroundStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
return LOOP_CONTINUE;
};

// Завершение состояния кормежки
func void ZS_MM_Rtn_EatGround_End()
{
// анимация выхода из состояния кормежки
AI_PlayAni(self,"T_EAT_2_STAND");
};

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


// Инициализация состояния резвости
func void ZS_MM_Rtn_Wusel()
{
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// режим пережвижения бегом
AI_SetWalkmode(self,NPC_RUN);
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр бежит в заданную точку
AI_GotoWP(self,self.wp);
};
// монстр бежит на свободную точку "FP_ROAM"
AI_GotoFP(self,"FP_ROAM");
};

// Цикл состояния резвости
func int ZS_MM_Rtn_Wusel_loop()
{
// если время резвости истекло и время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_WuselStart],00,self.aivar[AIV_MM_WuselEnd],00)) && (self.aivar[AIV_MM_WuselStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
// если монстр находится в этом состоянии >= 1 сек
if(Npc_GetStateTime (self) >= 1)
{
// если монстр находится в точке "FP_ROAM"
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);
// здесь лишний (можно удалить)
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};
return LOOP_CONTINUE;
};

// Завершение состояния резвости
func void ZS_MM_Rtn_Wusel_end()
{
}
;


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


// Инициализация состояния
func void ZS_MM_Rtn_OrcSit()
{
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// сброс флага достижения точки сидения
self.aivar[AIV_TAPOSITION] = NOTINPOS;
};

// Цикл состояния
func int ZS_MM_Rtn_OrcSit_loop()
{
// если время сидения истекло и время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_OrcSitStart],00,self.aivar[AIV_MM_OrcSitEnd],00)) && (self.aivar[AIV_MM_OrcSitStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
// если точка сидения не достигнута
if(self.aivar[AIV_TAPOSITION] == NOTINPOS)
{
// если есть свободная точка "FP_CAMPFIRE"
if(Wld_IsFPAvailable(self,"FP_CAMPFIRE"))
{
// монстр идет в эту точку
AI_GotoFP(self,"FP_CAMPFIRE");
};
// если монстр находится в точке "FP_CAMPFIRE"
if(Npc_IsOnFP(self,"FP_CAMPFIRE"))
{
// анимация сидящего орка
AI_PlayAniBS(self,"T_STAND_2_GUARDSLEEP",BS_SIT);
// установка флага достижения точки
self.aivar[AIV_TAPOSITION] = ISINPOS;
};
}
else // лишнее, можно удалить!
{
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_OrcSit_end()
{
// анимация выхода из сидячего положения
AI_PlayAniBS(self,"T_GUARDSLEEP_2_STAND",BS_STAND);
};
Несколько обработчиков состояний для некоторых типов монстров.
// ************************************
// Обработчик состояния отдыха дракона
// ************************************


// Инициализация состояния
func void ZS_MM_Rtn_DragonRest()
{
// установить время реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// приоритет на питание
self.aivar[AIV_MM_PRIORITY] = PRIO_EAT;
// если дракон не тестовый (строки программы, отмеченные в конце //*** можно удалить)
if(Hlp_GetInstanceID(self) != Hlp_GetInstanceID(Dragon_Testmodell)) //***
{ //***
// разрешить нормальный набор восприятий
Perception_Set_Monster_Rtn();
// разрешить восприятие ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_MM_AssessPlayer);
}; //***
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
// установить режим передвижения шагом
AI_SetWalkmode(self,NPC_WALK);
B_MM_DeSynchronize();
// если монстр не находится в заданной точке
if(Hlp_StrCmp(Npc_GetNearestWP(self),self.wp) == FALSE)
{
// монстр идет в заданную точку
AI_GotoWP(self,self.wp);
};
// если есть свободная точка с именем "FP_ROAM"
if(Wld_IsFPAvailable(self,"FP_ROAM"))
{
// монстр идет в эту точку
AI_GotoFP(self,"FP_ROAM");
}
else // иначе
{
// выравнивание в точке
AI_AlignToWP(self);
};
// сброс счетчика цикла регенерации
self.aivar[AIV_TAPOSITION] = 0;
};

// Цикл состояния
func int ZS_MM_Rtn_DragonRest_Loop()
{
// если время отдыха истекло и время не контролируется программой поведения монстра
if((!Wld_IsTime(self.aivar[AIV_MM_RestStart],00,self.aivar[AIV_MM_RestEnd],00)) && (self.aivar[AIV_MM_RestStart] != OnlyRoutine))
{
// переход в планировщик суточного цикла
AI_StartState(self,ZS_MM_AllScheduler,1,"");
return LOOP_END;
};
// если НПС дракон
if(self.guild == GIL_DRAGON)
{
// счетчик цикла регенерации ++
self.aivar[AIV_TAPOSITION] += 1;
// если жизнь дракона < максимальной и прошло не менее 2 сек
if(self.attribute[ATR_HITPOINTS] < self.attribute[ATR_HITPOINTS_MAX]) && (self.aivar[AIV_TAPOSITION] >= 2)
{
// жизнь дракона ++
self.attribute[ATR_HITPOINTS] += 1;
// сброс счетчика цикла регенерации
self.aivar[AIV_TAPOSITION] = 0;
};
};
// с вероятностью 0,005 менять анимацию монстра
if(Hlp_Random(1000) <= 5)
{
var int randomMove;
randomMove = Hlp_Random(3);
AI_StandUp(self);
if(randomMove == 0) { AI_PlayAni(self,"R_ROAM1"); };
if(randomMove == 1) { AI_PlayAni(self,"R_ROAM2"); };
if(randomMove == 2) { AI_PlayAni(self,"R_ROAM3"); };
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_DragonRest_End()
{
// анимация выхода из отдыха
AI_PlayAni(self,"T_REST_2_STAND");
};


// *******************************************
// Обработчик состояния когда овца идет за ГГ
// *******************************************


// Инициализация состояния
func void ZS_MM_Rtn_Follow_Sheep()
{
// установить время реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// разрешить восприятие ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_MM_AssessPlayer);
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
};

// Цикл состояния
func int ZS_MM_Rtn_Follow_Sheep_Loop()
{
// если НПС член партии ГГ
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
// если расстояние между НПС и ГГ > 5 метров
if(Npc_GetDistToNpc(self,hero) > 500)
{
// если НПС не плывет
if(!C_BodyStateContains(self,BS_SWIM))
{
// НПС переходит на бег
AI_SetWalkmode(self,NPC_RUN);
};
// НПС движется к ГГ
AI_GotoNpc(self,hero);
}
else // иначе
{
// НПС поворачивается к ГГ
AI_TurnToNpc(self,hero);
// установить для НПС ближайшую свободную точку
self.wp = Npc_GetNearestWP(self);
};
}
else // иначе
{
// анимация
var int randomMove;
randomMove = Hlp_Random(3);
if(randomMove == 0) { AI_PlayAni(self,"R_ROAM1"); };
if(randomMove == 1) { AI_PlayAni(self,"R_ROAM2"); };
if(randomMove == 2) { AI_PlayAni(self,"R_ROAM3"); };
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_Follow_Sheep_End()
{
}
;

// ****************************************************
// Обработчик состояния когда овца идет за Бальтасаром
// ****************************************************


// Инициализация состояния
func void ZS_MM_Rtn_Follow_Sheep_Balthasar()
{
// установить время реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// разрешить восприятие ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_MM_AssessPlayer);
};

// Цикл состояния
func int ZS_MM_Rtn_Follow_Sheep_Balthasar_Loop()
{
// если расстояние между Бальтасаром и точкой "NW_BIGMILL_FARM3_BALTHASAR" > 5 м
if(Npc_GetDistToWP(Balthasar,"NW_BIGMILL_FARM3_BALTHASAR") > 500)
{
// если расстояние между НПС и Бальтасаром > 5 метров
if(Npc_GetDistToNpc(self,Balthasar) > 500)
{
// если НПС не плывет
if(!C_BodyStateContains(self,BS_SWIM))
{
// НПС переходит на бег
AI_SetWalkmode(self,NPC_RUN);
};
// НПС движется к Бальтасару
AI_GotoNpc(self,Balthasar);
}
else // иначе
{
// НПС поворачивается к Бальтасару
AI_TurnToNpc(self,Balthasar);
// установить для НПС ближайшую свободную точку
self.wp = Npc_GetNearestWP(self);
};
}
else // иначе (когда пришли)
{
// переход НПС в состояние брожения около точки "NW_BIGMILL_FARM3_BALTHASAR"
AI_StartState(self,ZS_MM_Rtn_Roam,1,"NW_BIGMILL_FARM3_BALTHASAR"
);
};
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_Follow_Sheep_Balthasar_End ()
{
}
;


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


// Локальное восприятие разговора с ГГ
func void B_SummonedAssessTalk()
{
// вызванный монстр умирает (жизнь = 0)
Npc_ChangeAttribute(self,ATR_HITPOINTS,-self.attribute[ATR_HITPOINTS_MAX])
;
};

// Инициализация состояния
func void ZS_MM_Rtn_Summoned()
{
// установить время реакции на восприятия 1 сек
Npc_SetPercTime(self,1);
// разрешить восприятие ГГ
Npc_PercEnable(self,PERC_ASSESSPLAYER,B_MM_AssessPlayer);
// разрешить восприятие врага
Npc_PercEnable(self,PERC_ASSESSENEMY,B_MM_AssessEnemy);
// разрешить восприятие магии
Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
// разрешить восприятие повреждения
Npc_PercEnable(self,PERC_ASSESSDAMAGE,B_MM_AssessDamage);
// разрешить восприятие сражения двух других НПС
Npc_PercEnable(self,PERC_ASSESSFIGHTSOUND,B_MM_AssessOthersDamage);
// если вызванный НПС Огонек
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Wisp_Detector))
{
// разрешить восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_AssessTalk);
}
else // иначе (если монстр)
{
// разрешить локальное восприятие разговора
Npc_PercEnable(self,PERC_ASSESSTALK,B_SummonedAssessTalk);
};
// установить дружеское отношение к ГГ
B_SetAttitude(self,ATT_FRIENDLY);
// НПС член партии ГГ
self.aivar[AIV_PARTYMEMBER] = TRUE;
// НПС встает
AI_StandUp(self);
// режим передвижения - бег
AI_SetWalkmode(self,NPC_RUN);
};

// Цикл состояния
func int ZS_MM_Rtn_Summoned_Loop()
{
// Выполнение Огоньком заданий
B_MM_WispDetect();
// если расстояние между НПС и ГГ > 5 метров
if(Npc_GetDistToNpc (self, hero) > 500)
{
// НПС бежит к ГГ
AI_GotoNpc(self,hero);
}
else //иначе
{
// если прошла секунда
if(Npc_GetStateTime(self) >= 1)
{
// если НПС не видит ГГ
if(!Npc_CanSeeNpc(self,hero))
{
// НПС поворачивается к ГГ
AI_TurnToNpc(self,hero);
};
// увеличение времени вызова монстра
self.aivar[AIV_SummonTime] = (self.aivar[AIV_SummonTime] + Npc_GetStateTime(self));
// если время вызова монстра превысило время жизни
if(self.aivar[AIV_SummonTime] >= MONSTER_SUMMON_TIME)
{
// вызванный монстр умирает (жизнь = 0)
Npc_ChangeAttribute(self,ATR_HITPOINTS,-self.attribute[ATR_HITPOINTS_MAX])
;
};
// сброс времени состояния
Npc_SetStateTime (self, 0);
};
};
// установить для НПС ближайшую свободную точку
self.wp = Npc_GetNearestWP(self);
return LOOP_CONTINUE;
};

// Завершение состояния
func void ZS_MM_Rtn_Summoned_End()
{
}
;
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
12. Вспомогательные В_ функции для людей.

Все В_ функции расположены в директории ..\AI\Human\B_Human\
// ********************************************************
// Функция переводящая НПС в состояние атаки
// ********************************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - атакующий НПС (далее - агрессор)
// oth - атакуемый НПС (далее - жертва)
// attack_reason - причина атаки
// wait - время выжидания перед атакой
// ======================================


func void B_Attack(var c_npc slf,var c_npc oth,var int attack_reason,var int wait)
{
// установить агрессору время задержки перед атакой
slf.aivar[AIV_WaitBeforeAttack] = wait;
// если агрессор должен атаковать немедленно
if(attack_reason == AR_SuddenEnemyInferno)
{
// установить агрессору флаг наличия врага
slf.aivar[AIV_EnemyOverride] = FALSE;
// послать жертве восприятие нападения
Npc_SendPassivePerc(slf,PERC_ASSESSFIGHTSOUND,slf,oth);
};
// если агрессор находится в состоянии разговора
if(Npc_IsInState(slf,ZS_Talk))
{
// закончить разговор агрессору
slf.aivar[AIV_INVINCIBLE] = FALSE;
// закончить разговор жертве
oth.aivar[AIV_INVINCIBLE] = FALSE;
};
// если агрессор находится в состоянии атаки и жертва есть последняя цель агрессора
if(Npc_IsInState(slf,ZS_Attack)) && (Hlp_GetInstanceID(oth) == slf.aivar[AIV_LASTTARGET])
{
// если причина атаки агрессора не убийство жертвы и новая причина атаки приоритетней существующей причины атаки
if(!C_NpcHasAttackReasonToKill(slf)) && (attack_reason > slf.aivar[AIV_ATTACKREASON])
{
// установить агрессору новую причину атаки
slf.aivar[AIV_ATTACKREASON] = attack_reason;
// если жертва ГГ
if(Npc_IsPlayer(oth))
{
// установить агрессору причину атаки ГГ
slf.aivar[AIV_LastPlayerAR] = attack_reason;
};
};
}
else // иначе
{
// установить агрессору новую причину атаки
slf.aivar[AIV_ATTACKREASON] = attack_reason;
// если жертва ГГ
if (Npc_IsPlayer(oth))
{
// установить агрессору причину атаки ГГ
slf.aivar[AIV_LastPlayerAR] = attack_reason;
};
};
// если агрессор атакует убийцу овец
if(slf.aivar[AIV_ATTACKREASON] == AR_SheepKiller)
{
// запоминается новость, что жертва убила овцу
B_MemorizePlayerCrime(slf,oth,CRIME_SHEEPKILLER);
};
// если причина атаки вызвана повреждением агрессора или является реакцией на обнаженное оружие
if(slf.aivar[AIV_ATTACKREASON] == AR_ReactToDamage) || (slf.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon)
{
// если агрессор имеет дело не с "крутым парнем" и (жертва не ГГ и не друг агрессору)
if(!C_NpcIsToughGuy(slf)) && (!(Npc_IsPlayer(oth) && (slf.npctype == NPCTYPE_FRIEND)))
{
// запоминается новость, что ГГ сражался с НПС
B_MemorizePlayerCrime(slf,oth,CRIME_ATTACK);
};
};
// если причина атаки воровство или использование МОВа
if(slf.aivar[AIV_ATTACKREASON] == AR_Theft) || (slf.aivar[AIV_ATTACKREASON] == AR_UseMob)
{
// запоминается новость, что ГГ воровал
B_MemorizePlayerCrime(slf,oth,CRIME_THEFT);
};
// если причина атаки убийство человека
if(slf.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman)
{
// запоминается новость, что ГГ совершил убийство
B_MemorizePlayerCrime(slf,oth,CRIME_MURDER);
};
// если агрессор уже в состоянии атаки
if(Npc_IsInState(slf,ZS_Attack))
{
return;
};
// если причина атаки убийство
if (slf.aivar[AIV_ATTACKREASON] == AR_KILL)
{
// установить враждебное отношение агрессора к ГГ
B_SetAttitude(slf,ATT_HOSTILE);
};
// если ГГ жертва
if(Npc_IsPlayer(oth))
{
// параметр последнего сражения с ГГ - прервано
slf.aivar[AIV_LastFightAgainstPlayer] = FIGHT_CANCEL;
// последнее сражение не комментировалось
slf.aivar[AIV_LastFightComment] = FALSE;
};
// если агрессор не в состоянии разговора
if(!Npc_IsInState(slf,ZS_Talk))
{
// очистить очередь AI состояний агрессора
Npc_ClearAIQueue(slf);
};
// запретить агрессору восприятия
B_ClearPerceptions(slf);
// установить в качестве цели жертву
Npc_SetTarget(slf,oth);
// если агрессор лежит
if(C_BodyStateContains(slf,BS_LIE))
{
// переход в состояние атаки с завершением предыдущего состояния
AI_StartState(slf,ZS_Attack,1,"");
}
else // иначе
{
// немедленный переход в состояние атаки
AI_StartState(slf,ZS_Attack,0,"");
};
return;
};


// **************************************
// Функция вызова охраны
// --------------------------------------
// self - НПС агрессор, other - НПС жертва
// **************************************


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

func int C_WantToCallGuards(var c_npc slf)
{
// если агрессор не является членом партии ГГ
if(self.aivar[AIV_PARTYMEMBER] == FALSE)
{
// если НПС принадлежит к
if(slf.guild == GIL_PAL) // паладинам
|| (slf.guild == GIL_MIL) // или милиции
|| (slf.guild == GIL_VLK) // или горожанам
|| (slf.guild == GIL_SLD) // или наемникам
|| (slf.guild == GIL_BAU) // или крестьянам
{
// охрана может быть вызвана
return TRUE;
};
};
// охрану вызвать нельзя
return FALSE;
};

// Вызов охраны
func void B_CallGuards()
{
// если агрессор не может вызвать охрану
if(!C_WantToCallGuards(self))
{
return;
};
// если причина атаки
if(self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToKill) // вызвана охрана по факту убийства
|| (self.aivar[AIV_ATTACKREASON] == AR_GuardStopsFight) // или охрана прекратила атаковать преступника
|| (self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToThief) // или охрана вызвана по факту воровства
|| (self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToRoom) // или охрана вызвана для защиты помещения
{
// агрессор говорит жертве (SVM фраза "ТРЕВОГА!")
B_Say_Overlay(self,other,"$ALARM");
return;
};
// если причина атаки - нападение на врага или убийство человека
if(self.aivar[AIV_ATTACKREASON] == AR_GuildEnemy) || (self.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman)
{
// если агрессор милиционер или паладин или наемник
if(self.guild == GIL_MIL) || (self.guild == GIL_PAL) || (self.guild == GIL_SLD)
{
// агрессор говорит жертве (SVM фраза "ТРЕВОГА!")
B_Say_Overlay(self,other,"$ALARM");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
// если агрессор имеет дело не с "крутым парнем"
if(!C_NpcIsToughGuy(self))
{
// агрессор говорит жертве (SVM фраза "ОХРАНА!")
B_Say_Overlay(self,other,"$GUARDS");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
return;
};
// если охрана ворот атакует незваного гостя
if(self.aivar[AIV_ATTACKREASON] == AR_GuardStopsIntruder)
{
// агрессор говорит жертве (SVM фраза "ТРЕВОГА!")
B_Say_Overlay(self,other,"$ALARM");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
// если причина атаки воровство или использование чужого МОВа
if(self.aivar[AIV_ATTACKREASON] == AR_Theft) || (self.aivar[AIV_ATTACKREASON] == AR_UseMob)
{
// если агрессор имеет дело не с "крутым парнем"
if(!C_NpcIsToughGuy(self))
{
// агрессор говорит жертве (SVM фраза "ОХРАНА!")
B_Say_Overlay(self,other,"$GUARDS");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
};
return;
};
// если причина нападения - реакция на обнаженное оружие
if (self.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon)
{
// если агрессор имеет дело не с "крутым парнем"
if(!C_NpcIsToughGuy(self))
{
// агрессор говорит жертве (SVM фраза "ОХРАНА!")
B_Say_Overlay(self,other,"$GUARDS");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
};
return;
};
// если причина нападения - посягательство на чужое помещение
if(self.aivar[AIV_ATTACKREASON] == AR_ClearRoom)
{
// если агрессор милиционер или паладин или наемник
if(self.guild == GIL_MIL) || (self.guild == GIL_PAL) || (self.guild == GIL_SLD)
{
// агрессор говорит жертве (SVM фраза "ТРЕВОГА!")
B_Say_Overlay(self,other,"$ALARM");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
// если агрессор имеет дело не с "крутым парнем"
if(!C_NpcIsToughGuy(self))
{
// агрессор говорит жертве (SVM фраза "ОХРАНА!")
B_Say_Overlay(self,other,"$GUARDS");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
return;
};
return;
};


// *************************************************************************
// Обработчик состояния комментирования подставной гильдии (переодетого ГГ)
// -------------------------------------------------------------------------
// self - НПС источник информации, other - НПС приемник информации (обычно ГГ)
// *************************************************************************


func void ZS_CommentFakeGuild()
{
// разрешить минимальный набор восприятий
Perception_Set_Minimal();
// НПС встает
AI_StandUp(self);
// если НПС не сидит
if(!C_BodystateContains(self,BS_SIT))
{
// НПС поворачивается к ГГ
B_TurnToNpc(self,other);
};
// если ГГ не сидит
if(!C_BodystateContains(other,BS_SIT))
{
// ГГ поворачивается к НПС
B_TurnToNpc(other,self);
// если расстояние между ГГ и НПС < 80 см
if(Npc_GetDistToNpc(other,self) < 80)
{
// ГГ делает шаг назад
AI_Dodge(other);
};
};
// если на ГГ одеты доспехи
if(Npc_HasEquippedArmor(other) == TRUE)
{
var c_item itm;
// получить ссылку на доспехи
itm = Npc_GetEquippedArmor(other);
// если НПС милиционер или паладин
if(self.guild == GIL_MIL || self.guild == GIL_PAL)
{
// НПС говорит ГГ (SVM фраза "Ты солдат! Одевайся соответственно.")
B_Say (self,other, "$ADDON_WRONGARMOR_MIL");
}
// иначе, если НПС маг послушник или маг огня
else if(self.guild == GIL_NOV || self.guild == GIL_KDF)
{
// НПС говорит ГГ (SVM фраза "Эта одежда не соответствует нашему ордену. Переоденься.")
B_Say(self,other,"$ADDON_WRONGARMOR_KDF");
}
// иначе, если НПС наемник или охотник на драконов
else if(self.guild == GIL_SLD || self.guild == GIL_DJG)
{
// НПС говорит ГГ (SVM фраза "В каком виде ты тут бродишь? Одень что-то приличное.")
B_Say(self,other,"$ADDON_WRONGARMOR_SLD");
}
else // иначе (другие гильдии)
{
// НПС говорит ГГ (SVM фраза "Это не твоя одежда. Я с тобой не буду говорить.")
B_Say(self,other,"$ADDON_WRONGARMOR");
};
}
else // иначе (ГГ без доспехов)
{
// если НПС бандит
if(self.guild == GIL_BDT)
{
// НПС говорит ГГ (SVM фраза "Да на тебе даже кольчуги нет. Проваливай!")
B_Say(self,other,"$ADDON_NOARMOR_BDT");
};
};
};


// **************************************
// Функция подготовки НПС боеприпасов
// **************************************


// ======================================
// Аргументы:
// --------------------------------------
// slf - экипируемый НПС
// ======================================


func void B_CreateAmmo(var c_npc slf)
{
var c_item rangedWeapon;
// если НПС находится в боевом режиме с оружием дальнего радиуса поражения
if(Npc_IsInFightMode(slf,FMODE_FAR))
{
// получить оружие, которое НПС держит в руках
rangedWeapon = Npc_GetReadiedWeapon(slf);
}
// иначе, если НПС экипирован оружием дальнего радиуса поражения
else if(Npc_HasEquippedRangedWeapon(slf))
{
// получить оружие дальнего радиуса поражения, которым экипирован НПС
rangedWeapon = Npc_GetEquippedRangedWeapon(slf);
}
else // иначе
{
return;
};
// если боезапас - Стрела
if(rangedWeapon.munition == ItRw_Arrow)
{
// если у НПС < 10 стрел
if(Npc_HasItems(slf,ItRw_Arrow) < 10)
{
// создать в инвентаре НПС 10 стрел
CreateInvItems(slf,ItRw_Arrow,10);
};
}
// иначе, если боезапас - Болт
else if(rangedWeapon.munition == ItRw_Bolt)
{
// если у НПС < 10 болтов
if(Npc_HasItems(slf,ItRw_Bolt) < 10)
{
// создать в инвентаре НПС 10 болтов
CreateInvItems(slf,ItRw_Bolt,10);
};
};
};


// **************************************
// Функция добивания НПС
// **************************************


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


func void B_FinishingMove(var c_npc slf,var c_npc oth)
{
// если агрессор не находится в режиме сражения с оружием ближнего радиуса поражения
if(!Npc_IsInFightMode(slf,FMODE_MELEE))
{
// агрессор ставится в режим сражения с оружием Ржавый меч
Npc_SetToFightMode(slf,ItMw_1h_MISC_Sword);
};
// агрессор добивает жертву
AI_FinishingMove (slf, oth);
};


// ********************************
// НПС перестает смотреть на цель
// ********************************


// ================================
// Аргументы:
// --------------------------------
// slf - смотрящий НПС
// ================================


func void B_StopLookAt(var c_npc slf)
{
var c_npc target;
// получить цель, на которую смотрит НПС
target = Npc_GetLookAtTarget(slf);
// если цель существует
if(Hlp_IsValidNpc(target))
{
// НПС перестает смотреть на цель
AI_StopLookAt (slf);
};
};

// ***************************
// НПС смотрит на другого НПС
// ***************************


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


func void B_LookAtNpc(var c_npc slf,var c_npc oth)
{
// НПС перестает смотреть на старую цель
B_StopLookAt(slf);
// НПС смотрит на новую цель
AI_LookAtNpc(slf,oth);
};

// **************************************
// НПС поворачивается к другому НПС
// **************************************


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


func void B_TurnToNpc(var c_npc slf,var c_npc oth)
{
// НПС поворачивается к цели
AI_TurnToNpc(slf,oth);
};


// *********************************
// Перевод НПС в исходное состояние
// *********************************


// ================================
// Аргументы:
// --------------------------------
// slf - НПС, переводимый в исходное состояние
// ================================


func void B_ResetAll(var c_npc slf)
{
// НПС перестает смотреть на цель
B_StopLookAt(slf);
// НПС прячет оружие
AI_RemoveWeapon(slf);
};


// *******************************
// НПС говорит SVM фразу
// *******************************


// ===============================
// Аргументы:
// -------------------------------
// slf - говорящий НПС
// oth - слушающий НПС
// text - имя переменной класса C_SVM, которая содержит произносимую фразу (должно начинаться с символа $)
// ===============================


func void B_Say(var c_npc slf,var c_npc oth,var string text)
{
// НПС говорит другому НПС SVM (Standart Voice Module) фразу
AI_OutputSVM(slf,oth,text);
};


// ******************************
// Комментарий завершенной атаки
// ------------------------------
// self - агрессор, other - жертва
// ******************************


func void B_Say_AttackEnd()
{
// если агрессор атаковал врага или монстра, убившего человека
if(self.aivar[AIV_ATTACKREASON] == AR_GuildEnemy) || (self.aivar[AIV_ATTACKREASON] == AR_MonsterMurderedHuman)
{
// если жертва человек
if(other.guild < GIL_SEPERATOR_HUM)
{
// если жертва не убита
if(!Npc_IsDead(other))
{
// если последняя атакованная цель и есть жертва
if(self.aivar[AIV_LASTTARGET] == Hlp_GetInstanceID(other))
{
// агрессор говорит жертве (SVM фраза) "Умри, подлец!"
B_Say(self,other,"$KILLENEMY");
}
else // иначе
{
// агрессор говорит жертве (SVM фраза) "Да, убей эту свинью!"
B_Say(self,other,"$GOODKILL");
};
}
else // иначе (жертва мертва)
{
// агрессор говорит жертве (SVM фраза) "Ты это заслужил, подлец!"
B_Say(self,other,"$ENEMYKILLED");
};
}
else // иначе (жертва монстр)
{
// если агрессор член партии ГГ
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
var int rnd;
rnd = Hlp_Random(100);
// если вероятность 0.85 и жертва не дракон
if(rnd > 15) && (other.guild != GIL_DRAGON)
{
return;
};
};
// если жертва убита не ГГ
if(other.aivar[AIV_KilledByPlayer] == FALSE)
{
// если агрессор имеет номер голоса 9
if(self.voice == 9)
{
var int random;
random = Hlp_Random(2);
// если вероятность 0.5
if(random == 0)
{
// агрессор говорит жертве (SVM фраза) "С тобой покончено, скотина!"
B_Say(self,other,"$ADDON_MONSTERKILLED");
}
else
{
// агрессор говорит жертве (SVM фраза) "На ОДНУ тварь меньше."
B_Say(self,other,"$ADDON_MONSTERKILLED2");
};
}
// иначе, если агрессор имеет номер голоса 12
else if(self.voice == 12)
{
// если агрессор Горн
if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(GornOW)) // в Рудниковой долине
|| (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(GornDJG)) // охотник на драконов
|| (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(GornNW_vor_DJG)) // охотник на драконов в лагере наемников
|| (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(GornNW_nach_DJG)) // охотник на драконов в 6 главе
|| (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Gorn_DI))) // на острове драконов
{
var int randy;
randy = Hlp_Random(2);
// если вероятность 0.5
if(randy == 0)
{
// агрессор говорит жертве (SVM фраза) "С тобой покончено, скотина!"
B_Say(self,other,"$ADDON_MONSTERKILLED");
}
else
{
// агрессор говорит жертве (SVM фраза) "Одной тварью меньше!"
B_Say (self,other,"$MONSTERKILLED");
};
}
else
{
// агрессор говорит жертве (SVM фраза) "С тобой покончено, скотина!"
B_Say(self,other,"$ADDON_MONSTERKILLED");
};
}
else // другие голоса
{
// агрессор говорит жертве (SVM фраза) "Одной тварью меньше!"
B_Say(self,other,"$MONSTERKILLED");
};
}
else // иначе (жертва убита ГГ)
{
// ГГ говорит жертве (SVM фраза) "Хорошая работа - одной тварью меньше!"
B_Say(self,other,"$GOODMONSTERKILL");
};
};
return;
};
// если агрессор атаковал вора
if(self.aivar[AIV_ATTACKREASON] == AR_Theft)
{
// агрессор говорит жертве (SVM фраза) "И не пытайся больше обокрасть меня!"
B_Say(self,other,"$THIEFDOWN");
return;
};
// агрессор атаковал ГГ, вскрывшего его сундук
if(self.aivar[AIV_ATTACKREASON] == AR_UseMob)
{
// агрессор говорит жертве (SVM фраза) "В следующий раз не советую тебе шарить по чужим вещам!"
B_Say(self,other,"$RUMFUMMLERDOWN");
return;
};
// если агрессор атаковал убийцу овец
if (self.aivar[AIV_ATTACKREASON] == AR_SheepKiller)
{
// если жертва человек
if(other.guild < GIL_SEPERATOR_HUM)
{
// агрессор говорит жертве (SVM фраза) "Никогда больше не делай этого! Это же наши овцы!"
B_Say(self,other,"$SHEEPATTACKERDOWN");
}
else // иначе (жертва монстр)
{
// агрессор говорит жертве (SVM фраза) "Одной тварью меньше!"
B_Say(self,other,"$MONSTERKILLED");
};
return;
};
// если агрессор атаковал человека, убившего другого человека
if(self.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman)
{
// если жертва не убита
if(!Npc_IsDead(other))
{
// если последняя атакованная цель и есть жертва
if(self.aivar[AIV_LASTTARGET] == Hlp_GetInstanceID(other))
{
// агрессор говорит жертве (SVM фраза) "Умри, убийца!"
B_Say(self,other,"$KILLMURDERER");
}
else // иначе
{
// агрессор говорит жертве (SVM фраза) "Да, убей эту свинью!"
B_Say(self,other,"$GOODKILL");
};
}
else // иначе (жертва убита)
{
// агрессор говорит жертве (SVM фраза) "Ты это заслужил, подлец!"
B_Say(self,other,"$ENEMYKILLED");
};
return;
};
// если агрессор помогает убить монстра
if(self.aivar[AIV_ATTACKREASON] == AR_MonsterVsHuman)
{
// если голос агрессора 9 или 12
if(self.voice == 9) || (self.voice == 12)
{
// агрессор говорит жертве (SVM фраза) "С тобой покончено, скотина!"
B_Say(self,other,"$ADDON_MONSTERKILLED");
}
else // иначе (другие голоса)
{
// агрессор говорит жертве (SVM фраза) "Одной тварью меньше!"
B_Say(self,other,"$MONSTERKILLED");
};
return;
};
// если охрана ворот атакует монстра
if(self.aivar[AIV_ATTACKREASON] == AR_MonsterCloseToGate)
{
// агрессор говорит жертве (SVM фраза) "Тупоголовая скотина!"
B_Say(self,other,"$STUPIDBEASTKILLED");
return;
};
// если агрессор реагировал на повреждение (на него напали первым)
if(self.aivar[AIV_ATTACKREASON] == AR_ReactToDamage)
{
// агрессор говорит жертве (SVM фраза) "Больше никогда не спорь со мной!"
B_Say(self,other,"$NEVERHITMEAGAIN");
return;
};
// если агрессор реагировал на обнаженное оружие
if(self.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon)
{
// агрессор говорит жертве (SVM фраза) "Это будет тебе уроком!"
B_Say(self,other,"$YOUBETTERSHOULDHAVELISTENED");
return;
};
// если агрессор реагировал на вход в его помещение или вызвана охраны для защиты помещения
if(self.aivar[AIV_ATTACKREASON] == AR_ClearRoom) || (self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToRoom)
{
// если ГГ находится в помещении, принадлежащем агрессору
if(C_NpcIsBotheredByPlayerRoomGuild(self))
{
// агрессор говорит жертве (SVM фраза) "А теперь убирайся отсюда!"
B_Say(self,other,"$GETUPANDBEGONE");
}
else // иначе (вне помещения)
{
// агрессор говорит жертве (SVM фраза) "И чтоб я больше тебя здесь не видел!"
B_Say(self,other,"$NEVERENTERROOMAGAIN");
};
return;
};
// если причина атаки - ГГ в помещении с ограниченным доступом
if(self.aivar[AIV_ATTACKREASON] == AR_LeftPortalRoom)
{
// агрессор говорит жертве (SVM фраза) "И чтоб я больше тебя здесь не видел!"
B_Say(self,other,"$NEVERENTERROOMAGAIN");
return;
};
// если охрана ворот атакует незваного гостя
if(self.aivar[AIV_ATTACKREASON] == AR_GuardStopsIntruder)
{
// агрессор говорит жертве (SVM фраза) "Умри, подлец!"
B_Say(self,other,"$KILLENEMY");
return;
};
// если охрана прекратила атаковать преступника
if(self.aivar[AIV_ATTACKREASON] == AR_GuardStopsFight)
{
// если жертва наемник или охотник на драконов
if(other.guild == GIL_SLD) || (other.guild == GIL_DJG)
{
// молчат
}
else // иначе
{
// агрессор говорит жертве (SVM фраза) "Борьбы здесь не будет, ясно!? Заруби это себе на носу!"
B_Say(self,other,"$THEREISNOFIGHTINGHERE");
};
return;
};
// если вызвана охрана по факту воровства
if(self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToThief)
{
// агрессор говорит жертве (SVM фраза) "В следующий раз не советую тебе шарить по чужим вещам!"
B_Say(self,other,"$RUMFUMMLERDOWN");
return;
};
return;
};


// ********************************
// Комментарий причины атаки
// --------------------------------
// self - агрессор, other - жертва
// ********************************


func void B_Say_AttackReason()
{
// если гильдии агрессора и жертвы не враждебны и жертва враждебна агрессору
if(Wld_GetGuildAttitude(self.guild,other.guild) != ATT_HOSTILE) && (Npc_GetAttitude(self,other) == ATT_HOSTILE)
{
// если причина атаки - убийство ГГ НПС
if(self.aivar[AIV_ATTACKREASON] == AR_KILL)
{
return;
};
// агрессор говорит жертве (SVM фраза) "Я тебя сейчас убью!"
B_Say_Overlay(self,other,"$IGETYOUSTILL");
return;
};
// если жертва враг гильдии агрессора
if(self.aivar[AIV_ATTACKREASON] == AR_GuildEnemy)
{
// если агрессор член партии ГГ
if(self.aivar[AIV_PARTYMEMBER] == TRUE)
{
var int rnd;
rnd = Hlp_Random(100);
// если вероятность 0.85
if(rnd > 15)
{
return;
};
};
// если жертва человек
if(other.guild < GIL_SEPERATOR_HUM)
{
// если ГГ переодетый бандит
if(C_PlayerIsFakeBandit(self,other) == TRUE)
{
// агрессор говорит жертве (SVM фраза) "Умри, грязный бандюга!"
B_Say_Overlay(self,other,"$ADDON_DIEBANDIT");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
}
// иначе, если ГГ переодетый пират
else if(C_PlayerIsFakePirate(self,other) == TRUE)
{
// агрессор говорит жертве (SVM фраза) "Я тебя прикончу, Пират!"
B_Say_Overlay (self,other, "$ADDON_DIRTYPIRATE");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
}
else // иначе
{
// агрессор говорит жертве (SVM фраза) "Теперь твоя очередь!"
B_Say_Overlay(self,other,"$DIEENEMY");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
};
}
else // иначе (жертва монстр)
{
// если голос агрессора 9
if(self.voice == 9)
{
var int random;
random = Hlp_Random(3);
if(random < 1)
{
// агрессор говорит жертве (SVM фраза) "Тут снова крутится одна из этих тварей!"
B_Say_Overlay(self,other,"$DIEMONSTER");
}
else if(random == 1)
{
// агрессор говорит жертве (SVM фраза) "Снова одна из этих тварей!"
B_Say_Overlay(self,other,"$ADDON_DIEMONSTER");
}
else
{
// агрессор говорит жертве (SVM фраза) "Вот опять одна из тварюг!"
B_Say_Overlay(self,other,"$ADDON_DIEMONSTER2");
};
}
else // иначе (другие голоса)
{
// агрессор говорит жертве (SVM фраза) "Тут снова крутится одна из этих тварей!"
B_Say_Overlay(self,other,"$DIEMONSTER");
};
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
};
return;
};
// если агрессор атакует вора
if(self.aivar[AIV_ATTACKREASON] == AR_Theft)
{
// агрессор говорит жертве (SVM фраза) "Погоди у меня, гадкий воришка!"
B_Say_Overlay(self,other,"$DIRTYTHIEF");
return;
};
// если агрессор атакует грабителя сундуков
if(self.aivar[AIV_ATTACKREASON] == AR_UseMob)
{
// агрессор говорит жертве (SVM фраза) "Руки прочь!"
B_Say_Overlay(self,other,"$HANDSOFF");
return;
};
// если агрессор атакует убийцу овец
if(self.aivar[AIV_ATTACKREASON] == AR_SheepKiller)
{
// если жертва человек
if(other.guild < GIL_SEPERATOR_HUM)
{
// агрессор говорит жертве (SVM фраза) "Этот подлец убивает наших овец!"
B_Say_Overlay(self,other,"$SHEEPKILLER");
}
else // иначе (жертва монстр)
{
// агрессор говорит жертве (SVM фраза) "Эта проклятая тварь сжирает наших овец!"
B_Say_Overlay(self,other,"$SHEEPKILLERMONSTER");
};
return;
};

// если агрессор атакует человека, убившего человека
if(self.aivar[AIV_ATTACKREASON] == AR_HumanMurderedHuman)
{
// агрессор говорит жертве (SVM фраза) "Убийца!"
B_Say_Overlay(self,other,"$YOUMURDERER");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
// если агрессор атакует монстра, убившего человека
if(self.aivar[AIV_ATTACKREASON] == AR_MonsterMurderedHuman)
{
// нет комментариев
return;
};
// если агрессор помогает убить монстра
if(self.aivar[AIV_ATTACKREASON] == AR_MonsterVsHuman)
{
// агрессор говорит жертве (SVM фраза) "Тут снова крутится одна из этих тварей!"
B_Say_Overlay(self,other,"$DIEMONSTER");
// агрессор посылает восприятие нападения
Npc_SendPassivePerc(self,PERC_ASSESSFIGHTSOUND,self,other);
return;
};
// если охрана ворот атакует монстра
if (self.aivar[AIV_ATTACKREASON] == AR_MonsterCloseToGate)
{
// агрессор говорит жертве (SVM фраза) "Тут не пройдет ни одна тварь!"
B_Say_Overlay(self,other,"$DIESTUPIDBEAST");
return;
};
// если на агрессора напали
if(self.aivar[AIV_ATTACKREASON] == AR_ReactToDamage)
{
// напавший монстр
if(other.guild > GIL_SEPERATOR_HUM)
{
// агрессор говорит жертве (SVM фраза) "Ты получил, что хотел!"
B_Say_Overlay(self,other,"$YOUASKEDFORIT");
return;
}
else // иначе (человек)
{
// агрессор говорит жертве (SVM фраза) "Ты у меня дождешься, подлец!"
B_Say_Overlay(self,other,"$YOUDAREHITME");
return;
};
};
// если агрессор среагировал нп обнаженное оружие
if(self.aivar[AIV_ATTACKREASON] == AR_ReactToWeapon)
{
// агрессор говорит жертве (SVM фраза) "Ты получил, что хотел!"
B_Say_Overlay(self,other,"$YOUASKEDFORIT");
return;
};
// если агрессор реагировал на вход в его помещение
if(self.aivar[AIV_ATTACKREASON] == AR_ClearRoom)
{
// агрессор говорит жертве (SVM фраза) "Тогда я должен тебя поколотить!"
B_Say_Overlay(self,other,"$THENIBEATYOUOUTOFHERE");
return;
};
// если причина атаки - ГГ в помещении с ограниченным доступом
if(self.aivar[AIV_ATTACKREASON] == AR_LeftPortalRoom)
{
// агрессор говорит жертве (SVM фраза) "Чего это ты там ищешь, ей!"
B_Say_Overlay(self,other,"$WHATDIDYOUDOINTHERE");
return;
};
// если охрана прекратила атаковать преступника
if(self.aivar[AIV_ATTACKREASON] == AR_GuardStopsFight)
{
// агрессор говорит жертве (SVM фраза) "Вы хотите с этим покончить по-хорошему?!"
B_Say_Overlay(self,other,"$WILLYOUSTOPFIGHTING");
return;
};
// если вызвана охрана по факту воровства
if(self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToThief)
{
return;
};
// если вызвана охраны для защиты помещения
if(self.aivar[AIV_ATTACKREASON] == AR_GuardCalledToRoom)
{
return;
};
return;
};
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу