-
Ben80
имя: Сергей
- Эксперт
-
- Сообщения: 1318
- Зарегистрирован: 18 июн 2017, 06:49
- Пол:
- Поблагодарили: 336 раз.
|
Ben80 » 09 окт 2017, 04:06
Александр, посмотрите, пожалуйста, мой старый код, который я доработал. Вот он работает так, как задумано. И все достаточно просто. На клею, примитивно, но работает. Хотя бы поэтому его стоит посмотреть. FirstDec должен быть, конечно, массивом на N героев. - Код: Выделить всё
#include "..\..\include\homm3.h"
Patcher* _P; PatcherInstance* _PI;
static _bool_ plugin_On = 0;
const int ghostHeroHookAddr[] = {0x41664C, 0x4DE583, 0x5D44A0, 0x5D451D}; _Hero_* ghostHero = new _Hero_();
// Выбранный селектор в диалоге (унифицированное значение, не равное выбранному на ползунке) int selNumber; bool cancelSpell = false; bool FirstDec = true;
// Создаём стандартный задник с рамкой цвета игрока void setStdBackground(_Dlg_* dlg) { CALL_5 (int, __thiscall, 0x48FA80, dlg, dlg->x, dlg->y, dlg->width, dlg->height);
for (int i = dlg->field_4C; i <= dlg->field_50; ++i) { CALL_5 (int, __thiscall, 0x5FF400, dlg, 512, 13, i, o_GameMgr->GetMeID()); } }
void __fastcall scrollDlgCallback_1(int click_id, _Dlg_* dlg) { // Выводим в текстовое поле текущее значение, выбранное с помощью ползунка // click_id; // Уровень Магии воздуха определяет доступные для выбора значения
if(click_id == 0) sprintf(o_TextBuffer, "%s", "Поменьше"); if(click_id == 1) sprintf(o_TextBuffer, "%s", "Побольше"); // селектор - преобразуем выбранный номер к унифицированной последовательности selNumber = click_id + 4;
((_DlgStaticText_*)dlg->GetItem(14))->SetText(o_TextBuffer);
_DlgMsg_ m = {512, 3, 40, 0, 0, 0, 0, 0}; CALL_2 (void, __thiscall, 0x5FF3A0, dlg, &m); dlg->Redraw(TRUE); }
void __fastcall scrollDlgCallback_2(int click_id, _Dlg_* dlg) { // Выводим в текстовое поле текущее значение, выбранное с помощью ползунка // click_id; // Уровень Магии воздуха определяет доступные для выбора значения
if(click_id == 0) sprintf(o_TextBuffer, "%s", "В 2 раза\nменьше"); if(click_id == 1) sprintf(o_TextBuffer, "%s", "Поменьше"); if(click_id == 2) sprintf(o_TextBuffer, "%s", "Побольше"); if(click_id == 3) sprintf(o_TextBuffer, "%s", "В 2 раза\nбольше"); // селектор - преобразуем выбранный номер к унифицированной последовательности selNumber = click_id + 3;
((_DlgStaticText_*)dlg->GetItem(14))->SetText(o_TextBuffer);
_DlgMsg_ m = {512, 3, 40, 0, 0, 0, 0, 0}; CALL_2 (void, __thiscall, 0x5FF3A0, dlg, &m); dlg->Redraw(TRUE); }
void __fastcall scrollDlgCallback_3(int click_id, _Dlg_* dlg) { // Выводим в текстовое поле текущее значение, выбранное с помощью ползунка // click_id; // Уровень Магии воздуха определяет доступные для выбора значения
if(click_id == 0) sprintf(o_TextBuffer, "%s", "В 5 раз\nменьше"); if(click_id == 1) sprintf(o_TextBuffer, "%s", "В 3 раза\nменьше"); if(click_id == 2) sprintf(o_TextBuffer, "%s", "В 2 раза\nменьше"); if(click_id == 3) sprintf(o_TextBuffer, "%s", "Поменьше"); if(click_id == 4) sprintf(o_TextBuffer, "%s", "Побольше"); if(click_id == 5) sprintf(o_TextBuffer, "%s", "В 2 раза\nбольше"); if(click_id == 6) sprintf(o_TextBuffer, "%s", "В 3 раза\nбольше"); if(click_id == 7) sprintf(o_TextBuffer, "%s", "В 5 раз\nбольше"); // селектор - преобразуем выбранный номер к унифицированной последовательности selNumber = click_id + 1;
((_DlgStaticText_*)dlg->GetItem(14))->SetText(o_TextBuffer);
_DlgMsg_ m = {512, 3, 40, 0, 0, 0, 0, 0}; CALL_2 (void, __thiscall, 0x5FF3A0, dlg, &m); dlg->Redraw(TRUE); }
void yDlgShow(int width, int height, int count, char* captionText, char* messageText, bool middle = true, int x = 0, int y = 0) { // Создаём по центру экрана пустой диалог с тенью _Dlg_* dlg = _CustomDlg_::Create(DLG_X_CENTER, DLG_Y_CENTER, width, height, DF_SCREENSHOT | DF_SHADOW, NULL); // Добавляем задник (фон) и рамку по цвету игрока setStdBackground(dlg); // Добавляем заголовок диалога dlg->AddItem(_DlgStaticText_::Create(0, 20, dlg->width, 30, captionText, "bigfont.fnt", 7, 1, ALIGN_H_CENTER | ALIGN_V_TOP, 0));
// Добавляем текст dlg->AddItem(_DlgStaticText_::Create(0, 50, dlg->width, 50, messageText, "medfont.fnt", 1, 0, ALIGN_H_CENTER | ALIGN_V_TOP, 0));
// Добавляем полосу горизонтальной прокрутки //dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count, // (_ptr_)scrollDlgCallback, 0, 18, 0)); // Добавляем текстовое поле для отображения значений, выбираемых с помощью ползунка if(count == 2) { dlg->AddItem(_DlgStaticText_::Create((dlg->width - 72) / 2 + 1, dlg->height - 65, 72, 40, "Поменьше", "medfont.fnt", 1, 14, ALIGN_H_CENTER | ALIGN_V_CENTER, 0)); dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count, (_ptr_)scrollDlgCallback_1, 0, 0, 0)); selNumber = 4; } if(count == 4) { dlg->AddItem(_DlgStaticText_::Create((dlg->width - 72) / 2 + 1, dlg->height - 65, 72, 40, "В 2 раза\nменьше", "medfont.fnt", 1, 14, ALIGN_H_CENTER | ALIGN_V_CENTER, 0)); dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count, (_ptr_)scrollDlgCallback_2, 0, 0, 0)); selNumber = 3; } if(count == 8) { dlg->AddItem(_DlgStaticText_::Create((dlg->width - 72) / 2 + 1, dlg->height - 65, 72, 40, "В 5 раз\nменьше", "medfont.fnt", 1, 14, ALIGN_H_CENTER | ALIGN_V_CENTER, 0)); dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count, (_ptr_)scrollDlgCallback_3, 0, 0, 0)); selNumber = 1; }
// Добавляем кнопку OK dlg->AddItem(_DlgStaticPcx8_::Create(30, dlg->height - 61, 0, "Box64x30.pcx")); dlg->AddItem(_DlgButton_::Create(31, dlg->height - 60, 64, 30, 30722, "iOkay.def", 0, 1, 1, 28, 2));
// Добавляем кнопку Cancel dlg->AddItem(_DlgStaticPcx8_::Create(dlg->width - 31 - 64, dlg->height - 61, 0, "Box64x30.pcx")); dlg->AddItem(_DlgButton_::Create(dlg->width - 30 - 64, dlg->height - 60, 64, 30, 30721, "iCancel.def", 0, 1, 1, 1, 2));
if ( !middle ) dlg->SetPos(x, y); dlg->Run(); dlg->Destroy(TRUE); }
float __stdcall getUnpackedMultiplier(int n) { float selFloat[8] = {0.2, 0.333, 0.5, 0.666, 1.5, 2.0, 3.0, 5.0}; return selFloat[n/2 - 1]; }
int __stdcall makeGhostHero(LoHook* h, HookContext* c) { _Hero_* hero; int* heroReg; float multiplier = 1.0;
h->GetAddress() == ghostHeroHookAddr[0] ? heroReg = &c->esi : heroReg = &c->eax; hero = *(_Hero_**)heroReg; if ( hero->disguise != -1) { // Копируем героя в "призрачного" героя *ghostHero = *hero; // Своих героев просматриваем в истинном виде (в оригинальной игре это не так) //if(hero->owner_id != o_GameMgr->GetMeID()) multiplier = getUnpackedMultiplier((int)hero->disguise);
ghostHero->disguise = -1; for (int i = 0; i < 7; ++i) { ghostHero->army.count[i] = ghostHero->army.count[i] * multiplier; } *(int*)heroReg = (int)ghostHero; }
return EXEC_DEFAULT; }
int __stdcall decPackedDisguise(LoHook* h, HookContext* c) { for (int i = 0; i < o_HEROES_COUNT; ++i) { if ( o_GameMgr->GetHero(i)->owner_id == o_GameMgr->GetMeID() && o_GameMgr->GetHero(i)->disguise != -1 && o_ActivePlayer->IsHuman()) { if(((int)(o_GameMgr->GetHero(i)->disguise)) % 2 == 0) { o_GameMgr->GetHero(i)->disguise = -1; FirstDec = true; } else if(FirstDec == false || o_NetworkGame == false) { --o_GameMgr->GetHero(i)->disguise; } else FirstDec = false; } }
return EXEC_DEFAULT; }
int __stdcall setPackedDisguise(LoHook* h, HookContext* c) { // Получаем количество делений для ползунка исходя из уровня Магии воздуха int local_ecx = c->ecx; int local_eax = c->eax; cancelSpell = false; int arPos[4] = {2,2,4,8}; int nPos = arPos[*(char*)(c->esi + 201 + 15)]; // Если герой скастовал Disguise, показываем диалог //yDlgShow(240, 140, nPos, "Маскировка", "Выберите мнимую\nсилу отрядов"); yDlgShow(300, 175, nPos, "Маскировка", "Выберите мнимую\nсилу отрядов"); // Если нажата кнопка OK (30722), то формируем поле disguise у героя, // проигрываем WAV файл // иначе - возвращаем герою израсходованную ману if ( o_WndMgr->result_dlg_item_id == 30722 ) { c->edi = selNumber * 2 + 1; //c->eax = 0x6854A0; //c->ecx = *(int*)(0x6856C4); //CALL_0(__int64, __fastcall, 0x59A770); //c->ecx = local_ecx; //c->eax = local_eax; } else { c->edi = -1; cancelSpell = true; }
return EXEC_DEFAULT; }
int __stdcall cancelSpellCost(LoHook* h, HookContext* c) { if(cancelSpell == true) c->eax = 0;
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.NewDisguise");
_PI->WriteHexPatch(0x4C7DA5, "90 90 90"); //_PI->WriteHexPatch(0x41C7BA, "90 90 90 90 90"); _PI->WriteLoHook(0x4C700B, decPackedDisguise); _PI->WriteLoHook(0x41C7C6, setPackedDisguise); _PI->WriteLoHook(0x41C7DD, cancelSpellCost); for (int i = 0; i < 4; ++i) _PI->WriteLoHook(ghostHeroHookAddr[i], makeGhostHero); } }
return TRUE; }
Последний раз редактировалось Ben80 09 окт 2017, 04:37, всего редактировалось 2 раз(а).
|