-
Ben80
имя: Сергей
- Эксперт
-
- Сообщения: 1318
- Зарегистрирован: 18 июн 2017, 06:49
- Пол:
- Поблагодарили: 336 раз.
|
Ben80 » 09 авг 2023, 13:26
Плагин, корректирующий изменение очков движения героев.(только для английской версии 2.1) В оригинальной игре очки движения (MP) рассчитываются только в начале хода (лишь при взаимодействии с некоторыми объектами они изменяются, например, благодаря Оазису). Плагин немедленно (а не в начале следующего хода) уменьшает количество MP героя, если ему передаются существа более медленные, чем самое медленное из существ, уже имевшихся у героя. Передача существ может быть от другого героя, от любого объекта карты, при взаимодействии героя с городом. Уменьшение количества MP пропорционально количеству MP героя на данный момент. Например, если у армия героя состоит из Эльфов и в начале хода ему передают гномов, то уменьшение MP составит 200. А если этому же герою передаются Гномы после того, как он прошел половину своего дневного максимума движения, то уменьшение составит всего 100. Зачем это нужно ? Оригинальная механика игры заставляет совершать игроков всяческие ритуальные телодвижения по "возгонке" MP основных героев. Например, в конце хода к главному герою подходит вспомогательный герой и забирает у него наиболее медленных существ. А в начале следующего хода он уже отдает ему этих существ. Или, например, привычка забегать героем в город только для того, чтобы оставить в гарнизоне наиболее медленных существ, с тем, чтобы забрать их в следующий ход. Короче, имеется в виду весь этот бессмысленный и беспощадный "микроменеджмент", от которого хотелось бы избавиться. Знакомо то, что ниже ? Интересно было бы изучить последствия для игры использования предлагаемой механики. Стало ли меньше микроменеджмента ? Появились ли значительные дополнительные неудобства ? Увеличилось ли разнообразие стратегий ? (например, главному герою стали реже доставляться медленные существа по цепочкам и эти существа стали чаще использоваться в составе самостоятельных вспомогательных армий) Код - Код: Выделить всё
#include "../../include2023/patcher_x86.hpp" #include "../../include2023/gui.h" #include "../../include2023/managers.h" #include "../../include2023/map.h" #include "../../include2023/game.h" #include "../../include2023/combat.h"
#include <math.h> #include <stdio.h> #include <io.h> #include <fcntl.h>
Patcher* _P; PatcherInstance* _PI;
static _bool_ plugin_On = 0;
int aTag_monsterInfo;
int gpGame; int gpCurPlayer; int gpTownManager; int giCurPlayer;
void __stdcall HH_advM_DoEvent(HiHook* h, advManager* advM, mapCell* cell, int cellX, int cellY) { hero* hero_1 = &(*(game**)gpGame)->heroes[(*(playerData**)gpCurPlayer)->curHeroIdx]; hero* hero_2; int location = cell->objType & 0x7F;
if(!(hero_1->flags & HERO_AT_SEA)) { int minSpeedBefore_1 = hero_1->field_43; int minSpeedBefore_2;
if(location == LOCATION_HERO) { hero_2 = &(*(game**)gpGame)->heroes[(unsigned char)cell->extraInfo]; if(!(hero_2->flags & HERO_AT_SEA)) minSpeedBefore_2 = hero_2->field_43; }
CALL_4(void, __thiscall, h->GetDefaultFunc(), advM, cell, cellX, cellY);
int minSpeedAfter_1 = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 ) minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed; }
if(minSpeedAfter_1 < minSpeedBefore_1) { hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100) / (float)(1000 + (minSpeedBefore_1 - 2) * 100); hero_1->field_43 = minSpeedAfter_1; }
if(location == LOCATION_HERO) if(!(hero_2->flags & HERO_AT_SEA)) { int minSpeedAfter_2 = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_2->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed < minSpeedAfter_2 ) minSpeedAfter_2 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed; }
if(minSpeedAfter_2 < minSpeedBefore_2) { hero_2->remainingMobility *= (float)(1000 + (minSpeedAfter_2 - 2) * 100) / (float)(1000 + (minSpeedBefore_2 - 2) * 100); hero_2->field_43 = minSpeedAfter_2; } } } else { CALL_4(void, __thiscall, h->GetDefaultFunc(), advM, cell, cellX, cellY); }
hero_1->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_1); if(location == LOCATION_HERO) { hero_2->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_2); }
}
void __stdcall HH_townManager_DoCommand(HiHook* h, townManager* tM, int command) { hero* hero_1; int minSpeedBefore_1;
if(tM->castle->visitingHeroIdx != -1) { hero_1 = &(*(game**)gpGame)->heroes[tM->castle->visitingHeroIdx]; minSpeedBefore_1 = hero_1->field_43; }
CALL_2(void, __thiscall, h->GetDefaultFunc(), tM, command);
if(tM->castle->visitingHeroIdx != -1) { int minSpeedAfter_1 = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 ) minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed; }
if(minSpeedAfter_1 < minSpeedBefore_1) { hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100) / (float)(1000 + (minSpeedBefore_1 - 2) * 100); hero_1->field_43 = minSpeedAfter_1; } } }
void __stdcall HH_advM_DoAIEvent(HiHook* h, advManager* advM, mapCell* cell, hero* hero_1, int cellX, int cellY) { hero* hero_2; int location = cell->objType & 0x7F;
if(!(hero_1->flags & HERO_AT_SEA)) { int minSpeedBefore_1 = hero_1->field_43; int minSpeedBefore_2;
if(location == LOCATION_HERO) { hero_2 = &(*(game**)gpGame)->heroes[(unsigned char)cell->extraInfo]; if(!(hero_2->flags & HERO_AT_SEA)) minSpeedBefore_2 = hero_2->field_43; }
CALL_5(void, __thiscall, h->GetDefaultFunc(), advM, cell, hero_1, cellX, cellY);
int minSpeedAfter_1 = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeedAfter_1 ) minSpeedAfter_1 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed; }
if(minSpeedAfter_1 < minSpeedBefore_1) { hero_1->remainingMobility *= (float)(1000 + (minSpeedAfter_1 - 2) * 100) / (float)(1000 + (minSpeedBefore_1 - 2) * 100); hero_1->field_43 = minSpeedAfter_1; }
if(location == LOCATION_HERO) if(!(hero_2->flags & HERO_AT_SEA)) { int minSpeedAfter_2 = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_2->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed < minSpeedAfter_2 ) minSpeedAfter_2 = ((tag_monsterInfo*)aTag_monsterInfo)[hero_2->army.creatureTypes[i]].speed; }
if(minSpeedAfter_2 < minSpeedBefore_2) { hero_2->remainingMobility *= (float)(1000 + (minSpeedAfter_2 - 2) * 100) / (float)(1000 + (minSpeedBefore_2 - 2) * 100); hero_2->field_43 = minSpeedAfter_2; } } } else { CALL_5(void, __thiscall, h->GetDefaultFunc(), advM, cell, hero_1, cellX, cellY); }
hero_1->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_1); if(location == LOCATION_HERO) { hero_2->mobility = CALL_1(int, __thiscall, 0x494BB0, hero_2); }
}
int __stdcall setSlowestSpeedStartDay(LoHook* h, HookContext* c) { hero* hero_1; int minSpeed; for ( int j = 0; j < (*(game**)gpGame)->players[*(int*)giCurPlayer].numHeroes; ++j ) { hero_1 = &(*(game**)gpGame)->heroes[(*(game**)gpGame)->players[*(int*)giCurPlayer].heroesOwned[j]]; minSpeed = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeed ) minSpeed = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed; } hero_1->field_43 = minSpeed; }
return EXEC_DEFAULT;
}
int __stdcall setSlowestSpeedStartGame(LoHook* h, HookContext* c) { hero* hero_1; int minSpeed; for ( int j = 0; j < MAX_HEROES; ++j ) { hero_1 = &(*(game**)gpGame)->heroes[j]; minSpeed = 7; for ( int i = 0; i < 5; ++i ) { if ( hero_1->army.creatureTypes[i] != -1 && ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed < minSpeed ) minSpeed = ((tag_monsterInfo*)aTag_monsterInfo)[hero_1->army.creatureTypes[i]].speed; } hero_1->field_43 = minSpeed; }
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("H2_HeroesMobilityChange");
int check;
// H2 Eng PoL 2.1 check = *(int*)(0x484DC1+6); if(check == 0x14000000) { aTag_monsterInfo = 0x4F21F8;
gpGame = 0x52477C; gpCurPlayer = 0x5306D0; gpTownManager = 0x5247C4; giCurPlayer = 0x5305D0;
_PI->WriteHiHook(0x485EA0, SPLICE_, EXTENDED_, THISCALL_, HH_advM_DoEvent); _PI->WriteHiHook(0x413F80, SPLICE_, EXTENDED_, THISCALL_, HH_townManager_DoCommand); _PI->WriteHiHook(0x48F940, SPLICE_, EXTENDED_, THISCALL_, HH_advM_DoAIEvent);
_PI->WriteLoHook(0x4240EA, setSlowestSpeedStartDay); _PI->WriteLoHook(0x4281D5, setSlowestSpeedStartGame); }
} }
return TRUE; }
Последний раз редактировалось Ben80 10 авг 2023, 05:09, всего редактировалось 2 раз(а).
|