-
as239
имя: Анатолий
- Ветеран
-
- Сообщения: 527
- Зарегистрирован: 29 дек 2018, 14:17
- Пол:
- Поблагодарили: 38 раз.
-
|
as239 » 04 фев 2019, 18:18
Нужно, чтобы ещё кто-то dll-ку проверил. Очень странно, что собранная не работает. Попробуйте отключить hw_rules. Уже вижу, что хук для Утопы Вы пропустили. Киньте весь текст плагина. UPD: Потестил. У меня работает и с hw_rules и c NewCrBanks. Вот весь код, хук на утопию добавил, теперь там выводится строка во всю ширину экрану с непонятыми символами: - Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS #define HK_E 18 #include "homm3.h" #include <string>
using namespace std;
Patcher* _P; PatcherInstance* _PI; static _bool_ plugin_On = 0;
#define CREATURE_INFO_OFFSET (*(_ptr_*)0x47ADD1) #define o_CreatureInfo ((_CreatureInfo_*)CREATURE_INFO_OFFSET)
int sEBX; int originalCreatureID; char originalCreatureN; // //------------------------------------------------------------------------------------------------------- //igrik int __stdcall Y_SpellShow(LoHook* h, HookContext* c) { // цифровое отображение длительности заклинаний (вытащено из HotA.dll) int Spell = *(int*)(c->esi); int DlgShow = *(int*)(c->ebp-40); if (Spell >=0) { if (Spell == 47 || Spell == 59 || Spell == 72) int Spell = 47; else { sprintf(o_TextBuffer, "x%d", *(int*)(c->esi+12)); int SpellNew = CALL_1 (int, __cdecl, 6386834, 80); int SpellShow = CALL_12 (int, __thiscall, 6014624, SpellNew, *(int*)(c->ebp-28), 202, 46, 20, o_TextBuffer, "tiny.fnt", 4, 3003 - *(int*)(c->ebp-32), 10, 0, 8); CALL_4 (int, __thiscall, 0x5FE2D0, DlgShow + 48, *(int*)(DlgShow +56), 1, &SpellShow); } } return EXEC_DEFAULT; }
int __stdcall Y_SpellInfo1(LoHook* h, HookContext* c) { // в этой функции я не смог поставить HiHook // потому что в WoGе после её выполнения вылетает if( c->eax >= 3000 && c->eax <= 3007 ) { switch (c->eax){ case 3000: c->eax = 11; break; // спелл_1 case 3001: c->eax = 11; break; // спелл_2 case 3002: c->eax = 11; break; // спелл_3 case 3006: c->eax = 9; break; // мораль case 3007: c->eax = 10; break; // удача default: c->eax = -1; break; // на всякий } c->return_address = 0x5F4B34; return NO_EXEC_DEFAULT; } return EXEC_DEFAULT; }
int __stdcall Y_SpellInfo2(LoHook* h, HookContext* c) { // подсказка для циферных отображений спеллов, морали и удачи switch (c->esi){ case 3000: c->esi = 221; break; // спелл_1 case 3001: c->esi = 222; break; // спелл_2 case 3002: c->esi = 223; break; // спелл_3 case 3006: c->esi = 219; break; // мораль case 3007: c->esi = 220; break; // удача } return EXEC_DEFAULT; }
int __stdcall Y_SpellShow1(LoHook* h, HookContext* c) { int New = CALL_1 (int, __cdecl, 0x617492, 80); int SpellShow = CALL_12 (int, __thiscall, 6014624, New, 15, c->ebx + 16, 46, 20, "", "tiny.fnt", 4, c->edi + 3003, 10, 0, 8); CALL_4 (int, __thiscall, 0x4230D0, c->esi, *(int*)(c->esi + 8), 1, &SpellShow); return EXEC_DEFAULT; }
int __stdcall Y_SpellShow2(LoHook* h, HookContext* c) { int New = CALL_1 (int, __cdecl, 0x617492, 80); int SpellShow = CALL_12 (int, __thiscall, 6014624, New, 15, *(int*)(c->ebp + 24) + 16, 46, 20, "", "tiny.fnt", 4, c->ebx + 3003, 10, 0, 8); CALL_4 (int, __thiscall, 0x4230D0, c->esi, *(int*)(c->esi + 8), 1, &SpellShow); return EXEC_DEFAULT; }
int __stdcall Y_SpellShow3(LoHook* h, HookContext* c) { _Dlg_* dlg = (_Dlg_*)(c->edi + 56); int item = 3006 - *(int*)(c->ebp + 8); int spell = *(int*)c->esp - 1;
if (spell >= 0 && spell != 47 && spell != 59 && spell != 72) sprintf(o_TextBuffer, "x%d", *(int*)(c->esi + 4 * spell + 408)); else sprintf(o_TextBuffer, "");
((_DlgStaticText_*)dlg->GetItem(item))->SetText(o_TextBuffer);
return EXEC_DEFAULT; }
int __stdcall Y_DlgTown_Proc(HiHook* hook, _TownMgr_* tm, _EventMsg_* klick) { int res = CALL_2(int, __thiscall, hook->GetDefaultFunc(), tm, klick);
if (res) { if (klick->type == 2 && klick->subtype == HK_E) { int heroU_id = tm->town->up_hero_id; int heroD_id = tm->town->down_hero_id;
if ( heroU_id != -1 && heroD_id != -1) { _Hero_* heroU = o_GameMgr->GetHero(heroU_id); _Hero_* heroD = o_GameMgr->GetHero(heroD_id);
CALL_2(void, __fastcall, 0x4A25B0, heroU, heroD); CALL_3(void, __thiscall, 0x4AAA60, o_AdvMgr, heroU, heroD);
// делаем автоматический выход из окна города o_WndMgr->result_dlg_item_id = 0x7800; klick->type = 0x4000; klick->subtype = 1; klick->item_id = 10;
return 2; } } } return res; } // //------------------------------------------------------------------------------------------------------- //AlexSPL int __stdcall setCreatureBankReward(LoHook* h, HookContext* c) { // const char TownType = o_GameMgr->GetTown(o_ActivePlayer->towns_ids[0])->type; const int TownType = *(int*)o_GameMgr->Offset(0x1F6A0 + 0x10 + o_ActivePlayerID * 4);
const int Lvl6CreatureID = TownType == 8 ? CID_PSYCHIC_ELEMENTAL : 10 + TownType * 14; const int Lvl7CreatureID = TownType == 8 ? CID_FIREBIRD : 12 + TownType * 14;
sEBX = c->ebx; originalCreatureID = *(int*)(c->ebx + 0x54); originalCreatureN = *(char*)(c->ebx + 0x58);
switch ( originalCreatureID ) { // Меняем Ангелов case CID_ANGEL: *(int*)(c->ebx + 0x54) = Lvl7CreatureID; *(char*)(c->ebx + 0x58) = originalCreatureN * 200 / (o_CreatureInfo + Lvl7CreatureID)->hit_points; // N if ( *(char*)(c->ebx + 0x58) < 1 ) *(char*)(c->ebx + 0x58) = 1; break;
// Меняем Виверн case CID_WYVERN: *(int*)(c->ebx + 0x54) = Lvl6CreatureID; *(char*)(c->ebx + 0x58) = originalCreatureN * 70 / (o_CreatureInfo + Lvl6CreatureID)->hit_points; // N if ( *(char*)(c->ebx + 0x58) < 1 ) *(char*)(c->ebx + 0x58) = 1; break; } return EXEC_DEFAULT; }
int __stdcall restoreOriginalReward(LoHook* h, HookContext* c) { *(int*)(sEBX + 0x54) = originalCreatureID; *(char*)(sEBX + 0x58) = originalCreatureN;
return EXEC_DEFAULT; }
//int __stdcall newTownShortcut(LoHook* h, HookContext* c) //{ // if ( c->edx == 0x12 ) { // _Hero_* hero1 = o_GameMgr->GetHero(o_TownMgr->town->up_hero_id); // _Hero_* hero2 = o_GameMgr->GetHero(o_TownMgr->town->down_hero_id); // // if ( *(int*)hero1 && *(int*)hero2 ) { // CALL_2(int, __fastcall, 0x4A25B0, hero1, hero2); // Показываем диалог Грамотности // CALL_1(int, __thiscall, 0x5C75B0, o_TownMgr); // Выходим из города (ExitTownScreen) // CALL_3(int, __thiscall, 0x4AAA60, o_AdvMgr, hero1, hero2); // Показываем диалог встречи героев // CALL_2(int, __thiscall, 0x5C67C0, o_TownMgr, 0); // Снова заходим в город (EnterTownScreen) // } // } // // return EXEC_DEFAULT; //} int __stdcall patchDll(LoHook* h, HookContext* c) { //Первая версия+ //HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll"); //char MageGuildPatch = 0xEB; //SIZE_T BytesWritten; //int DllPatchAddress = (int)hHW_SOD + 0xFE2C; //WriteProcessMemory(GetCurrentProcess(), (LPVOID)DllPatchAddress, &MageGuildPatch, 1, &BytesWritten); //Первая версия-
HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll"); _PI->WriteByte((int)hHW_SOD + 0xFE2C, 0xEB);
//_PI->WriteLoHook((int)GetModuleHandleA("HD_SOD.dll") + 0x10FDC, newTownShortcut);
return EXEC_DEFAULT; }
string getInterval(int n) { string str = "1-4"; if ( n > 999 ) str = "1000+"; else if ( n > 499 ) str = "500-999"; else if ( n > 249 ) str = "250-499"; else if ( n > 99 ) str = "100-249"; else if ( n > 49 ) str = "50-99"; else if ( n > 19 ) str = "20-49"; else if ( n > 9 ) str = "10-19"; else if ( n > 4 ) str = "5-9"; return str; }
int __stdcall showGuards(LoHook* h, HookContext* c) { bool isUtopia = h->GetAddress() == 0x4A1E56;
// Получаем состояние банка _CrBankState_* bankState = (_CrBankState_*)CALL_1(int, __fastcall, 0x405D80, isUtopia ? c->edi : c->ebx);
int CreaturesCount = bankState->defenders.GetCreaturesCount(); string str = (char*)c->ecx; // Оригинальное сообщение str = str + "\n\nAmount: " + getInterval(CreaturesCount); // Утопия? if ( isUtopia ) { str = str + " (" + getInterval(bankState->defenders.count[0]) + ", " + getInterval(bankState->defenders.count[1]) + ", " + getInterval(bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[3]) + ")"; } else // Если есть грейд if ( bankState->defenders.type[2] != bankState->defenders.type[0]) { str = str + " (" + getInterval(CreaturesCount - bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[2]) + ")"; } // Передаём адрес текстового буфера в качестве аргумента для диалога sprintf(o_TextBuffer, "%s", str); c->ecx = (int)o_TextBuffer; return EXEC_DEFAULT; }
// //------------------------------------------------------------------------------------------------------- //MAIN 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("HD.Plugin.FreshMod"); //------------------------------------------------------------------------------------------------ //AlexSPL _PI->WriteLoHook(0x4ABBFA, setCreatureBankReward); _PI->WriteLoHook(0x4AC168, restoreOriginalReward); //Перестройка ГМ с любого уровня _PI->WriteLoHook(0x598510 /* перед загрузкой .vid */, patchDll); //------------------------------------------------------------------------------------------------ //igrik // возможность заходить в гильдию магов без наличия книги и денег у героя-гостя _PI->WriteHexPatch(0x5CEA83, "EB74"); _PI->WriteHexPatch(0x5CEACD, "2800"); // Патч на tiny.fnt малые описания монстров (все в DEC) *(int*)6243434 = 6687924; // в бою *(int*)6244485 = 6687924; // при покупке *(int*)6241855 = 6687924; // не в бою // отображение длительности заклинаний в окне монстра (вытащено из HotA.dll) _PI->WriteLoHook(0x5F6BE2, Y_SpellShow); _PI->WriteLoHook(0x5F4B05, Y_SpellInfo1); // тут WoG/ERA не дают поставить HiHook _PI->WriteLoHook(0x5F522A, Y_SpellInfo2); // отображение длительности заклинаний в расширенной статистике (вытащено из HotA.dll) _PI->WriteLoHook(0x46D12B, Y_SpellShow1); _PI->WriteLoHook(0x46D4CB, Y_SpellShow2); _PI->WriteLoHook(0x46D9F0, Y_SpellShow3); //Обмен между героями в городе _PI->WriteHiHook(0x5D3640, SPLICE_, EXTENDED_, THISCALL_, Y_DlgTown_Proc);
//Отображение охраны _PI->WriteLoHook(0x4A13E6, showGuards); _PI->WriteLoHook(0x4A1E56, showGuards);
} }
return TRUE; }
|