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

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

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

Вопросы по скриптингу

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.371
Благодарности
7.803
Баллы
995
  • Первое сообщение
  • #1
Прежде чем задавать вопросы, ознакомьтесь с документацией..
1) Читать онлайн
2) Архив с офлайн-версией(chm) во вложении
 

Вложения

  • Vam_tutor.rar
    171,6 KB · Просмотры: 514
Последнее редактирование модератором:

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.128
Благодарности
3.220
Баллы
485
Не понятно каким образом проигрывать анимацию отброса всех атакующих. То есть сразу чтобы все отлетали, как при касте кулака ветра или удара голема
Применять ко всем атакующим урон типа DAM_FLY.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.339
Благодарности
3.183
Баллы
525
каким образом проигрывать анимацию отброса всех атакующих
Применять ко всем атакующим урон типа DAM_FLY.
Да, урон типа DAM_FLY отбросит неписей, но здесь возникает вопрос, как его применить. Вариант 1 - можно попробовать создать заклинание с соответствующим типом урона, действующее по площади, аналогично Ледяной волне, например. При этом заклинание должен будет кастануть избиваемый непись, а для этого ему нужно будет предписать сменить оружие и выбрать нужное заклинание. Это связано с затратами времени и эффектом прерывания каста при получении очередного повреждения. Вариант 2 - можно попробовать нанести урон из скриптов с помощью функции Wld_PlayEffect. Кажется, там есть соответствующий аргумент. Нет сейчас скриптов и Соурсера под рукой, не могу проверить. В этом варианте не совсем понятно, будет ли правильно определяться направление отбрасывания неписей.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
Да, урон типа DAM_FLY отбросит неписей, но здесь возникает вопрос, как его применить. Вариант 1 - можно попробовать создать заклинание с соответствующим типом урона, действующее по площади, аналогично Ледяной волне, например. При этом заклинание должен будет кастануть избиваемый непись, а для этого ему нужно будет предписать сменить оружие и выбрать нужное заклинание. Это связано с затратами времени и эффектом прерывания каста при получении очередного повреждения. Вариант 2 - можно попробовать нанести урон из скриптов с помощью функции Wld_PlayEffect. Кажется, там есть соответствующий аргумент. Нет сейчас скриптов и Соурсера под рукой, не могу проверить. В этом варианте не совсем понятно, будет ли правильно определяться направление отбрасывания неписей.
А как именно называется этот нужный эффект?
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.339
Благодарности
3.183
Баллы
525
А как именно называется этот нужный эффект?
Возможно, ещё никак, и его нужно создать в скриптах визуальных эффектов. Или можно использовать существующий уже эффект. Нужно посмотреть в скриптах визуальных эффектов, какие эффекты используются при касте заклинания Кулак Шторма. Там по каждому заклинанию есть ряд инстанций, в том числе и эффект, применяемый к жертве заклинания.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
Возможно, ещё никак, и его нужно создать в скриптах визуальных эффектов. Или можно использовать существующий уже эффект. Нужно посмотреть в скриптах визуальных эффектов, какие эффекты используются при касте заклинания Кулак Шторма. Там по каждому заклинанию есть ряд инстанций, в том числе и эффект, применяемый к жертве заклинания.
Точняк, щас посмотрю. Пробовал брать механику с активацией восприятия урона от жертвы соседа, но логика что-то прям сложно конструируется. Никак не допру как правильнее реализовать
 
Последнее редактирование:

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
Точняк, щас посмотрю. Пробовал брать механику с активацией восприятия урона от жертвы соседа, но логика что-то прям сложно конструируется. Никак не допру как правильнее реализовать
В общем я не нашел этот эффект, к сожалению. Думаю, как лучше реализовать вообще срабатывание именно отброса всех от нпс после срабатывания скрипта. То есть может создать восприятие на урон соседу и как то активировать там или может есть варинт получше?
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275
как лучше реализовать вообще срабатывание именно отброса всех от нпс после срабатывания скрипта.
скрипт "взрыва", тут проще всего прописать какое то простое zs_состояние для жертв и перевести их в него через AI_SetNpcsToState.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
скрипт "взрыва", тут проще всего прописать какое то простое zs_состояние для жертв и перевести их в него через AI_SetNpcsToState.
но как мне получить всех этих жертв?то есть в B_AccessDamage у меня срабатывает скрипт взрыва иself там именно nikita, но я не думаю, что оттуда можно получить всех victim сразу
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275
ты можешь для теста сначала перевести всех в радиусе в состояние сна через AI_SetNpcsToState . если тест тебя удовлетворит то уже писать новое zs_состояние в котором наносить урон флай и прочее
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
ты можешь для теста сначала перевести всех в радиусе в состояние сна через AI_SetNpcsToState . если тест тебя удовлетворит то уже писать новое zs_состояние в котором наносить урон флай и прочее
еще вопрос. как этот урон флай собственно наносить? Функция есть?
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275
еще вопрос. как этот урон флай собственно наносить? Функция есть?
Код:
// ГГ посылает в Npc self "Огненный шар" с уроном от нокаута
 Wld_PlayEffect("spellFX_ChargeFireball", PC_Hero, self, 1, 250, DAM_FLY, FALSE);
подробнее смотри на gothic-library.ru
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.339
Благодарности
3.183
Баллы
525
Кстати, а нельзя ли здесь в качестве эффекта указать пустую строку? В случае с отбрасыванием визуализация эффекта не обязательна, хотя что-то там всё таки должно быть. Анимация отбрасывающего, например.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
она и так будет.

наверное можно. там под каждый отдельный случай надо тестить :)
У меня как получилось: отбрасывает, но далеко не всегда. Например не отбрасывает при битве с небольшим колличеством горожан, но при этом если огромной кучей навалятся - срабатывает обычно. что то мне кажется у меня условие ломанное:
Daedalus:
func int B_BlastTimer(var C_NPC slf, var C_NPC oth)
{
    if(!Npc_RefuseTalk(slf))
    {
        Npc_SetRefuseTalk(slf, 5);
 
        slf.aivar[AIV_BlastCount] = 0;
    }
    else
    {
        if(slf.aivar[AIV_BlastCount] == 10)
        {
            AI_SetNpcsToState(slf,ZS_Blast,300);
  
            PrintScreen("Взрыв!",-1,-1,"FONT_OLD_20_WHITE.TGA",1);
  
            Npc_SetRefuseTalk(slf, 1);
  
            slf.aivar[AIV_BlastCount] = 0;
  
            return true;
        };
    };
 
    slf.aivar[AIV_BlastCount] += 1;
 
    return false;
};

Daedalus:
func void B_AssessDamage()
{
    if(self.guild == GIL_NIK)
    {
        B_BlastTimer(self, other);
 
        return;
    };
  --------------

ZS_BLAST:

Daedalus:
func void B_StopBlast()
{
    Npc_PercEnable(self,PERC_ASSESSMAGIC,B_AssessMagic);
    Npc_ClearAIQueue(self);
    AI_Standup(self);
    if(self.guild < GIL_SEPERATOR_HUM)
    {
        B_AssessDamage();
        AI_ContinueRoutine(self);
    }
    else
    {
        Npc_SetTempAttitude(self,ATT_HOSTILE);
        AI_ContinueRoutine(self);
    };
};

func void ZS_Blast()
{
    Npc_PercEnable(self,PERC_ASSESSSTOPMAGIC,B_StopBlast);
 
    if(!Npc_HasBodyFlag(self,BS_FLAG_INTERRUPTABLE))
    {
        AI_Standup(self);
    }
    else
    {
        AI_StandupQuick(self);
    };
    if(self.guild < GIL_SEPERATOR_HUM)
    {
        AI_PlayAni(self,"T_STAND_2_LIGHTNING_VICTIM");
    };
    return;
};

func int ZS_Blast_Loop()
{
    Wld_PlayEffect("spellFX_Firestorm_SPREAD",Nikita,Nikita,0,0,0,false);
    Wld_PlayEffect("SPELLFX_chargeFireball",other,self,4,300,DAM_FLY,FALSE);
    PrintScreen("ZS_Blast!",-1,-1,"FONT_OLD_20_WHITE.TGA",1);
    Npc_ClearAIQueue(other);
    if(Npc_GetStateTime(self) > 7)
    {
        B_StopBlast();
    };
    return TRUE;
};

func void ZS_Blast_End()
{
};
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275
RPD, скинь свой файла ZS_Attack
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
RPD, скинь свой файла ZS_Attack
Daedalus:
func void B_AssessSurprise()
{
    Npc_SetTarget(self,other);
    self.aivar[AIV_ATTACKREASON] = AR_GuildEnemy;
};

func void ZS_Attack()
{
    if((other.guild == GIL_NIK) && (!Npc_IsPlayer(self)))
    {
        self.flags = 0;
    };
    if((self.guild == GIL_NIK) && (!Npc_IsPlayer(other)))
    {
        other.flags = 0;
    };
   
    Perception_Set_Minimal();
   
    Npc_PercEnable(self,PERC_ASSESSSURPRISE,B_AssessSurprise);
    B_ValidateOther();
    self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
    if(C_WantToFlee(self,other))
    {
        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);
    if(self.guild == GIL_NIK)
    {
        Mdl_ApplyOverlayMdsTimed(self,"HUMANS_SPRINT.MDS",300000);
    };
    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;
    self.aivar[AIV_TAPOSITION] = 0;
    self.aivar[AIV_HitByOtherNpc] = 0;
    self.aivar[AIV_SelectSpell] = 0;
};

func int ZS_Attack_Loop()
{
    B_Greg_ComesToDexter();
    Npc_GetTarget(self);
    if(Npc_GetDistToNpc(self,other) > self.aivar[AIV_FightDistCancel])
    {
        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)
        {
            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])
    {
        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)
    {
        AI_Wait(self,0.8);
        self.aivar[AIV_WaitBeforeAttack] = 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);
    };
    if((Npc_GetStateTime(self) > 2) && (self.aivar[AIV_TAPOSITION] == 0))
    {
        B_CallGuards();
        self.aivar[AIV_TAPOSITION] = 1;
    };
    if((Npc_GetStateTime(self) > 8) && (self.aivar[AIV_TAPOSITION] == 1))
    {
        B_CallGuards();
        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(self);
        }
        else
        {
            Npc_ClearAIQueue(self);
        };
        self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
        return LOOP_CONTINUE;
    }
    else
    {
        Npc_ClearAIQueue(self);
        if((Hlp_IsValidNpc(other)) && (Npc_IsInState(other,ZS_Unconscious)) && (self.guild == GIL_NIK))
        {
            if(self.aivar[AIV_PursuitEnd] == FALSE)
            {
                if(B_GetCurrentAbsolutionLevel(self) > self.aivar[AIV_LastAbsolutionLevel])
                {
                    B_Say(self,other,"$WISEMOVE");
                }
                else
                {
                    B_Say_AttackEnd();
                };
            };
            if(Npc_IsInFightMode(self,FMODE_MELEE))
            {
                B_FinishingMove(self, other);
               
                return LOOP_END;
            };  
           
            return LOOP_CONTINUE;
        };
        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);
            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
        {
            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 = 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])
        {
            B_Say(self,other,"$WISEMOVE");
        }
        else
        {
            B_Say_AttackEnd();
        };
    };
    if((other.aivar[AIV_KilledByPlayer] == TRUE) && (Wld_GetGuildAttitude(self.guild,hero.guild) != ATT_HOSTILE))
    {
        B_SetAttitude(self,ATT_FRIENDLY);
    };
    if(Npc_IsInState(other,ZS_Unconscious) && C_NpcHasAttackReasonToKill(self))
    {
        B_FinishingMove(self,other);
    };
    AI_RemoveWeapon(self);
    if(C_NpcIsDown(other) && C_WantToRansack(self) && ((other.aivar[AIV_RANSACKED] == FALSE) || C_NpcRansacksAlways(self)) && (Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT))
    {
        other.aivar[AIV_RANSACKED] = TRUE;
        if(other.guild < GIL_SEPERATOR_HUM)
        {
            AI_StartState(self,ZS_RansackBody,0,"");
            return;
        }
        else if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(AlligatorJack)) && (Npc_HasItems(other,ItFoMuttonRaw) > 0))
        {
            AI_StartState(self,ZS_GetMeat,0,"");
            return;
        };
    };
    if(self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX] / 2))
    {
        AI_StartState(self,ZS_HealSelf,0,"");
        return;
    };
};
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
76
Благодарности
2
Баллы
15
Daedalus:
func void B_AssessSurprise()
{
    Npc_SetTarget(self,other);
    self.aivar[AIV_ATTACKREASON] = AR_GuildEnemy;
};

func void ZS_Attack()
{
    if((other.guild == GIL_NIK) && (!Npc_IsPlayer(self)))
    {
        self.flags = 0;
    };
    if((self.guild == GIL_NIK) && (!Npc_IsPlayer(other)))
    {
        other.flags = 0;
    };
 
    Perception_Set_Minimal();
 
    Npc_PercEnable(self,PERC_ASSESSSURPRISE,B_AssessSurprise);
    B_ValidateOther();
    self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
    if(C_WantToFlee(self,other))
    {
        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);
    if(self.guild == GIL_NIK)
    {
        Mdl_ApplyOverlayMdsTimed(self,"HUMANS_SPRINT.MDS",300000);
    };
    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;
    self.aivar[AIV_TAPOSITION] = 0;
    self.aivar[AIV_HitByOtherNpc] = 0;
    self.aivar[AIV_SelectSpell] = 0;
};

func int ZS_Attack_Loop()
{
    B_Greg_ComesToDexter();
    Npc_GetTarget(self);
    if(Npc_GetDistToNpc(self,other) > self.aivar[AIV_FightDistCancel])
    {
        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)
        {
            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])
    {
        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)
    {
        AI_Wait(self,0.8);
        self.aivar[AIV_WaitBeforeAttack] = 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);
    };
    if((Npc_GetStateTime(self) > 2) && (self.aivar[AIV_TAPOSITION] == 0))
    {
        B_CallGuards();
        self.aivar[AIV_TAPOSITION] = 1;
    };
    if((Npc_GetStateTime(self) > 8) && (self.aivar[AIV_TAPOSITION] == 1))
    {
        B_CallGuards();
        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(self);
        }
        else
        {
            Npc_ClearAIQueue(self);
        };
        self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
        return LOOP_CONTINUE;
    }
    else
    {
        Npc_ClearAIQueue(self);
        if((Hlp_IsValidNpc(other)) && (Npc_IsInState(other,ZS_Unconscious)) && (self.guild == GIL_NIK))
        {
            if(self.aivar[AIV_PursuitEnd] == FALSE)
            {
                if(B_GetCurrentAbsolutionLevel(self) > self.aivar[AIV_LastAbsolutionLevel])
                {
                    B_Say(self,other,"$WISEMOVE");
                }
                else
                {
                    B_Say_AttackEnd();
                };
            };
            if(Npc_IsInFightMode(self,FMODE_MELEE))
            {
                B_FinishingMove(self, other);
             
                return LOOP_END;
            };
         
            return LOOP_CONTINUE;
        };
        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);
            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
        {
            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 = 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])
        {
            B_Say(self,other,"$WISEMOVE");
        }
        else
        {
            B_Say_AttackEnd();
        };
    };
    if((other.aivar[AIV_KilledByPlayer] == TRUE) && (Wld_GetGuildAttitude(self.guild,hero.guild) != ATT_HOSTILE))
    {
        B_SetAttitude(self,ATT_FRIENDLY);
    };
    if(Npc_IsInState(other,ZS_Unconscious) && C_NpcHasAttackReasonToKill(self))
    {
        B_FinishingMove(self,other);
    };
    AI_RemoveWeapon(self);
    if(C_NpcIsDown(other) && C_WantToRansack(self) && ((other.aivar[AIV_RANSACKED] == FALSE) || C_NpcRansacksAlways(self)) && (Npc_GetDistToNpc(self,other) < PERC_DIST_INTERMEDIAT))
    {
        other.aivar[AIV_RANSACKED] = TRUE;
        if(other.guild < GIL_SEPERATOR_HUM)
        {
            AI_StartState(self,ZS_RansackBody,0,"");
            return;
        }
        else if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(AlligatorJack)) && (Npc_HasItems(other,ItFoMuttonRaw) > 0))
        {
            AI_StartState(self,ZS_GetMeat,0,"");
            return;
        };
    };
    if(self.attribute[ATR_HITPOINTS] < (self.attribute[ATR_HITPOINTS_MAX] / 2))
    {
        AI_StartState(self,ZS_HealSelf,0,"");
        return;
    };
};
Изменил ZS_Blast немного. Почему-то в целом если прописывать именно инстанции в состоянии, то есть NIK_8987_Nikita, а не протсто C_Npc Nikita - то срабатывает вроде как почти всегда
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.930
Благодарности
929
Баллы
275
скрипты сиквела.

Daedalus:
func void B_InterruptMob(var string mobsi)
{
    var int randomize_mob;
    
    PrintDebugNpc(PD_TA_DETAIL,"B_InterruptMob");
    
    B_StopUseMob(self,mobsi);
    
    var int randomize_mob;  randomize_mob = Hlp_Random(7); // 0-6
    // а если выпадет ноль??


    if((randomize_mob == 1) && !C_NpcIsBoss(self))
    {
        AI_PlayAni(self,"T_BORINGKICK");
    };
    else if (randomize_mob == 2)    {   AI_PlayAni(self,"T_SEARCH");            }
    else if (randomize_mob == 3)    {   AI_PlayAni(self,"R_SCRATCHHEAD");       }
    else if (randomize_mob == 4)    {   AI_PlayAni(self,"R_LEGSHAKE");          }
    else if (randomize_mob == 5)    {   AI_PlayAni(self,"R_SCRATCHRSHOULDER");    }
    else if (randomize_mob == 6)    {   AI_PlayAni(self,"R_SCRATCHLSHOULDER");    };
    
    Npc_SetStateTime(self,0);
    
    AI_UseMob(self,mobsi,1);
    
    b_usemobitems(self,mobsi);
    
    self.aivar[AIV_DONTUSEMOB] = 1;
};

если randomize_mob будет равен нулю, то анимации не будет. так задумано или ошибка?
 
Сверху Снизу