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

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

В разработке... useWithItem и ConditionFunc для MobInter

Бене Гессерит это


  • Всего проголосовало
    8

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
MobInter содержит «вшитую» проверку на предмет необходимый герою для взаимодействия с Mob'ом. Данный плагин «отвязывает» проверку на WithItem , осуществляя перехват функции разрешающий взаимодействие с объектом в новой общей Condition функции вызываемой из скриптов.

Спасибо ElderGamer за идею, спасибо Xeдин за реализацию, спасибо Gratt за то что лишил нас костылей, спасибо Slavemaster за то что делает Юнион совершенным.

***

После установки плагина на уровне скриптов надо добавить две функции:
  • G_MobInter_CanInteractWith – разрешает / запрещает взаимодействие с моб объектом.
  • G_MobInter_UseWithItem – заменяет Item(при необходимости)
  • G_MobInter_SendCallOnStateFunc - заменяет StateFunc функции(при необходимости)
Функция G_MobInter_CanInteractWith "общая" для всех МОБ'ов. В ней можно прописать вызов отдельных кондишен функцию для конктерных МОБ объектов с которыми взаимодействует герой.
Daedalus:
// функция вызывается движком если НПС - герой
func int G_MobInter_CanInteractWith(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format("   G_MobInter_CanInteractWith:  sceme: %s useWithItem (%i)", sceme, useWithItem));
 
    if  (Hlp_StrCmp(sceme,"LAB"))       {   return C_Hero_GetInv_MobInterItem(ItMi_Flask);  };
    //if  (Hlp_StrCmp(sceme,"RMAKER"))    {    return hero_RMaker_Condition(useWithItem);   };// это рунный стол, делаем проверку внутри HERO_ALCHEMY_CONDITION
 
    if  (useWithItem == -1)              {   return true;    }; // Item не требуется
 
    return C_Hero_GetInv_MobInterItem(useWithItem);             // вроверка на наличие у героя Item
};
Внутри функции кондишион моба можно делать проверку на необходимые условия для взаимодействием с данным мобом, как в оригинальных скриптах: наличие у героя каких то вещей , навыков, времени суток, наличие друзей / врагов рядом и так далее.

Для прочих объектов я написал черновик универсальной функции C_Hero_GetInv_MobInterItem.
Daedalus:
func int C_Hero_GetInv_MobInterItem(var int useWithItem)
{
    if (Npc_GetInvItem(hero,useWithItem))
    {
        return true;    // у героя есть предмет -- > взаимодействие
    };
 
    // создаём красивый отказ от взаимодействия
    CreateInvItem(hero,useWithItem);
 
    var string msg;
    msg = ConcatStrings("Для использования необдим: ", item.name) ;
    PrintDialog( 1, msg , -1, -1, FONT_ScreenSmall, 2);
    AI_PlayAni(hero,"T_DONTKNOW");
 
    Npc_RemoveInvItem(hero,useWithItem);
 
    return false;
};
В ней проверяется есть ли у героя предмет для взаимодействия с МОБом, если его нет то выводится какое-то сообщение и/или герой машет руками и/или герой что то говорит. То есть данная функция дописывается/настраивается согласно тому как автор видит данное событие.
1686181406672.png
1686181427399.png

***

Из бонусов:
  • теперь предмет необходимый для взаимодействия с мобом не будет удалять у героя движок. То есть в диалоге выхода из производства не придётся создавать «неиспользованную» руну/колбу/заготовку.
  • в функции C_MobInter_UseWithItem можно заменить item который герой будет использовать при взаимодействие с МОБ'ом.

Daedalus:
// функция вызывается движком  если НПС - герой
func int G_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format(" call G_MobInter_UseWithItem sceme: %s, useWithItem: %i", sceme, useWithItem));
 
    if (Hlp_StrCmp(sceme,"LAB"))    { return C_MobInter_UseNewItem(ItMi_Flask_fake); };
 
    // возвращаем оригинальную инстанцию
    return useWithItem;
};


***
Daedalus:
func int G_MobInter_SendCallOnStateFunc(var string sceme, var int state)
{
    Hlp_PrintConsole(Str_Format(" call G_MobInter_SendCallOnStateFunc sceme: %s, state: %i", sceme, state));
};
 

Вложения

  • 2023_06_16_zMobInet.zip
    92,9 KB · Просмотры: 3
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
теперь наверное надо как то прикрутить парсер скриптовой функции что бы уже на уровне скриптов расписать тонкую обработку под свои нужны
Daedalus:
func int C_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    return useWithItem;
};
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
теперь наверное надо как то прикрутить парсер скриптовой функции что бы уже на уровне скриптов расписать тонкую обработку под свои нужны
Daedalus:
func int C_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    return useWithItem;
};
 

Xeдин


Модостроитель
Регистрация
3 Дек 2008
Сообщения
1.448
Благодарности
1.976
Баллы
365
MW 7, тебе проверка this->useWithItem.CompareI(FocusHero->useWithItem) вообще не нужна, ты по фокусу выше уже сравниваешь. Да и сам фокус не очень идея. Если я правильно понял что ты хочешь, попробуй такой, немного костыльный вариант.
Daedalus:
func int C_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format(" call C_MobInter_UseWithItem useWithItem: %i, sceme: %s", useWithItem, sceme));
    return ItMiSwordRaw;
};
C++:
// Supported with union (c) 2020 Union team
// User API for oCMobInter
// Add your methods here
int GetUseWithItem_New();
int CanInteractWith_New(oCNpc*);
C++:
void Game_Loop() {
      GetUseWithItemGameLoop();
}
C++:
// Supported with union (c) 2020 Union team
// Union SOURCE file

namespace GOTHIC_ENGINE {
    // Add your code here . . .

    oCMobInter* lastPlayerMobInter = nullptr;

    HOOK Ivk_oCMobInter_CanInteractWith_New PATCH(&oCMobInter::CanInteractWith, &oCMobInter::CanInteractWith_New);
    int oCMobInter::CanInteractWith_New(oCNpc* npc) {
        if (player == npc) {
            lastPlayerMobInter = this;
        }
        return THISCALL(Ivk_oCMobInter_CanInteractWith_New)(npc);
    }

    HOOK Ivk_oCMobInter_GetUseWithItem_New PATCH(&oCMobInter::GetUseWithItem, &oCMobInter::GetUseWithItem_New);
    int oCMobInter::GetUseWithItem_New() {
        if (player && this == lastPlayerMobInter) {
            int sym_index = parser->GetIndex("C_MobInter_UseWithItem");
            if (sym_index != -1) {
                int idxUseWithItem = parser->GetIndex(this->useWithItem);
                if (idxUseWithItem != -1) {      
                    parser->datastack.Push(reinterpret_cast<int>(&this->sceme));
                    parser->datastack.Push(zPAR_TOK_PUSHVAR);
                    parser->datastack.Push(idxUseWithItem);
                    parser->datastack.Push(zPAR_TOK_PUSHINT);
                    parser->DoStack(parser->GetSymbol(sym_index)->single_intdata);
                    zCPar_Symbol* newUseWithItemSym = parser->GetSymbolInfo(parser->PopDataValue());
                    if (newUseWithItemSym) {
                        zSTRING old = Z this->useWithItem;
                        this->SetUseWithItem(newUseWithItemSym->name);
                        int resCall = THISCALL(Ivk_oCMobInter_GetUseWithItem_New)();
                        this->SetUseWithItem(old);
                        return resCall;
                    }
                }
            }
        }
        return THISCALL(Ivk_oCMobInter_GetUseWithItem_New)();
    }

    void GetUseWithItemGameLoop() {
        if (player && !player->GetInteractMob() && lastPlayerMobInter) {
            lastPlayerMobInter = nullptr;
        }  
    }
}
В примере при взаимодействии с ведром с водой игрок будет доставать ItMiSwordRaw

36.jpg


Хотя с ITFO_BEER лучше выглядит :)

37.jpg
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
Xeдин, работает как надо, спасибо.

***

пример использования в г2
Daedalus:
instance ItMi_Flask_fake(c_item)  {    ItMi_Flask();  };
    
func int C_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format(" call C_MobInter_UseWithItem sceme: %s, useWithItem: %i", sceme, useWithItem));
 
    if (Hlp_StrCmp(sceme,"LAB") == true)
    {        
        // новый предмет
        var int itmid;  itmid=ItMi_Flask_fake;
        
        // если нет предмета, то создаём
        if (!Npc_GetInvItem(hero,itmid))    {   CreateInvItem(hero,itmid);  };
        
        // возвращаем новодел
        return itmid;
    };
    
    
    // возвращаем оригинальную инстанцию
    return useWithItem;
};
 

Вложения

  • zMobInter.zip
    89,6 KB · Просмотры: 4

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
добавлена новая версия в шапку

MEG@VOLT удали пожалуйста файлы в скрепке к данному посту
 

Вложения

  • C_MobInter.zip
    23,3 KB · Просмотры: 4
  • 1685779446173.jpeg
    1685779446173.jpeg
    382,1 KB · Просмотры: 96
  • 1685779456847.jpeg
    1685779456847.jpeg
    411,3 KB · Просмотры: 91
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
Рунный стол
Внутри функции кондишион моба можно делать проверку на необходимые условия для взаимодействием с данным мобом, как в оригинальных скриптах: наличие у героя каких то вещей , навыков, времени суток, наличие друзей / врагов рядом и так далее.
Daedalus:
func int hero_RMaker_Condition(var int useWithItem)
{  
    // может быть стоит добавить проверку на знание заклинаний рун

    if (!C_Hero_GetInv_MobInterItem(itmi_pliers))   { return false; };  // нужны щипцы для бровей
    if (!C_Hero_GetInv_MobInterItem(useWithItem))   { return false; };  // нужна руна

    Hlp_PrintConsole("  hero_RMaker_Condition --> TRUE");
 
    return true;
};
 
Последнее редактирование:

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
C_MobInter_CanInteractWith – разрешает / запрещает взаимодействие с моб объектом.
Работает ли это с Г1? Попробовал добавить функцию в скрипты, но она, похоже, не вызывается.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
С новыми файлами в Г1 вылет при попытке взаимодействия с объектами. Пока пробую экспериментировать в Г2НВ.

Кстати, в Г2НВ при взаимодействии с кальяном тушка зависает в состоянии S0.

Не понятно, как описанный алгоритм будет работать с зажиганием факелов и костров. Там в свойствах объектов прописана инстанция горящего факела, наличие которого, вроде бы, определить из скриптов не получается, поскольку он находится не в инвентаре, а в слоте руки.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
С новыми файлами в Г1 вылет при попытке взаимодействия с объектами.
Со всеми?

Не понятно, как описанный алгоритм будет работать с зажиганием факелов и костров
Делать проверку на то что у героя в руке. Через функцию зпарсера. Это я уже пробовал. Работает. Вечером код запощу.
 
Последнее редактирование:

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Все не проверял. За один запуск игры проверяется только один вариант. :) Проверял на факеле, сковороде, скамейке и котле для готовки (то что есть рядом с ГГ в сохранёнке).
 

ElderGamer


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

Экспериментирую со сковородой (которая не плита). Задумка заключается в том, чтобы реализовать возможность пожарить на сковороде не только мясо, но и другие продукты с выбором варианта в mobsi-диалоге. mobsi-диалог запускается при достижении состояния S1 взаимодействия со сковородой. При этом на момент старта диалога в слоте руки не должно быть предмета (куска мяса).

Сейчас функция C_MobInter_CanInteractWith позволяет начать взаимодействие со сковородой, если у ГГ в инвентаре нет куска сырого мяса. Но процесс взаимодействия доходит только до состояния S0. Играться с анимациями, чтобы убрать оттуда тег использования предмета, пока не пробовал.
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.081
Благодарности
1.901
Баллы
320
На мой взгляд, более аккуратным решением будет найти все вызовы виртуальной функции oCMOB::GetUseWithItem и определить, в контексте какого NPC она вызывается. Также, не следует использовать префикс C_ для названия скриптовой функции, так как это означает Check (проверка).
C++:
namespace NAMESPACE
{
    zSTRING GetScemeName(oCMobInter* mob, oCNpc* npc)
    {
#if ENGINE == Engine_G1
        mob->SearchFreePosition(npc);
#else
        mob->SearchFreePosition(npc, 150.0f);
#endif

        zSTRING dummy;

        void** vtable = *reinterpret_cast<void***>(mob);
        vtable += 42;
        zSTRING*(__thiscall* func)(oCMOB*, zSTRING*) = reinterpret_cast<decltype(func)>(*vtable);
        return zSTRING{ *func(mob, &dummy) };
    }

    int __stdcall GetUseWithItem(oCMobInter* mob, oCNpc* npc, int instance)
    {
        static int scriptFunc = parser->GetIndex("G_GetUseWithItem");

        if (scriptFunc != -1)
            return CallParser<int>(parser, scriptFunc, GetScemeName(mob, npc), npc, instance);

        return instance;
    }

    Sub executePatch(ZSUB(GameEvent::Entry), []
        {
            CPatchInteger getUseWithItem;
            getUseWithItem.Init();
            getUseWithItem.SetObjectName("GetUseWithItem");
            getUseWithItem.SetValue(reinterpret_cast<int>(&GetUseWithItem));
            getUseWithItem.DontRemove();

            CPatch::ExecuteResource(CPlugin::GetCurrentPlugin()->GetModule(), MAKEINTRESOURCE(IDR_PATCH1), "PATCH");
        });
}
Union:
#engine [G1, G1A, G2, G2A]
    #patch [zHookMobItem]
        // engine specific
        INT engine_version = ZenDef(1, 2, 3, 4)

        INT text_oCNpcInventory_HandleEvent_call_GetUseWithItem = ZenDef(0x0066F132, 0x0069C805, 0x006B11E0, 0x0070ED68)
        INT text_oCMobInter_HasUseWithItem_call_GetUseWithItem = ZenDef(0x0067C8F4, 0x006AB1C4, 0x006BFAD4, 0x0071DB64)
        INT text_oCMobInter_CanInteractWith_call_GetUseWithItem_1 = ZenDef(0x0067F6A5, 0x006AE888, 0x006C2FFA, 0x0072108A)
        INT text_oCMobInter_CanInteractWith_call_GetUseWithItem_2 = ZenDef(0x0067F74E, 0x006AE92F, 0x006C3021, 0x007210B1)
        INT text_oCMobInter_CanInteractWith_call_GetUseWithItem_3 = ZenDef(0x00000000, 0x00000000, 0x006C30FB, 0x0072118D)
        INT text_oCMobInter_CanChangeState_call_GetUseWithItem = ZenDef(0x0067E4DA, 0x006AD47A, 0x006C1C0A, 0x0071FC9A)

        INT var_npc = ZenDef(0x78, 0x9C, 0xA0, 0xA0)
        // end of engine specific

        #assembler [text_oCNpcInventory_HandleEvent_call_GetUseWithItem]
            push ecx
            orgcode
            pop ecx
            push eax
            mov eax, [ebp+$var_npc]
            push eax
            push ecx
            call $GetUseWithItem
        #/assembler

        #assembler [text_oCMobInter_HasUseWithItem_call_GetUseWithItem]
            push ecx
            orgcode
            pop ecx
            push eax
            mov eax, [esp+0xC]
            push eax
            push ecx
            call $GetUseWithItem
        #/assembler

        IF engine_version == 2
            #assembler [text_oCMobInter_CanInteractWith_call_GetUseWithItem_1]
                push ecx
                orgcode
                pop ecx
                push eax
                push ebp
                push ecx
                call $GetUseWithItem
            #/assembler

            #assembler [text_oCMobInter_CanInteractWith_call_GetUseWithItem_2]
                push ecx
                orgcode
                pop ecx
                push eax
                push ebp
                push ecx
                call $GetUseWithItem
            #/assembler
        ELSE
            #assembler [text_oCMobInter_CanInteractWith_call_GetUseWithItem_1]
                push ecx
                orgcode
                pop ecx
                push eax
                push esi
                push ecx
                call $GetUseWithItem
            #/assembler

            #assembler [text_oCMobInter_CanInteractWith_call_GetUseWithItem_2]
                push ecx
                orgcode
                pop ecx
                push eax
                push esi
                push ecx
                call $GetUseWithItem
            #/assembler
        END

        IF engine_version >= 3
            #assembler [text_oCMobInter_CanInteractWith_call_GetUseWithItem_3]
                push ecx
                orgcode
                pop ecx
                push eax
                push esi
                push ecx
                call $GetUseWithItem
            #/assembler
        END

        #assembler [text_oCMobInter_CanChangeState_call_GetUseWithItem]
            push ecx
            orgcode
            pop ecx
            push eax
            push edi
            push ecx
            call $GetUseWithItem
        #/assembler
    #/patch
#/engine
Daedalus:
func int G_GetUseWithItem(var string sceme, var C_NPC npc, var int itemID)
{
    if Hlp_GetInstanceID(npc) == PC_Hero
    {
        if Hlp_Random(100) < 50
        {
            return ItFoBeer;
        };
        
        return ItFoApple;
    };
    
    return itemID;
};
Но не стоит забывать, что смена интерактивного предмета уничтожит все временные предметы в слотах (которые, например, с помощью DEF_CREATE_ITEM создаются).
 

Xeдин


Модостроитель
Регистрация
3 Дек 2008
Сообщения
1.448
Благодарности
1.976
Баллы
365
Slavemaster, ну да, так немного правильнее будет определить npc у которого вызывается, но вроде проблема у них не в GetUseWithItem, а они хотят oCMobInter::CanInteractWith переопределять на уровне скриптов (C_MobInter_CanInteractWith).
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
ElderGamer, попробовал написать взаимодействие со сковородой для готики 2. пришлось добавить еще G_MobInter_SendCallOnStateFunc

основные моменты:
1) у меня прописаны условия в G_MobInter_CanInteractWith, то есть проверки на то есть ли у героя еда которая будет готовится. это нужно что бы исключить то что ты описывал когда "процесс взаимодействия доходит только до состояния S0".
2) в G_MobInter_UseWithItem я возвращал null или -1 или 0, что бы в сковородку герой ничего не положил. в последний раз использовал 0.
3) в G_MobInter_SendCallOnStateFunc я вызывал функцию PAN_RUN_s1 через которую запускался интерактив с выбором через диалог что будет готовиться
4) при запуске варианта в диалоге о готовке я вставлял необходимую еду в сковородку через Npc_PutInSlot. подробнее во втором спойлере.

что то получилось, но требуется доработка и отладка.
Daedalus:
//
// функции вызывается движком если НПС - герой
//
func int G_MobInter_CanInteractWith(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format(" call G_MobInter_CanInteractWith:  sceme: %s useWithItem (%i)", sceme, useWithItem));
 
    if  (Hlp_StrCmp(sceme,"PAN"))       {   return true;  };
 
    if  (useWithItem == -1)              {   return true;    };
 
    return C_Hero_GetInv_MobInterItem(useWithItem); //
};


func int G_MobInter_UseWithItem(var string sceme, var int useWithItem)
{
    Hlp_PrintConsole(Str_Format(" call G_MobInter_UseWithItem sceme: %s, useWithItem: %i", sceme, useWithItem));
 
    //if  (Hlp_StrCmp(sceme,"PAN"))   { return -1;  };
    if  (Hlp_StrCmp(sceme,"PAN"))   { return 0;  };
 
    // возвращаем оригинальную инстанцию
    return useWithItem;
};

func int G_MobInter_SendCallOnStateFunc(var string sceme, var int state)
{
    Hlp_PrintConsole(Str_Format(" call G_MobInter_SendCallOnStateFunc sceme: %s, state: %i", sceme, state));
 
    if  (Hlp_StrCmp(sceme,"PAN") && state == 1)     { PAN_RUN_s1(); return true;  };    // начало
    if  (Hlp_StrCmp(sceme,"PAN") && state == 0)     { PAN_RUN_s0(); return true;  };    // конец
};

Daedalus:
//*************************************************//
//              что то жарить
func void Npc_RemoveRightHandItem()
{
    Npc_RemoveFromSlot(hero,"ZS_RIGHTHAND",0);
};


func void PC_PAN_amount_info(var int itemInstanceRaw,var int itemInstance2, var int amount)
{
    if (PLAYER_MOBSI_PAN == TRUE)
    {
        //Npc_RemoveFromSlot(hero,"ZS_RIGHTHAND",0);
        Npc_RemoveRightHandItem();
 
        //Npc_PutInSlot(hero,"ZS_RIGHTHAND",itemInstanceRaw,0);
        if Npc_GetInvItem(hero,itemInstanceRaw)
        {
            Npc_PutInSlot(hero,"ZS_RIGHTHAND",item,0);   // добавляем в сковородку то что будем готовить
        };
    };
 
    // отладка
    var c_item itm;     itm = Npc_GetSlotItem(hero,"ZS_RIGHTHAND");
    Hlp_PrintConsole(itm.name);

    if (Npc_HasItems(hero,itemInstanceRaw) >= amount)
    {
        var float pause; pause = intToFloat(amount);
        AI_Wait(hero,pause);
        Npc_RemoveInvItems(hero,itemInstanceRaw,amount);
        CreateInvItems(hero,itemInstance2,amount);
        AI_PrintScreen(Str_Format("%s - %s",item.name,PRINT_EAT2),-1,YPOS_GoldGiven,FONT_ScreenSmall,3);
        B_PrintCooking(txt_HowMuchIsTheFish);
    }
    else
    {
        //B_PrintNoInstanceRaw(itemInstanceRaw);
        B_PrintCooking(txt_needItFoMuttonRaw);
    };
 
    AI_CallScript("Npc_RemoveRightHandItem",self, other); // в конце готовки "очищаем" сковородку
};

//*************************************************//
//              жарить мясо
instance PC_Mobsi_Pan_Mutton5(PRT_Mobsi_Pan)    { information = PC_Mobsi_Pan_Mutton5_info; };
instance PC_Mobsi_Pan_Mutton1(PRT_Mobsi_Pan)    { information = PC_Mobsi_Pan_Mutton1_info; };

func void PC_Mobsi_Pan_Mutton5_info()  { PC_PAN_amount_info(ItFoMuttonRaw,ItFoMutton,5);  };
func void PC_Mobsi_Pan_Mutton1_info()  { PC_PAN_amount_info(ItFoMuttonRaw,ItFoMutton,1);  };

//*************************************************//
//              жарить рыбу

На мой взгляд, более аккуратным решением будет найти все вызовы виртуальной функции oCMOB::GetUseWithItem и
завтра попробую протестить решение Slavemaster и добавить в проект.
 

Вложения

  • 2023_06_06_zMobInet.zip
    93,8 KB · Просмотры: 2
Последнее редактирование:

Xeдин


Модостроитель
Регистрация
3 Дек 2008
Сообщения
1.448
Благодарности
1.976
Баллы
365
MW 7, щас посмотрел кстати, у тебя в хуке gCanInteractWith если скрипты возвращают что нельзя взаимодействовать, то и lastPlayerMobInter не надо сетить. Он у тебя до проверки сейчас сетится. Хотя если переделаешь все по методу Slavemaster, то это уже и не нужно будет.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
если скрипты возвращают что нельзя взаимодействовать, то и lastPlayerMobInter не надо сетить
C++:
    oCMobInter* lastPlayerMobInter = nullptr;

    HOOK gCanInteractWith PATCH(&oCMobInter::CanInteractWith, &oCMobInter::zCanInteractWith);
    int oCMobInter::zCanInteractWith(oCNpc* npc)
    {
        if (player == npc)
        {

            cmd << Z"oCMobInter [" + this->sceme + "] :: CanInteractWith" << endl;
            cmd << Z"    :: conditionFunc=" + this->conditionFunc + " :: onStateFuncName=" + this->onStateFuncName << endl;


            int funcIndex = parser->GetIndex("G_MobInter_CanInteractWith");
            
            int idxUseWithItem = parser->GetIndex(this->useWithItem);

            //return CallParser<int>(parser, funcIndex, this->sceme, idxUseWithItem); // отвалился C++17 Plugin Template будем страдать

            if (funcIndex >= 0)
            {

                parser->datastack.Push(reinterpret_cast<int>(&this->sceme));
                parser->datastack.Push(zPAR_TOK_PUSHVAR);
                parser->datastack.Push(idxUseWithItem);
                parser->datastack.Push(zPAR_TOK_PUSHINT);

                parser->DoStack(parser->GetSymbol(funcIndex)->single_intdata);

                //return parser->PopDataValue();

                int res = parser->PopDataValue();

                // если скрипты возвращают что нельзя взаимодействовать, то и lastPlayerMobInter не надо сетить.
                // если неверно, что неверно lastPlayerMobInter, то lastPlayerMobInter верно».
                if (res == 1)
                {

                    lastPlayerMobInter = this;
                }
                
                return res;
            }
        }
        return THISCALL(gCanInteractWith)(npc);
    }
 

Xeдин


Модостроитель
Регистрация
3 Дек 2008
Сообщения
1.448
Благодарности
1.976
Баллы
365

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.000
Благодарности
968
Баллы
295
Не признаёт функцию. Что нужно добавить к Юнион? Юнион обновлён до версии m.
это внешняя функция zParserExtender Gothic ½ - Расширение возможностей парсера | zParserExtender [плагин для Union].

на сколько я понял она уже вшита в юнион. по крайней мере в стим версии.
 
Сверху Снизу