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

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

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

MaGoth

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

Вложения

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

Oxbow

Участник форума
Регистрация
22 Дек 2017
Сообщения
265
Благодарности
33
Баллы
200
Oxbow, замеи вот так:
Daedalus:
class C_Trigger
{
  var int Delay;
  var int Enabled;
  var int AIVariables[16];
};
   
instance SelfTrigger (C_Trigger) {};
var int WolfSoul_Used;
Daedalus:
func void Start_Trigger_Attribute_TimeBonus(var c_npc slf,var int attribute,var int value,var int time)
{
    SelfTrigger = Oxbow_Cycle_Func("Trigger_Attribute_TimeBonus", 1000, slf, null, null);
     SelfTrigger.AIVariables[0] = time;
    SelfTrigger.AIVariables[1] = attribute;
     SelfTrigger.AIVariables[2] = value;
    WolfSoul_Used = false;
   
};


func int Trigger_Attribute_TimeBonus()
{  
    if(WolfSoul_Used == false)
   {
        if (Npc_HasItems(hero,ItPo_Bonus_Active) == true)
        {
            AI_Wait(hero,3);
            AI_PlayAni(self,"S_FIRE_VICTIM");
            Wld_PlayEffect("VOB_MAGICBURN",hero,hero,0,0,0,FALSE);
            B_Say(self,self,"$Dead");
            AI_StopFX(self,"VOB_MAGICBURN");
            Npc_ChangeAttribute(self,ATR_HITPOINTS,-self.attribute[ATR_HITPOINTS_MAX]);
            Npc_StopAni(self,"S_FIRE_VICTIM");
        };
        if (Npc_HasItems(hero,ItPo_Bonus_Active) == false)
        {
            B_RaiseAttribute(self,SelfTrigger.AIVariables[1],SelfTrigger.AIVariables[2]);
            CreateInvItem(self,ItPo_Bonus_Active);
        };
        WolfSoul_Used = true;
    };

    SelfTrigger.AIVariables[0] -= 1;
   
    if (SelfTrigger.AIVariables[0] <= 0)
    {
        B_RaiseAttribute(self,SelfTrigger.AIVariables[1], -SelfTrigger.AIVariables[2]);
        Npc_RemoveInvItems(hero,ItPo_Bonus_Active,1);
        return LOOP_END;
    };  

    return LOOP_CONTINUE;
};
 

Вложения

  • Ошибка1.png
    Ошибка1.png
    2,9 KB · Просмотры: 13

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
MW 7, А я чо? я ни чо.
так то да...
Oxbow, везде сделай self за место hero, и переменные Attribute_TimeBonus и Protection_TimeBonus где-то используются? Из приведенный тобой кодов я не увидел, по этому удалил. Возможно на них ругается...
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
969
Баллы
295
если зелья эксклюзивное для героя тогда в коде надо использовать hero и делать данный триггер глобальным, как рекомендовал Гратт.
 

Oxbow

Участник форума
Регистрация
22 Дек 2017
Сообщения
265
Благодарности
33
Баллы
200
MEG@VOLT вырубается при сохранении, загрузке и "новой игре" (если запущен триггер). Еще вырубается если добавить return LOOP_END; к смерти героя от выпивания второго зелья подряд.
Задолбали меня эти триггеры, зелья. Спасибо за помощь MEG@VOLT, MW 7 . Займусь пожалуй заклинанием "Каменные кулаки" и состояниями в папке ZS_Magic. Еще бы понять как рабоатет заклинание Свет.
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
969
Баллы
295
Oxbow, а тригеры то тут при чём? у тебя же непонятная версия и что бы запустить тригеры вы накидываете что то ещё.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Oxbow, установи 1.0m
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
969
Баллы
295
Давайте подэтожим по зельям на триггерах:
  • для работы триггеров нужен последний юнион + зпарсер;
  • зелья на триггерах можно реализовать отдельным проектом, в таком случае в основной проект добавляются сами зелья, а в папку авторан функции USE** и функции триггеров;
  • можно всё сделать в рамках одного проекта, в таком случае компилировать проект надо будет движком.

***
от себя добавлю, что я эти зелья на триггерах написал год назад, потом дважды переписал согласно рекомендациям Гратта, потом сделал отдельную тему про триггеры всё проживав еще раз. Потом из вредности скомпилировал проект движком, потом батник написал что бы компилировать движком удобнее/понятнее было. Всё проверено многократно и всё работает. Ставьте свежий юнион и в светлое будущее :)
 
Последнее редактирование:

Oxbow

Участник форума
Регистрация
22 Дек 2017
Сообщения
265
Благодарности
33
Баллы
200
Подскажите функция
Daedalus:
    EquipItem(hero,ITAR_WND_STONEHANDS);
не работает в процессе игры?
Предмет просто помечается красным (одет), но на персонаже не отображается.
Можно как-то это исправить?
 

MEG@VOLT

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

Oxbow

Участник форума
Регистрация
22 Дек 2017
Сообщения
265
Благодарности
33
Баллы
200

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
969
Баллы
295
Oxbow, для брони есть внешняя функция https://worldofplayers.ru/threads/37749/

void AI_EquipBestArmor (c_npc self); - в инвентаре НПС self ищутся и одеваются самые лучшие доспехи.
void AI_UnequipArmor (c_npc self); - одетые доспехи НПС self убираются в инвентарь.
void AI_EquipArmor (c_npc self, int armor); - НПС self одевает доспехи armor, которые должны находиться в его инвентаре.**
 
Последнее редактирование:

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
118
Благодарности
3
Баллы
40
Вопрос такой: Мой Нпс часто тупит при попытке проткнуть оппонента. Я, как исал выше, пытался сделать так, чтобы он протыкал человека сразу после того, как вырубил и вроде получилось, но вот, как говорю, тупит. Кидаю весь ZS_Attack. Мой код, как смог, выделил:
Daedalus:
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)
        {
            if((Hlp_GetInstanceID(other) == Hlp_GetInstanceID(nikita)) && !Npc_IsPlayer(self))
            {
                self.flags = 0;
            };
            if((Hlp_GetInstanceID(self) == Hlp_GetInstanceID(nikita)) && !Npc_IsPlayer(other))
            {
                other.flags = 0;
            };
            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)) && (C_NpcIsDown(other)) && (Hlp_GetInstanceID(self) == Hlp_GetInstanceID(Nikita)))
        {
            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);
            };
        };
-------------------------------------------------------------------------------------------------------------------------------------------------
        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;
        };
    };
};
Пост автоматически объединён:

Еще вопрос по поводу кругов магии. Я хотел создать новый круг, все вроде добавил, но единственное, что не поменялось, это цифра в информации об игроке. То есть перс вроде выучил новый круг, но цифра не меняется. У меня такое чувство, что это прописано в SetTalentSkills() функции, которую, вроде как, изменить нельзя. Так ли это?
 
Последнее редактирование модератором:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.001
Благодарности
969
Баллы
295
Мой Нпс часто тупит при попытке проткнуть оппонента. Я, как исал выше, пытался сделать так, чтобы он протыкал человека сразу после того, как вырубил и вроде получилось, но вот, как говорю, тупит.
после ФинишМув делай выход из loop цикла.

B_FinishingMove(self, other);
return LOOP_END;


**

То есть перс вроде выучил новый круг, но цифра не меняется.
цифра не меняется где? в меню? или герой не может использовать новые руны "7" круга? или не проходят проверки в кондишион диалогов?

RPD, пиши пожалуйста так что бы было понятно другим. тяжело угадывают что именно ты имеешь ввиду.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Я хотел создать новый круг, все вроде добавил, но единственное, что не поменялось, это цифра в информации об игроке.
Нужно править переменную в массиве TXT_TALENTS_SKILLS. Как минимум.

Наверное, правильным будет всё-таки переход к поиску нового противника. Если завершить атаку, то атакующий, возможно, сделает какие-то лишние телодвижения, прежде чем обнаружит нового противника и начнёт его атаковать.

Эта функция возвращает TRUE и в случае, если противник уже мёртв. То есть, когда добивание не требуется.

Кстати, эта функция также возвращает FALSE, когда противник лежит, после падения (BS_LIE). Это может произойти, если противник получил удар от голема или тролля или просто упал с возвышенности. Монстры не умеют добивать противника, а могло бы быть эффектно - тролль растоптал сбитого с ног противника.
*gothic_troll_punch*
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
118
Благодарности
3
Баллы
40
Нужно править переменную в массиве TXT_TALENTS_SKILLS. Как минимум.
Спасибо, именно этого не сделал.
Наверное, правильным будет всё-таки переход к поиску нового противника. Если завершить атаку, то атакующий, возможно, сделает какие-то лишние телодвижения, прежде чем обнаружит нового противника и начнёт его атаковать.
То есть LOOP_CONTINUE?
Пост автоматически объединён:

Еще нпс почему то часто роняет свой меч после добиваний, потом, конечно же, не поднимает. Возможно, это связано с функцией B_FinishingMove? В ней прописывается взятие ржавого меча. А вообще не получается отследить, когда именно роняет. Всегда по разному

И может тогда будет лучше заменить C_NpcIsDown(other) на Npc_IsInState(other,ZS_Unconscious)?
Пост автоматически объединён:

Сейчас поэкспериментировав немного с боями заметил, что мой нпс обычно станится, когда протыкает кого-то и в процессе в него прилетает, к примеру, огненный шар. Он в итоге не добивает и сам не двигается, пока его кто нибудь не ударит и не отвлечет
 
Последнее редактирование:

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
То есть LOOP_CONTINUE?
Попробуй. Если что-то не так, то нужно будет прописывать поиск новой цели сразу после добивания.

И может тогда будет лучше заменить C_NpcIsDown(other) на Npc_IsInState(other,ZS_Unconscious)?
Это зависит от того, может ли сложиться ситуация, когда противник твоего Никиты будет кем-то усыплён. Если такая ситуация возможна, то нужна проверка на состояние магического сна.

Еще нпс почему то часто роняет свой меч после добиваний, потом, конечно же, не поднимает.
Дичь какая-то. :eek:
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
118
Благодарности
3
Баллы
40
Вот правда берет и роняет. И вообще после добиваний у него два меча, либо уже один, если прошлый, который есть у него изначально, уронил.



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);
};


В скрипте прописан этот новый меч
Пост автоматически объединён:

Я вот даже нормально не объясню. Вот идет какая-то анимация, например движение руками и головой при монологе после убийства и раз - меч падает на землю
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Спорное решение, как по мне. Я бы у себя такое выпилил нахрен. Не логично ни разу. Но в твоём случае нужно разбираться, почему не фиксируется нахождение в режиме ближнего боя FMODE_MELEE? Попробуй убрать болтовню.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
RPD,
Смотри гифку.
AI_FinishingMove - это что? от куда взялося?
 

Вложения

  • GIF 12.12.2023 17-17-08.gif
    GIF 12.12.2023 17-17-08.gif
    1,4 MB · Просмотры: 8
Сверху Снизу