Уважаемые гости и новички, приветствуем Вас на нашем форуме
Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».
Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
не, ничего не меняется. Все равно как берет в руки призыв - сразу начинает его бесконечно перебирать (как будто система считает, что каст уже завершен и просто сразу вызывает return true), либо тормозить и держать в руках просто.
RPD, переписал. всё работает. файл в скрепке. Что у тебя там было в спеллкаст не знаю, поэтому сделал их лайтовыми для теста.
Daedalus:
func int B_SelectSpellNikita(var C_NPC slf, var C_NPC oth)
{
if (slf.guild != GIL_NIK) { return false; };
if (Npc_IsDrawingWeapon(slf)) { return TRUE;/*nichts tun wenn gerade am waffe ziehen*/ };
var int rand;
if (slf.aivar[AIV_SelectSpell] != rand)
{
// Without your television
rand = Hlp_Random(100) + 1;
slf.aivar[AIV_SelectSpell] = rand;
};
if (rand > 95)
{
return B_ReadyRune(slf, oth, ItRu_SumNik);
};
if (rand > 80)
{
var c_npc npc;
npc = Hlp_GetNpc(Nikita_for_Npc);
if (!Hlp_IsValidNpc(npc))
{
// можно добавить доп проверки на расстояние или смерть
return B_ReadyRune(slf, oth, ItRu_SumNik);
};
};
return B_ReadyRune(slf, oth, ItRu_PierceArrow);
};
MEG@VOLT, в Spell_Cast_Summon*** перезаписывается self после вызова Wld_SpawnNpcRange , поэтому self.aivar[AIV_SelectSpell] += 1; надо обновлять ДО Wld_Spawn ;-)
RPD, переписал. всё работает. файл в скрепке. Что у тебя там было в спеллкаст не знаю, поэтому сделал их лайтовыми для теста.
Daedalus:
func int B_SelectSpellNikita(var C_NPC slf, var C_NPC oth)
{
if (slf.guild != GIL_NIK) { return false; };
if (Npc_IsDrawingWeapon(slf)) { return TRUE;/*nichts tun wenn gerade am waffe ziehen*/ };
var int rand;
if (slf.aivar[AIV_SelectSpell] != rand)
{
// Without your television
rand = Hlp_Random(100) + 1;
slf.aivar[AIV_SelectSpell] = rand;
};
if (rand > 95)
{
return B_ReadyRune(slf, oth, ItRu_SumNik);
};
if (rand > 80)
{
var c_npc npc;
npc = Hlp_GetNpc(Nikita_for_Npc);
if (!Hlp_IsValidNpc(npc))
{
// можно добавить доп проверки на расстояние или смерть
return B_ReadyRune(slf, oth, ItRu_SumNik);
};
};
return B_ReadyRune(slf, oth, ItRu_PierceArrow);
};
MEG@VOLT, в Spell_Cast_Summon*** перезаписывается self после вызова Wld_SpawnNpcRange , поэтому self.aivar[AIV_SelectSpell] += 1; надо обновлять ДО Wld_Spawn ;-)
Давно хотел сказать, что это почти полностью решило проблему застреваний при касте, либо переборки в руках, спеллов. Иногда случается, но это небо и земля по сравнению с тем, что было. Спасибо!
Я хотел бы сделать так, чтобы при закликивании НПС он мог что то типа взорваться, нанести урон и оглушить ненадолго противников. То есть отслеживать тот момент когда непись получает кучу ударов и сам ни одного не наносит, ну или редко. И вызывать функцию этого взрыва. Можно как то реализовать?
первая это скрипт "взрыва", тут проще всего прописать какое то простое zs_состояние для жертв и перевести их в него через AI_SetNpcsToState.
второе это какой то скрипт-счётчик который будет понимать что НПС "закликан" и вызвать скрипт "взрыва". что такое "заклинивание" я не знаю так как ни играл ни разу в Готику с мышкой.
первая это скрипт "взрыва", тут проще всего прописать какое то простое zs_состояние для жертв и перевести их в него через AI_SetNpcsToState.
второе это какой то скрипт-счётчик который будет понимать что НПС "закликан" и вызвать скрипт "взрыва". что такое "заклинивание" я не знаю так как ни играл ни разу в Готику с мышкой.
в B_AssessDamage считать кол-во ударов записывая их в отдельный аивер НПС, а в ZS_Attack_Loop данный аивер обнулять каждые условно две секунды, если при этом цифра была высокая то запускать скрипт "взрыва".
в B_AssessDamage считать кол-во ударов записывая их в отдельный аивер НПС, а в ZS_Attack_Loop данный аивер обнулять каждые условно две секунды, если при этом цифра была высокая то запускать скрипт "взрыва".
Могу порекомендовать приём, помогающий найти причину не такого результата работы функций ИИ, какого тебе хотелось бы. Поскольку функции ИИ работают очень быстро, а внутри этих функций есть масса проверяемых условий, как правило, бывает трудно понять, какое из этих условий мешает получить нужный результат. И даже, в какой функции это условие находится. Разобраться помогает временное введение в функции ИИ строчек с выводом текстовых сообщений на экран. Это может быть название функции, чтобы убедиться, вызывается ли функция вообще. Это может быть надпись типа "Условие 1", "Условие 2" и т. д., чтобы понять, какое условие срабатывает, и это приводит к завершению работы функции. Это может быть значение аргументов функции или переменных. Например, при выборе заклинания в Г2 меняется значение переменной, определяющее очередь заклинаний. Зависание может быть связано с конкретным значением этой переменной.
Могу порекомендовать приём, помогающий найти причину не такого результата работы функций ИИ, какого тебе хотелось бы. Поскольку функции ИИ работают очень быстро, а внутри этих функций есть масса проверяемых условий, как правило, бывает трудно понять, какое из этих условий мешает получить нужный результат. И даже, в какой функции это условие находится. Разобраться помогает временное введение в функции ИИ строчек с выводом текстовых сообщений на экран. Это может быть название функции, чтобы убедиться, вызывается ли функция вообще. Это может быть надпись типа "Условие 1", "Условие 2" и т. д., чтобы понять, какое условие срабатывает, и это приводит к завершению работы функции. Это может быть значение аргументов функции или переменных. Например, при выборе заклинания в Г2 меняется значение переменной, определяющее очередь заклинаний. Зависание может быть связано с конкретным значением этой переменной.
Возможно, здесь получится задействовать таймер отказа от диалога RefuseTalk.
Я так понимаю, что B_AssessDamage() вызывается после каждого удара, тогда проблем с отслеживанием нет, но как запускать некий таймер? И сбрасывать. Есть ли какие-то функции подходящие?
// установить счетчик отказа от диалога для НПС npc на timeSec секунд.
func void Npc_SetRefuseTalk(var C_NPC npc, var int timeSec);
// проверить, истек ли счетчик отказа от диалога для НПС npc,
// возвращает TRUE, если счетчик не истек, иначе – FALSE.
func int Npc_RefuseTalk(var C_NPC npc);
Получил удар, проверил, установлен ли таймер. Если таймер не установлен, устанавливаешь таймер на 2 (к примеру) секунды, счётчик ударов равен 1. Получил следующий удар, проверил, установлен ли таймер. Если таймер установлен, снова устанавливаешь таймер на 2 секунды, значение счётчика ударов увеличиваешь на 1, проверяешь, не достигло ли его значение нужной величины, при которой происходит реакция на беспрерывную атаку. Если нужное значение счётчика ударов достигнуто, сбрасываешь значение счётчика в 0, устанавливаешь таймер в 0, запускаешь реакцию. Как-то так.
// установить счетчик отказа от диалога для НПС npc на timeSec секунд.
func void Npc_SetRefuseTalk(var C_NPC npc, var int timeSec);
// проверить, истек ли счетчик отказа от диалога для НПС npc,
// возвращает TRUE, если счетчик не истек, иначе – FALSE.
func int Npc_RefuseTalk(var C_NPC npc);
Возможно, вызывается после блокирования удара. Нужно проверять.
Получил удар, проверил, установлен ли таймер. Если таймер не установлен, устанавливаешь таймер на 2 (к примеру) секунды, счётчик ударов равен 1. Получил следующий удар, проверил, установлен ли таймер. Если таймер установлен, снова устанавливаешь таймер на 2 секунды, значение счётчика ударов увеличиваешь на 1, проверяешь, не достигло ли его значение нужной величины, при которой происходит реакция на беспрерывную атаку. Если нужное значение счётчика ударов достигнуто, сбрасываешь значение счётчика в 0, устанавливаешь таймер в 0, запускаешь реакцию. Как-то так.
На данном сайте используются файлы cookie, чтобы персонализировать контент и сохранить Ваш вход в систему, если Вы зарегистрируетесь.
Продолжая использовать этот сайт, Вы соглашаетесь на использование наших файлов cookie.