Цитата:
- Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "..\..\HotA\homm3.h"
Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;
bool __stdcall changeLMSpells(HiHook* hook)
{
bool res = CALL_0(bool, __cdecl, hook->GetDefaultFunc());
int LMEffects[] = {1, 1, 2, 3};
for (int i = 0; i < 4; ++i)
{
o_Spell[SPL_MIRTH].effect[i] = LMEffects[i];
o_Spell[SPL_SORROW].effect[i] = -LMEffects[i];
o_Spell[SPL_FORTUNE].effect[i] = LMEffects[i];
o_Spell[SPL_MISFORTUNE].effect[i] = -LMEffects[i];
}
// Здесь заодно можно поменять описания
return res;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
{
if ( !plugin_On )
{
plugin_On = 1;
_P = GetPatcher();
_PI = _P->CreateInstance((char*)"HD.Plugin.LMSpells");
// HiHook on loading sptraits.txt
_PI->WriteHiHook(0x4EDEAF, SPLICE_, EXTENDED_, THISCALL_, changeLMSpells);
}
}
return TRUE;
}
Только учтите, что у этих заклинаний свой собственный кап (-3..+3) Морали и Удачи.
Насчёт возвращаемого типа bool vs char vs int. Считаю, что в исходниках был логический тип bool (false - файл sptraits.txt не удалось загрузить/файл загружен с ошибками, true - файл загружен успешно). Но здесь не будет ошибкой использовать char или даже int в качестве возвращаемого HiHook'ом типа. Насчёт соглашения о вызове __cdecl vs __stdcall. У функции нет аргументов, поэтому используем __cdecl, т.к. это соглашение о вызове в MVS используется по умолчанию.
* * *
Цитата:
Сделать это можно в том же хайхуке. Думаю, у Вас получится.
* * *
Замечание о TXT-файлах, загружаемых из LOD-архива. Для всех задач, которые требуют изменения данных в TXT-файлах ресурсов игры, можно использовать единый адрес для LoHook: 0x4EE006 (сразу после загрузки всех TXT-файлов), а не ставить хайхуки на каждую функцию загрузки текстовика по отдельности.
Пример.
- Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "..\..\HotA\homm3.h"
Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;
int __stdcall changeLMSpells(LoHook* h, HookContext* c)
{
int LMEffects[] = {1, 1, 2, 3};
for (int i = 0; i < 4; ++i)
{
o_Spell[SPL_MIRTH].effect[i] = LMEffects[i];
o_Spell[SPL_SORROW].effect[i] = -LMEffects[i];
o_Spell[SPL_FORTUNE].effect[i] = LMEffects[i];
o_Spell[SPL_MISFORTUNE].effect[i] = -LMEffects[i];
}
// Здесь заодно можно поменять описания
return EXEC_DEFAULT;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
{
if ( !plugin_On )
{
plugin_On = 1;
_P = GetPatcher();
_PI = _P->CreateInstance((char*)"HD.Plugin.LMSpells");
// LoHook after loading all text files
_PI->WriteLoHook(0x4EE006, changeLMSpells);
}
}
return TRUE;
}
В этот лоухук можно поместить весь код, связанный с работой с текстовыми ресурсами LOD.
Так... Кроме camptext.txt Тогда LoHook можно поставить ниже (например, здесь: 0x4EE1C1) или обернуть функцию 0x4EDCE0 HiHook'ом.