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

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

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

Вопросы по union

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
10.378
Благодарности
7.201
Баллы
1.850
Но какой класс/метод/поле тогда за это отвечает? Можно ли его просто взять и в динамике изменить?
Где-то слышал, что движком заложено макс дистанция отрисовки нпс 8000
Возможно плагином можно сделать. Но я не подскажу как((
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Где-то слышал, что движком заложено макс дистанция отрисовки нпс 8000
Не пугай так пожалуйста, только не это(
Пост автоматически объединён:

Где-то слышал, что движком заложено макс дистанция отрисовки нпс 8000
Может в таком случае пройтись по всем вобам и те, что oCNpc насильно отрисовать? Мне бы понимать, что за менеджер вообще их отрисовывает, я бы попробовал.
 
Последнее редактирование:

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Я определенно хукаю неправильно. Как же это сделать?
С zCViewDraw::Render похожий код работает без проблем, но она возвращает пустое значение. А тут ни в какую прям. Пробовал и detours, и auto и callpatch. Никак.


C++:
    void __fastcall zTBBox3D_Draw(zTBBox3D* self, void* vtable, zCOLOR& color);
    auto Hook_zTBBox3D_Draw = Union::CreateHook(reinterpret_cast<void*>(zSwitch(0x00636F50, 0x0065D480, 0x00545EE0, 0x00545EE0)), &zTBBox3D_Draw, Union::HookType::Hook_Auto);
    void __fastcall zTBBox3D_Draw(zTBBox3D* self, void* vtable, zCOLOR& color)
    {
        Draw_zTBBox3D(&color);
        Hook_zTBBox3D_Draw(self, vtable, color);
    }

    //0x006015D0 public: virtual int __fastcall zCVob::Render(struct zTRenderContext&)

    int __fastcall zCVob_Render(zCVob* self, zTRenderContext& rctxt);
    auto Hook_zCVob_Render = Union::CreateHook(reinterpret_cast<INT32*>(zSwitch(0x00636F50, 0x0065D480, 0x006015D0, 0x006015D0)), &zCVob_Render, Union::HookType::Hook_CallPatch);
    int __fastcall zCVob_Render(zCVob* self, zTRenderContext& rctxt)
    {
        Render_zCVob(self);
        return Hook_zCVob_Render(self, rctxt);
    }
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
494
Благодарности
337
Баллы
230
Я определенно хукаю неправильно. Как же это сделать?
Про какую функцию идет речь? Про zCVob::Render() или zTBBox3D:: Draw() ?
Из практики знаю, что рендер вобов не перехватывается на враппере DX11, потому что функция переписана и оригинальная не вызывается.

По поводу регулировки дистанции рендера объектов, есть такое решение, но на обычном Union API.
Если интересует, то вот пример для Г2а:
C++:
// G2a
// 0x006013E0 public: void __thiscall zCVob::CalcRenderAlpha(float dist, zCVisual*& pVisual, float& alpha)
void __fastcall CalcRenderAlpha(zCVob* _this, void* vt, float dist, zCVisual*& pVisual, float& alpha);
CInvoke <void(__thiscall*) (zCVob* _this, float dist, zCVisual*& pVisual, float& alpha)> pCalcRenderAlpha(0x006013E0, CalcRenderAlpha, IVK_AUTO);
void __fastcall CalcRenderAlpha(zCVob* _this, void* vt, float dist, zCVisual*& pVisual, float& alpha)
{
    // вызываем настоящую функцию
    // (на всякий случай, вдруг к ней привязаны другие перехватчики)
    pCalcRenderAlpha(_this, dist, pVisual, alpha);

    // если объект не имеет визуала ИЛИ не находится на локации ИЛИ находится в воде(? странно)
    if (!_this->GetVisual() || !_this->homeWorld || _this->bIsInWater)
        // выходим, т.к. прозрачность воба в этих ситуациях уже посчитана: 0.0f, 0.0f, 1.0f
        return;

    // для НПС
    if (dynamic_cast<oCNpc*>(_this))
        // если вкл. полупрозрачность тела, то используем спец. значение альфы (alpha = _this->visualAlpha),
        // иначе, сообщаем рендеру, что это обычный непрозрачный объект (alpha = 1.0f)
        alpha = _this->visualAlphaEnabled ? _this->visualAlpha : 1.0f;

    // Примечание: (alpha = 0.0f) - запрещает рендерить воб
}

void Game_Loop()
{
    // получение некоторых величин
    float ins_range = oCSpawnManager::GetInsertRange();                    // дист. вставки НПС
    float rem_range = oCSpawnManager::GetRemoveRange();                    // дист. удаления НПС
    float mesh_lod = zCProgMeshProto::GetLODParamStrengthModifier();    // коф. упрощения мешей (0 - лоу поли, 1.0 - детальнее)
    float vob_scab = ogame->world->vobFarClipZScalability;

    // вывод на экран
    screen->Print(100, 1300, string::Combine("vob_scabty = %f", vob_scab));
    screen->Print(100, 1600, string::Combine("range = %i-%i", (int)ins_range, (int)rem_range));
    screen->Print(100, 1900, string::Combine("mesh_lod = %f", mesh_lod));


    // величины изменения параметров:
    float lod_offset    = 0.05f;    // для LOD
    float scab_offset    = 0.1f;        // для ZScalability
    float spawn_offset    = 100.0f;    // для Range

    /********************************************/
    //  Настройка тумана и дальности прорисовки
    /********************************************/
    if (zKeyPressed(KEY_NUMPAD1))
    {
        // убавление
        vob_scab -= scab_offset;
        ogame->world->vobFarClipZScalability = vob_scab;
        ogame->world->GetActiveSkyControler()->SetFarZScalability(vob_scab);
    }


    if (zKeyPressed(KEY_NUMPAD2))
    {
        // прибавление
        vob_scab += scab_offset;
        ogame->world->vobFarClipZScalability = vob_scab;
        ogame->world->GetActiveSkyControler()->SetFarZScalability(vob_scab);
    }



    /**************************************************/
    //  Настройка дальности появления и исчезания НПС
    /**************************************************/
    if (zKeyPressed(KEY_NUMPAD4))
    {
        // убавление
        oCSpawnManager::SetInsertRange(ins_range - spawn_offset);
        oCSpawnManager::SetRemoveRange(rem_range - spawn_offset);
    }

    if (zKeyPressed(KEY_NUMPAD5))
    {
        // прибавление
        oCSpawnManager::SetInsertRange(ins_range + spawn_offset);
        oCSpawnManager::SetRemoveRange(rem_range + spawn_offset);

        // после изменения настроек,
        // вызываем мгновенное появление НПС
        ogame->spawnman->SpawnImmediately(TRUE);
    }



    /******************/
    //  LOD для мешей
    /******************/
    if (zKeyPressed(KEY_NUMPAD7))
    {
        // упрощение модели
        mesh_lod -= lod_offset;
        zClamp(mesh_lod, 0.0f, 1.0f);
        zCProgMeshProto::SetLODParamStrengthModifier(mesh_lod);
    }

    if (zKeyPressed(KEY_NUMPAD8))
    {
        // усложнение модели
        mesh_lod += lod_offset;
        zClamp(mesh_lod, 0.0f, 1.0f);
        zCProgMeshProto::SetLODParamStrengthModifier(mesh_lod);
    }
}
Начинаешь регулировать дальность прорисовки тумана (Num1/2). Затем радиус появления НПС (Num4/5). Ну и ради эксперимента смотришь, как LOD ломает сетку модели на (Num7/8). Всё должно происходить в реал-тайм на локации. Слева будет колонка из 3х параметров, которые ты регулируешь.
Но учти, после открытия и закрытия главного меню, настройки дальности прорисовки и LOD сбросятся до значений, прописанных в Gothic.ini.
Здесь нужно будет подумать о сохранении результата. Всё зависит от задачи, которую ты хочешь решить.
Также нужно помнить, что у альт. рендера DX11 - свои настройки графики.

Тестовые скриншоты:
1.jpg
2.jpg
 
Последнее редактирование:

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Про какую функцию идет речь? Про zCVob::Render() или zTBBox3D:: Draw() ?
Из практики знаю, что рендер вобов не перехватывается на враппере DX11, потому что функция переписана и оригинальная не вызывается.

По поводу регулировки дистанции рендера объектов, есть такое решение, но на обычном Union API.
Если интересует, то вот пример для Г2а:
C++:
// G2a
// 0x006013E0 public: void __thiscall zCVob::CalcRenderAlpha(float dist, zCVisual*& pVisual, float& alpha)
void __fastcall CalcRenderAlpha(zCVob* _this, void* vt, float dist, zCVisual*& pVisual, float& alpha);
CInvoke <void(__thiscall*) (zCVob* _this, float dist, zCVisual*& pVisual, float& alpha)> pCalcRenderAlpha(0x006013E0, CalcRenderAlpha, IVK_AUTO);
void __fastcall CalcRenderAlpha(zCVob* _this, void* vt, float dist, zCVisual*& pVisual, float& alpha)
{
    // вызываем настоящую функцию
    // (на всякий случай, вдруг к ней привязаны другие перехватчики)
    pCalcRenderAlpha(_this, dist, pVisual, alpha);

    // если объект не имеет визуала ИЛИ не находится на локации ИЛИ находится в воде(? странно)
    if (!_this->GetVisual() || !_this->homeWorld || _this->bIsInWater)
        // выходим, т.к. прозрачность воба в этих ситуациях уже посчитана: 0.0f, 0.0f, 1.0f
        return;

    // для НПС
    if (dynamic_cast<oCNpc*>(_this))
        // если вкл. полупрозрачность тела, то используем спец. значение альфы (alpha = _this->visualAlpha),
        // иначе, сообщаем рендеру, что это обычный непрозрачный объект (alpha = 1.0f)
        alpha = _this->visualAlphaEnabled ? _this->visualAlpha : 1.0f;

    // Примечание: (alpha = 0.0f) - запрещает рендерить воб
}

void Game_Loop()
{
    // получение некоторых величин
    float ins_range = oCSpawnManager::GetInsertRange();                    // дист. вставки НПС
    float rem_range = oCSpawnManager::GetRemoveRange();                    // дист. удаления НПС
    float mesh_lod = zCProgMeshProto::GetLODParamStrengthModifier();    // коф. упрощения мешей (0 - лоу поли, 1.0 - детальнее)
    float vob_scab = ogame->world->vobFarClipZScalability;

    // вывод на экран
    screen->Print(100, 1300, string::Combine("vob_scabty = %f", vob_scab));
    screen->Print(100, 1600, string::Combine("range = %i-%i", (int)ins_range, (int)rem_range));
    screen->Print(100, 1900, string::Combine("mesh_lod = %f", mesh_lod));


    // величины изменения параметров:
    float lod_offset    = 0.05f;    // для LOD
    float scab_offset    = 0.1f;        // для ZScalability
    float spawn_offset    = 100.0f;    // для Range

    /********************************************/
    //  Настройка тумана и дальности прорисовки
    /********************************************/
    if (zKeyPressed(KEY_NUMPAD1))
    {
        // убавление
        vob_scab -= scab_offset;
        ogame->world->vobFarClipZScalability = vob_scab;
        ogame->world->GetActiveSkyControler()->SetFarZScalability(vob_scab);
    }


    if (zKeyPressed(KEY_NUMPAD2))
    {
        // прибавление
        vob_scab += scab_offset;
        ogame->world->vobFarClipZScalability = vob_scab;
        ogame->world->GetActiveSkyControler()->SetFarZScalability(vob_scab);
    }



    /**************************************************/
    //  Настройка дальности появления и исчезания НПС
    /**************************************************/
    if (zKeyPressed(KEY_NUMPAD4))
    {
        // убавление
        oCSpawnManager::SetInsertRange(ins_range - spawn_offset);
        oCSpawnManager::SetRemoveRange(rem_range - spawn_offset);
    }

    if (zKeyPressed(KEY_NUMPAD5))
    {
        // прибавление
        oCSpawnManager::SetInsertRange(ins_range + spawn_offset);
        oCSpawnManager::SetRemoveRange(rem_range + spawn_offset);

        // после изменения настроек,
        // вызываем мгновенное появление НПС
        ogame->spawnman->SpawnImmediately(TRUE);
    }



    /******************/
    //  LOD для мешей
    /******************/
    if (zKeyPressed(KEY_NUMPAD7))
    {
        // упрощение модели
        mesh_lod -= lod_offset;
        zClamp(mesh_lod, 0.0f, 1.0f);
        zCProgMeshProto::SetLODParamStrengthModifier(mesh_lod);
    }

    if (zKeyPressed(KEY_NUMPAD8))
    {
        // усложнение модели
        mesh_lod += lod_offset;
        zClamp(mesh_lod, 0.0f, 1.0f);
        zCProgMeshProto::SetLODParamStrengthModifier(mesh_lod);
    }
}
Начинаешь регулировать дальность прорисовки тумана (Num1/2). Затем радиус появления НПС (Num4/5). Ну и ради эксперимента смотришь, как LOD ломает сетку модели на (Num7/8). Всё должно происходить в реал-тайм на локации. Слева будет колонка из 3х параметров, которые ты регулируешь.
Но учти, после открытия и закрытия главного меню, настройки дальности прорисовки и LOD сбросятся до значений, прописанных в Gothic.ini.
Здесь нужно будет подумать о сохранении результата. Всё зависит от задачи, которую ты хочешь решить.
Также нужно помнить, что у альт. рендера DX11 - свои настройки графики.

Тестовые скриншоты:
Посмотреть вложение 132203 Посмотреть вложение 132204
Как то не подумал, что такое возможно. У меня как раз DX11. Сейчас определенно пойду пробовать, спасибо за ответ. В целом, это как раз то, что мне нужно, только вот в немного более интересном виде. В отдельном окне, по команде, и да, с сохранением настроек после выхода из игры. А функции наверху обе не перехватываются, но видимо проблема то все таки не в хуке.
 

RPD

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

Вот, например, функция открывания инвентаря ГГ.

C++:
    void __fastcall oCNpcInventory_Open(oCNpcInventory* self, void* vt, int a, int b, int c);
    auto Hook_oCNpcInventory_Open = Union::CreateHook(ENGINE_ADDRESS_OF(&oCNpcInventory::Open), &oCNpcInventory_Open, Union::HookType::Hook_Detours);
    void __fastcall oCNpcInventory_Open(oCNpcInventory* self, void* vt, int a, int b, int c)
    {
        Hook_oCNpcInventory_Open(self, vt, a, b, c);
    }


Я попробовал ее хукнуть с отключенными модификациями - все работает замечательно. Как только включаю тот же Union Advanced Inventory - хук уже не работает. Я уже столько информации нарыл, Что лучше искать адрес по сигнатуре из файла, что есть Imm32 коллекции, которые возможно в рантайме в себе хранят информацию об адресах и оффсетах. Мозг конечно взрывается, но плюс минус логику происходящего я понимаю. Проблемы на стадии реализации возникают, как код то написать? Пробовал так:

C++:
    void* FindEngineAddress(Union::Signature baseSign) {
    #if defined(__G1)
        Union::SignatureFile* signFile = Union::SignatureFile::GetFromFile("Names.txt");
        auto compSign = signFile->FindSimilarSignature(&baseSign);
        return compSign ? compSign->GetAddress() : nullptr;
    #elif defined(__G2A)
        Union::SignatureFile* signFile = Union::SignatureFile::GetFromFile("Names.txt");
        auto compSign = signFile->FindSimilarSignature(&baseSign);
        return compSign ? compSign->GetAddress() : nullptr;
    #else
        return nullptr;
    #endif
    }
    #define SIGNATURE_OF(what) Union::Signature(what, #what)
    #define ENGINE_ADDRESS_OF(what) FindEngineAddress(SIGNATURE_OF(what))
Не работает. И вроде бы я понимаю, почему. GetFromFile же собирает информацию с внешних файлов, не на стадии сборки проекта.

С imm32 я вообще не разобрался.


C++:
    void PatchMss32(Union::Dll module, void* patchWhat, void* patchFor)
    {
        static Union::ProcessImm32Collection* imm32coll = Union::ProcessImm32Collection::CreateSpecificCollection();
        imm32coll->AnalizeModule(&module);

        Union::Array<void*> addresses;
        Union::Array<void*> offsets;
        imm32coll->GetImm32For();

        for (auto&& it : addresses) {
            Union::ulong protection = PAGE_EXECUTE_READWRITE;
            VirtualProtect(it, 4, protection, &protection);
            *(void**)it = patchFor;
            VirtualProtect(it, 4, protection, &protection);
        }
    }

Не понятно в общем, как хукать так, чтобы адрес сам проставлялся. Чтобы обращение из хука не конфликтовало с другими плагинами. И, видимо, не нужно было пока на Union Framework переходить, чтоли.
 
Последнее редактирование:

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
494
Благодарности
337
Баллы
230
RPD, попробуй зайти с другой стороны:
см. Union (патч для Gothic) -> Детально -> Этапы загрузки Union -> п. 2, 4. Начни с четвёртого. Если тебе удобнее, пробуй на старом API.
Задача сводится к тому, чтобы первее всех перехватить нужную функцию, ну а дальше выполнить свой код и вызвать настоящую функцию.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.361
Благодарности
4.688
Баллы
625
Проблема в том, что детор union framework конкурирует с детором из обычного union, и там нужен адаптер, чтобы хуки могли согласовываться.
Но если мой диск в ремонте не починят, то не будет вам никаких адаптеров. Я плевать хотел еще раз эту шляпу писать.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Сама библиотека то есть и она почти работает. Последних правок в репозитории union нету.

То есть я придумывал то, что впринципе в моем проекте не нужно? Усложняю все? Получается, что вся эта шняга с imm32 излишне? Нсли так, то это шикарно. Я ведь на полном серьезе сидел и разбирался в классах самого Union'a и пытался понять, почему код с вики у меня не работает
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.361
Благодарности
4.688
Баллы
625
Вообще не надо использовать детор, если отрабатывает патч. Конкуренция за пролог может быть и на стороне того же дх11.
Ну и в отличии от union, framework корректно анализирует загружаемые и выгружаемые библиотеки, когда патч хуки уже были развешаны по адресам.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Вообще не надо использовать детор, если отрабатывает патч. Конкуренция за пролог может быть и на стороне того же дх11.
Ну и в отличии от union, framework корректно анализирует загружаемые и выгружа
С dx11 уже на своей шкуре испытал,хотел дальность прорисовки нпс увеличить, с ida пролазал все, что мог и большинство функций просто не перехватывались. Если резюмировать, что можете по итогу мне посоветовать? Думаю адаптер я поставляю, а каким образом он делу поможет? После его установки я смогу просто обычными хуками пользоваться, не анализируя длл? (второго я даже и не умею)
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.361
Благодарности
4.688
Баллы
625
Адаптер без union не заработает сам по себе. А union на корпоративном микроне, который за свою цену должен не то что не ломаться, но еще и кофе варить.
Коротко говоря, задача была перекинуть весь старый механизм перехвата на framework.

Во-первых я вообще не уверен что ты можешь влиять на дальность прорисовки нпс, используя дх11.
Во-вторых даже если так, то патчить надо непосредственно кусок кода, ответственный за это. А не хукать функцию целиком.
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Адаптер без union не заработает сам по себе. А union на корпоративном микроне, который за свою цену должен не то что не ломаться, но еще и кофе варить.
Коротко говоря, задача была перекинуть весь старый механизм перехвата на framework.

Во-первых я вообще не уверен что ты можешь влиять на дальность прорисовки нпс, используя дх11.
Во-вторых даже если так, то патчить надо непосредственно кусок кода, ответственный за это. А не хукать функцию целиком.
Правильно понимаю, что через CreatePartialHook? На вики просто информации не сильно много, поэтому приходится додумывать самому.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.361
Благодарности
4.688
Баллы
625
Правильно. Это при условии ты знаешь что и где хочешь менять. В патчах системпака какие-то правки на дальность были. Если они работают только на ваниле, то патчить придется дх11, что бред по определению
 

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Правильно. Это при условии ты знаешь что и где хочешь менять. В патчах системпака какие-то правки на дальность были. Если они работают только на ваниле, то патчить придется дх11, что бред по определению
Я думал, что как раз поиск по сигнатурам или использование imm32 инструкций решает эту проблему, что адреса и оффсетымогут меняться и в рантайме можно подхватить и вызвать в моменте именно нужную функциюпо нужному адресу, а получается это далеко не так просто? Я еще двадня назад пытался искать адреса в dll DX11 и думал, что занимаюсь полной херней, что это не правильно. А полчается что это единственный способ? Так то да, задача изменять прорисовку нпс с dx11, без него проблем не возникает, просто по той причине, что адреса всех функций, которые хоть как то с этим связаны, можно спокойно посмотреть через ida, дизассеблив экзешник. А вот в такой ситуации я не могу просто обращаться к тем же адресам, хуки не работают. По крайней мере до сего момента у меня так и не получилось. Правда частичный хук я не пробовал, но не думаю, что это поможет, если адресс все равно уже будет другим.

Но кстати просто для полной картины еще раз напишу, что я пытался создавать хуки на функции открывания и закрывания инвентаря oCNpcInventory::Open, oCNpcInventory::Close. С отключенными модификациями хуки отрабатывали отлично, с хотя бы даже включенным Union Advanced Inventory уже нет. Но, видимо, дело тут как раз в конфликте детуров, как я понимаю
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.361
Благодарности
4.688
Баллы
625
Ты можешь патчить любую библиотеку, но если твоя загружена раньше. В противном случае надо отслеживать загружаемые в память дллки в рантайме. Поиск по сигнатурам реален, если знаешь, что делаешь.

 

RPD

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

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

C++:
Union::SignatureFile* signFile = Union::SignatureFile::GetFromFile("Names.txt");
auto compSign = signFile->FindSimilarSignature(&baseSign);
return compSign ? compSign->GetAddress() : nullptr;


Все равно не работало. Но оно ищет из файла, внешнего. Не из длл. А сигнатуры из длл разве не через Union:: Dll<метод> берутся? Нужно к SharedMemory напрямую обращаться?
 
Последнее редактирование:

RPD

Участник форума
Регистрация
13 Ноя 2023
Сообщения
134
Благодарности
3
Баллы
40
Правильно. Это при условии ты знаешь что и где хочешь менять. В патчах системпака какие-то правки на дальность были. Если они работают только на ваниле, то патчить придется дх11, что бред по определению
С частичным хуком вроде ничего не конфликтует. По крайней мере oCNpcInventory::Close (Open) не конфликтуют с Advanced Inventory. Хотя адрес я статический поставил. Буду пробовать с прорисовкой нпс теперь.
 
Сверху Снизу