-
AlexSpl
имя: Александр
- Эксперт
-
- Сообщения: 5587
- Зарегистрирован: 17 сен 2010, 12:58
- Пол:
- Награды: 14
-
-
- Поблагодарили: 2185 раз.
|
AlexSpl » 12 сен 2017, 14:20
Напишите, пожалуйста, полный код для плагина, который у Вас получился. Вот код плагина для Eagle Eye (на основе Вашего кода): - Код: Выделить всё
#define _CRT_RAND_S #define _CRT_SECURE_NO_WARNINGS #include "HotA\homm3.h"
Patcher* _P; PatcherInstance* _PI;
static _bool_ plugin_On = 0;
struct PicStruc { int type; // тип картинки (9 - заклинание) int id; // ID картинки };
// кастомный _List_ struct List { _ptr_ Creation; PicStruc* Data; _ptr_ EndData; _ptr_ EndMem; };
int captionAddr;
// Заголовок в каждом диалоге int __stdcall saveCaption(LoHook* h, HookContext* c) { captionAddr = c->ecx; return EXEC_DEFAULT; }
int __stdcall captionFix(LoHook* h, HookContext* c) { *(int*)(c->ebp - 0x14) = captionAddr; return EXEC_DEFAULT; }
int __stdcall showSpellDlg(_Hero_* hero, int spells[], int nPics) { if ( !nPics ) return 0;
List picList; // Динамический массив картинок // Первый и последний элемент резервируем для полей Creation и EndData/EndMem соответственно PicStruc* pic = new PicStruc[nPics + 2];
for (int i = 0; i < nPics; ++i) { pic[i + 1].type = 9; pic[i + 1].id = spells[i]; } picList.Creation = (_ptr_)pic + 4; picList.Data = &pic[1]; // Адрес первого элемента в списке picList.EndData = (_ptr_)pic + (nPics + 1) * 8; // Адрес следующего за последним элементом в списке байта picList.EndMem = picList.EndData; sprintf(o_TextBuffer, "Благодаря навыку {Орлиный глаз}, {%s} выучил%s следующ%s заклинан%s:", hero->name, hero->sex ? "а" : "", nPics > 1 ? "ие" : "ее", nPics > 1 ? "ия" : "ие"); CALL_5(unsigned int, __fastcall, 0x4F7D20, o_TextBuffer, &picList, -1, -1, 0);
delete [] pic; return 0; }
int getEagleEyeSpells(_Hero_* hero, _Hero_* heroDonor, int spells[]) { int n = 0; unsigned int eagleEyeProb = (unsigned int)(CALL_1(float, __thiscall, 0x4E4690, hero) * 100.0f);
for (_Spell_* iSpell = o_Spell + SPL_QUICKSAND; iSpell <= o_Spell + SPL_AIR_ELEMENTAL; ++iSpell) { int i = iSpell - o_Spell; if ( heroDonor->spell_level[i] && !hero->spell[i] ) { if ( iSpell->level <= hero->second_skill[HSS_EAGLE_EYE] + 1 ) { unsigned int dice; rand_s(&dice); dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 100.0) + 1; if ( dice <= eagleEyeProb ) { spells[n++] = i; hero->spell[i] = 1; hero->spell_level[i] = 1; } } } }
return n; }
int __stdcall eagleEyeMain(LoHook* h, HookContext* c) { _Hero_* attHero = o_BattleMgr->hero[ATTACKER]; _Hero_* defHero = o_BattleMgr->hero[DEFENDER]; if ( attHero && defHero ) { int spells[70];
if ( attHero->second_skill[HSS_EAGLE_EYE] && attHero->DoesWearArtifact(AID_SPELL_BOOK) ) showSpellDlg(attHero, spells, getEagleEyeSpells(attHero, defHero, spells)); if ( defHero->second_skill[HSS_EAGLE_EYE] && defHero->DoesWearArtifact(AID_SPELL_BOOK) ) showSpellDlg(defHero, spells, getEagleEyeSpells(defHero, attHero, spells)); } 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("HD.Plugin.NewEagleEye");
// Меняем коэффициенты float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f}; _PI->WriteDword(0x63EA2C, *(int*)&eagleEyeCoefs[1]); _PI->WriteDword(0x63EA30, *(int*)&eagleEyeCoefs[2]); _PI->WriteDword(0x63EA34, *(int*)&eagleEyeCoefs[3]);
// Убираем оригинальный эффект _PI->WriteHexPatch(0x469C23, "EB"); _PI->WriteHexPatch(0x476996, "E9 DD 01 00 00"); // Фиксим заголовок диалога _PI->WriteLoHook(0x4F7D49, saveCaption); _PI->WriteLoHook(0x4F7D54, captionFix); _PI->WriteLoHook(0x462C7D, eagleEyeMain); } } return TRUE; }
Плагин для тестов: Осталось только написать код для сетевой игры. Я эти значения все равно получаю компиляцией тестовой программы на ассемблере, которую смотрю в OllyDbg. Там уже все в инвертированном виде. Другого способа не придумал. См. код выше. Так удобнее: - Код: Выделить всё
// Меняем коэффициенты float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f}; _PI->WriteDword(0x63EA2C, *(int*)&eagleEyeCoefs[1]); _PI->WriteDword(0x63EA30, *(int*)&eagleEyeCoefs[2]); _PI->WriteDword(0x63EA34, *(int*)&eagleEyeCoefs[3]);
* * * UPD Заменил неблагозвучное DoesHasArtifact(AID_SPELL_BOOK) на DoesWearArtifact(AID_SPELL_BOOK), тем более так правильнее.
|