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

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

TA Overlay

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.058
Благодарности
1.017
Баллы
315
Сегодня использовал TA Overlay для реализации процесса "ожидания" напарником пока ГГ поспит или поболтает :)

1) новое ZS_ для ожидания героя. в нём происходит удаление оверлея для напарника.
Daedalus:
// ---------------------------------
// ---------------------------------
// напарник курит и ждёт
func void ZS_SJ_FP()    {    ZS_Smoke_Joint(); };

func int ZS_SJ_FP_Loop()
{
    if (hero.aivar[AIV_INVINCIBLE] == false)
    {
        TA_RemoveOverlay(self);
        AI_ContinueRoutine(self);
    };
 
    return ZS_Smoke_Joint_Loop();
};

func void ZS_SJ_FP_End()    { ZS_Smoke_Joint_End(); };
// ---------------------------------
// ---------------------------------

тут вот в чём дело: у функции TA и Ta_min время будет устанавливаться относительно текущего. на практике это можно использовать для создания какого то расписания на несколько часов игрового времени, например работы в кузне. В моём примере ничего такого не надо, поэтому я просто сделал +12 часов.
Daedalus:
    TA_BeginOverlay(self);
        TA(self, 00,12, ZS_SJ_FP, NearestWP);
        TA(self, 12,00, ZS_SJ_FP, NearestWP);
        //TA_Min(self, 23,00, 08, 00, ZS_SJ_FP, NearestWP);
    TA_EndOverlay(self);
Игровое время 11:08
1741822583904.png
Daedalus:
func void B_SJ_FP_start()
{
    if hero.aivar[AIV_INVINCIBLE] == false  { return; };
    if self.aivar[AIV_INVINCIBLE] == true   { return; }; // герой говорит с напарником
    // если герой решил с кем то поболтать/ поспать /поработать в кузне
    var string NearestWP;
    NearestWP = Npc_GetNearestWP(self);
    Hlp_PrintConsole(Str_Format("B_SJ_FP_start[%s]:  NearestWP = %s", self.name, NearestWP));
   
    TA_BeginOverlay(self);
        TA(self, 00,12, ZS_SJ_FP, NearestWP);
        TA(self, 12,00, ZS_SJ_FP, NearestWP);
        //TA_Min(self, 23,00, 08, 00, ZS_SJ_FP, NearestWP);
    TA_EndOverlay(self);
    AI_ContinueRoutine(self);
};



включение оверлея из ZS_Follow_Player_Loop
Daedalus:
// ---------------------------------
func int ZS_Follow_Player_Loop ()
{
    B_SJ_FP_start();
    return ZS_Follow_Player_Loop_old();
};

p.s.
если может кто то проверить работу кода в ярике с командой пирата в "лагере" орков, будет очень хорошо.
 

Вложения

  • 2025_03_13_ZS_Follow_Player.zip
    846 байт · Просмотры: 14
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.058
Благодарности
1.017
Баллы
315
Альтернативный вариант для реализации процесса "ожидания" напарником с TA Overlay

в этом варианте я не использую новое zs_расписание для удаления Overlay и это хорошо.

Daedalus:
func void ZS_SJ_FP_start()
{
 
    if hero.aivar[AIV_INVINCIBLE] == false  { return; };
    if self.aivar[AIV_INVINCIBLE] == true   { return; };    // герой говорит с напарником
 
    if self.aivar[AIV_PARTYMEMBER] == false  { return; };
    //if Npc_IsInState(self,ZS_Follow_Player)


    // self это напарник героя. Напарник будет ждать героя
    // если герой решил с кем то поболтать/ поспать /поработать в кузне
 
 
    var string NearestWP;
    NearestWP = Npc_GetNearestWP(self);
 
    Hlp_PrintConsole(Str_Format("ZS_SJ_FP_start[%s]:  NearestWP = %s", self.name, NearestWP));

 
    TA_BeginOverlay(self);
        TA(self, 00,12, ZS_Smoke_Joint, NearestWP);
        TA(self, 12,00, ZS_Smoke_Joint, NearestWP);
    TA_EndOverlay(self);
 
    AI_ContinueRoutine(self);
 
    self.aivar[AIV_PARTYMEMBER] = 666; // Маркер
};

Daedalus:
func void ZS_SJ_FP_end()
{
    if self.aivar[AIV_PARTYMEMBER] != 666  { return; };

    Hlp_PrintConsole(Str_Format("   ZS_SJ_FP_end = [%s]", self.name));
    self.aivar[AIV_PARTYMEMBER] = true;
    TA_RemoveOverlay(self);
    AI_ContinueRoutine(self);
};

соответственно наложения оверлея и его удаление можно произвести например из кровати или какой то другой функции. НО НЕ В ДИАЛОГЕ С НПС. Для теста использовал цикличную функцию.
AI_SetNpcsToState используется для того что поработать с неопределённым кол-вом НПС.
Daedalus:
func event GameLoop()
{
    var int xyz;
 
    if PLAYER_MOBSI_PRODUCTION != false
    && xyz == 0
    {
        xyz = 1;
        AI_SetNpcsToState(hero, ZS_SJ_FP_start, 1000); //-kairo
    };
 
    if PLAYER_MOBSI_PRODUCTION == false
    && xyz == 1
    {
        AI_SetNpcsToState(hero, ZS_SJ_FP_end, 1000); //-kairo
        xyz = 0;
    };
};
 

Вложения

  • 2025_03_14_ZS_SJ_FP.zip
    1,4 KB · Просмотры: 1
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.058
Благодарности
1.017
Баллы
315
"Парковка" Билгота

Daedalus:
func void DIA_Bilgot_Pause_Info()
{
    if self.aivar[AIV_PARTYMEMBER] == 666
    {
        AI_Output(other,self,"DIA_Addon_Diego_ComeOn_15_00");    //Пойдем со мной.
        AI_Output(self,other,"DIA_Bilgot_TAKEYOUWITHME_05_03");    //Я готов!

        self.aivar[AIV_PARTYMEMBER] = true;
        TA_RemoveOverlay(self);
    }
    else
    {
        //AI_Output(other,self,"DIA_Bilgot_LAUFSCHNELLER_15_00");    //Ты не мог бы идти немного быстрее?!
        //AI_Output(self,other,"DIA_Bilgot_LAUFSCHNELLER_05_01");    //Я иду так быстро, как могу.
        AI_Output(other,self,"DIA_Addon_Diego_WarteHier_15_00");    //Подожди здесь!
        AI_Output(self,other,"DIA_Bilgot_BEIBRUECKEANGEKOMMEN_05_03");    //Прощай!

        var string NearestWP;
        NearestWP = Npc_GetNearestWP(self);
 
        Hlp_PrintConsole(Str_Format("DIA_Bilgot_Pause_Info[%s]:  NearestWP = %s", self.name, NearestWP));

        TA_BeginOverlay(self);
            TA(self, 00,12, ZS_Smoke_Joint, NearestWP);
            TA(self, 12,00, ZS_Smoke_Joint, NearestWP);
        TA_EndOverlay(self);
        self.aivar[AIV_PARTYMEMBER] = 666; // Маркер
    };
    AI_StopProcessInfos(self);
};

upd
добавил "парковку" для Assign Ambient Infos. файл в скрепе
 

Вложения

  • DIA_Bilgot_Pause.zip
    1,2 KB · Просмотры: 1
  • DIA_PARTYMEMBER_Pause.zip
    1,3 KB · Просмотры: 1
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.058
Благодарности
1.017
Баллы
315
Финальный вариант для реализации процесса "ожидания" напарником с TA Overlay

Наложения оверлея и его удаление можно произвести например из кровати или какой то другой любой функции. Для теста использовал цикличную функцию.

Спасибо ElderGamer за поиск оптимального варианта.

Если я правильно понял, ссылка нужна тебе для того, чтобы заставить непися в состоянии следования за ГГ что-то сделать. Если да, то в этом случае можно (и нужно) использовать посылку восприятия PERC_NPCCOMMAND и функцию-обработчик этого восприятия. В Г2 оно имеется, только зона действия ограничена 100 см. Это можно изменить в скриптах в функции InitPerceptions.

активируем PERC_NPCCOMMAND и увеличиваем радиус восприятие в функциях ZS_Follow_Player и ZS_Guide_Player
Daedalus:
func event E_ZS_Follow_Player()
{
    Hlp_PrintConsole(Str_Format("   E_ZS_Follow_Player[%s]:  ", self.name));
    Perc_SetRange        (PERC_NPCCOMMAND, 3000                            );
    Npc_PercEnable(self, PERC_NPCCOMMAND, B_NpcCommand);
};

func event E_ZS_Guide_Player()
{
    Hlp_PrintConsole(Str_Format("   E_ZS_Guide_Player[%s]:  ", self.name));
    Perc_SetRange        (PERC_NPCCOMMAND, 3000                            );
    Npc_PercEnable (self, PERC_NPCCOMMAND, B_NpcCommand);
};

посылка сигнала напарникам
Daedalus:
func event GameLoop()
{
    var int xyz;
 
    //if PLAYER_MOBSI_PRODUCTION != false
    if hero.aivar[AIV_INVINCIBLE] == true
    && xyz == 0
    {
        xyz = 1;
        Hlp_PrintConsole("  hero INVINCIBLE..");
        Npc_SendPassivePerc(hero,PERC_NPCCOMMAND,hero,hero);
    };
 
 
    //if PLAYER_MOBSI_PRODUCTION == false
    if hero.aivar[AIV_INVINCIBLE] == false
    && xyz == 1
    {
        Hlp_PrintConsole("  hero VINCIBLE..");
        Npc_SendPassivePerc(hero,PERC_NPCCOMMAND,hero,hero);
        xyz = 0;
    };
   
};

проверки и наложение / удаления оверлея
Daedalus:
func void B_OverlayParking_Start(var c_npc slf)
{
    if hero.aivar[AIV_INVINCIBLE] == false  { return; };
    if slf.aivar[AIV_PARTYMEMBER] == false  { return; };
 
 
    if slf.aivar[AIV_INVINCIBLE] == true    { return; };    // герой говорит с напарником?

 
    //if Npc_IsInState(slf,ZS_Follow_Player)


    // slf это напарник героя. Напарник будет ждать героя
    // если герой решил с кем то поболтать/ поспать /поработать в кузне
 
    var string NearestWP;
    NearestWP = Npc_GetNearestWP(slf);
 
    Hlp_PrintConsole(Str_Format("B_OverlayParking_Start[%s]:  NearestWP = %s", slf.name, NearestWP));

   
    TA_BeginOverlay(slf);
        TA(slf, 00,12, ZS_Follow_Player, NearestWP);
        TA(slf, 12,00, ZS_Follow_Player, NearestWP);
    TA_EndOverlay(slf);
 
    AI_ContinueRoutine(slf);
    slf.aivar[AIV_PARTYMEMBER] = 666; // Маркер
};


func void B_OverlayParking_End(var c_npc slf)
{
    if slf.aivar[AIV_PARTYMEMBER] != 666    { return; };

    Hlp_PrintConsole(Str_Format("   B_OverlayParking_End = [%s]", slf.name));
    slf.aivar[AIV_PARTYMEMBER] = true;
    TA_RemoveOverlay(slf);
    AI_ContinueRoutine(slf);
};


func void B_NpcCommand()
{
    // там список исключений из соседнего файла
    if DIA_PARTYMEMBER_Pause_Condition()
    {
        Hlp_PrintConsole(Str_Format("   B_NpcCommand[%s]...  ", self.name));
 
        B_OverlayParking_Start(self);
        B_OverlayParking_End(self);
 
    };
};


Мне нравится этот вариант, так как в нём "напарник"(например Ларес) в случае диалога героя с другим НПС не убегает и не пропадает, а "чекинится" на текущем мести. Пока не стал делать отдельную zs_функцию для парковки. в случае положительных тестов, можно будет уже дописать что то вдумчиво и осознанно.

p.s. НПС может тупить при "парковке". поэтому этот вариант надо использовать с DIA_PARTYMEMBER_Pause.zip Что бы можно всегда было удалить оверлей через диалог.
 

Вложения

  • B_OverlayParking.zip
    1,4 KB · Просмотры: 1
  • DIA_PARTYMEMBER_Pause.zip
    1,3 KB · Просмотры: 1
Последнее редактирование:
Сверху Снизу