From 03cf90499670198531b6bea153a745599ddceac6 Mon Sep 17 00:00:00 2001 From: Alexander <84857900+4z0t@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:05:50 +0300 Subject: [PATCH] Alternative fix for the toggle of the Salem (#94) Depends on: https://github.com/FAForever/fa/pull/6499 --- README.md | 6 +- hooks/EntityGetFootprint.cpp | 14 +++++ hooks/luaSimGetStat.cpp | 7 --- section/EntityGetFootprint.cpp | 39 +++++++++++++ section/include/global.h | 14 ++++- section/include/moho.h | 1 + section/luaSimGetStat.cpp | 101 --------------------------------- 7 files changed, 70 insertions(+), 112 deletions(-) create mode 100644 hooks/EntityGetFootprint.cpp delete mode 100644 hooks/luaSimGetStat.cpp create mode 100644 section/EntityGetFootprint.cpp delete mode 100644 section/luaSimGetStat.cpp diff --git a/README.md b/README.md index 4c2ba8f8..9adf1034 100644 --- a/README.md +++ b/README.md @@ -197,9 +197,6 @@ These new features have been added in a backwards compatible manner - section/LuaFuncRegs.cpp - Maximum sim rate up to 50 - hooks/DelClampMaxSimRate.cpp -- Adds an amphibious mode toggle to the Salem - - hooks/luaSimGetStat.cpp - - section/luaSimGetStat.cpp - Adds GetDepositsAroundPoint to Sim and UI - section/SimGetDepositsAroundPoint.cpp - section/LuaFuncRegs.cpp @@ -225,3 +222,6 @@ These new features have been added in a backwards compatible manner - section/BuildUnit.cpp - section/SelectUnit.cpp - section/SimArmyCreate.cpp +- Add `Unit:ForceAltFootPrint` that forces game to use AltFootprint for the unit (applied to Salem in particular) + - hooks/EntityGetFootprint.cpp + - section/EntityGetFootprint.cpp \ No newline at end of file diff --git a/hooks/EntityGetFootprint.cpp b/hooks/EntityGetFootprint.cpp new file mode 100644 index 00000000..03009612 --- /dev/null +++ b/hooks/EntityGetFootprint.cpp @@ -0,0 +1,14 @@ +#define SECTION(index, address) ".section h"#index"; .set h"#index","#address";" +#include "../define.h" + +asm( +// Moho::Entity::Entity +SECTION(0, 0x00677BC9) + "mov dword ptr [esi+0x1F8], ebx;" // 0x1F9 bool forceAltFootprint + +// Moho::Entity::GetFootprint +SECTION(1, 0x006788A5) + "jmp "QU(asm__GetFootprint)";" + "nop;" + "nop;" +); \ No newline at end of file diff --git a/hooks/luaSimGetStat.cpp b/hooks/luaSimGetStat.cpp deleted file mode 100644 index f05c53af..00000000 --- a/hooks/luaSimGetStat.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "../define.h" -asm( - ".section h0; .set h0,0x6CC759;" - "jmp "QU(luaSimGetStat)";" - "nop;" - "nop;" -); \ No newline at end of file diff --git a/section/EntityGetFootprint.cpp b/section/EntityGetFootprint.cpp new file mode 100644 index 00000000..610825a5 --- /dev/null +++ b/section/EntityGetFootprint.cpp @@ -0,0 +1,39 @@ +#include "include/CObject.h" +#include "include/magic_classes.h" +#include "include/moho.h" + +int ForceAltFootPrint(lua_State *L) +{ + + if (lua_gettop(L) != 2) + L->LuaState->Error(s_ExpectedButGot, __FUNCTION__, 2, lua_gettop(L)); + auto res = GetCScriptObject(L, 1); + if (res.IsFail()) + L->LuaState->Error("%s", res.reason); + + void *unit = res.object; + bool flag = lua_toboolean(L, 2); + + GetField(unit, 8+0x1F9) = flag; // bool forceAltFootprint + + return 0; +} +using UnitMethodReg = SimRegFunc<0x00E2D550, 0x00F8D704>; + +UnitMethodReg UseAltFootPrintReg{ + "ForceAltFootPrint", + "", + ForceAltFootPrint, + "Unit"}; + + +void asm__GetFootprint() +{ + asm( + "cmp byte ptr [ecx+0x11C], 0;" // this->sstiData.usingAltFp + "jnz 0x006788AE;" + "cmp byte ptr [ecx+0x1F9], 0;" // bool forceAltFootprint + "jnz 0x006788AE;" + "jmp 0x006788C2;" + ); +} \ No newline at end of file diff --git a/section/include/global.h b/section/include/global.h index 71a7b24d..6e5b4df1 100644 --- a/section/include/global.h +++ b/section/include/global.h @@ -152,4 +152,16 @@ struct Result { constexpr static Result Success(void *data) { return {(T *)data, nullptr}; } inline bool IsFail() { return reason != nullptr; } -}; \ No newline at end of file +}; + +template +T Offset(void *ptr, size_t offset) +{ + return (T)(((char *)ptr) + offset); +} + +template +T &GetField(void *ptr, size_t offset) +{ + return *Offset(ptr, offset); +} \ No newline at end of file diff --git a/section/include/moho.h b/section/include/moho.h index 4d59310f..943f99f5 100644 --- a/section/include/moho.h +++ b/section/include/moho.h @@ -821,6 +821,7 @@ struct UnitIntel struct Unit : WeakObject {//0x006A5422, 0x6A8 bytes + using Type = ObjectType<0x010C6FC8, 0x00F6A1E4>; //WeakObject WeakObject; // at 0x8 //Entity Entity; to 0x278 diff --git a/section/luaSimGetStat.cpp b/section/luaSimGetStat.cpp deleted file mode 100644 index 52844d7a..00000000 --- a/section/luaSimGetStat.cpp +++ /dev/null @@ -1,101 +0,0 @@ -char SalemWaterOnlyBp[1536]; -char SalemDefaultBp[4]; - -// This patch allows to turn off Salem's amphibious ability to exclude accidental land moves -// We take default Salem's blueprint and copy it to `SalemWaterOnlyBp` -// Then change 2 values in it: MinWaterDepth = 1.5 and OccupancyCaps = 8 -// Only these 2 do matter in movement calculations, other bp values stay the same -// Then we just change a pointer to blueprint in unit object depending on what mode should be activated -// Amphibious mode ON: SalemDefaultBp, amphibious mode OFF: SalemWaterOnlyBp. - -void luaSimGetStat() -{ - asm( - "cmp byte ptr [eax], 0x68;" - "jne EXIT;" - "cmp byte ptr [eax+0x1], 0x31;" - "jne EXIT;" - "push eax;" - "push ebx;" - "mov eax, %[SalemDefaultBp];" - "cmp eax, 0x0;" - "je UpdateBlueprints;" - "cmp byte ptr [eax + 0xDA], 0x9;" // Check if SalemDefaultBp pointer is still valid (OccupancyCaps = 9 means it is) - "mov eax, %[SalemWaterOnlyBp];" // and if not then update both blueprints (prevents crashes on simulation restart) - "je dummyExists;" - "UpdateBlueprints:;" - "mov eax, %[SalemWaterOnlyBp];" - "push ebx;" - "push ecx;" - "push edx;" - "mov ebx, dword ptr [ebx+0x74];" - "mov %[SalemDefaultBp], ebx;" - "mov eax, ebx;" - "mov ebx, %[SalemWaterOnlyBp];" - "mov edx, dword ptr [eax];" - "mov [ebx], edx;" - "mov ecx, 0x4;" - "MemCpyCycle:;" - "add ebx, 4;" - "mov edx, dword ptr [eax+ecx];" - "mov [ebx], edx;" - "add ecx, 4;" - "cmp ecx, 1532;" - "jbe MemCpyCycle;" - "mov dword ptr [ebx - 0x51C], 0x3fc00000;" //MinWaterDepth = 1.5 - "mov dword ptr [ebx - 0x522], 0x8;" //OccupancyCaps = 8 - "pop edx;" - "pop ecx;" - "pop ebx;" - "dummyExists:;" - "cmp dword ptr [esp+0x20], 0x0;" - "jne SetAmphON;" - "mov eax, dword ptr [ebx+0x74];" - "cmp byte ptr [eax + 0xDA], 0x8;" - "je POPEXIT;" - "mov eax, %[SalemWaterOnlyBp];" - "mov dword ptr [ebx+0x74], eax;" - "jmp POPEXIT;" - "SetAmphON:;" - "mov eax, dword ptr [ebx+0x74];" - "cmp byte ptr [eax + 0xDA], 0x9;" - "je POPEXIT;" - "mov eax, %[SalemDefaultBp];" - "mov dword ptr [ebx+0x74], eax;" - "POPEXIT:;" - "pop ebx;" - "pop eax;" - "EXIT:;" - "mov esi, eax;" - "add esp,0x8;" - "test esi, esi;" - "jmp 0x006CC760;" - : - : [SalemWaterOnlyBp] "i" (SalemWaterOnlyBp), [SalemDefaultBp] "m" (SalemDefaultBp) - : - ); -} - -/* Lua sim function: unit:GetStat(char statName, int defValue) -unit:GetStat("h1_SetSalemAmph", 1) - -if (statName.at(0) == "h") { - if (statName.at(1) == "1") { - - if !SalemWaterOnlyBp { - SalemWaterOnlyBp = defaultBP //handmade memcpy here :) - SalemWaterOnlyBp.Footprint.MinWaterDepth = 1.5 //default 0 - SalemWaterOnlyBp.Footprint.OccupancyCaps = 8 //default 9 Only these 2 parameters do matter - } - - if (defValue == 0){ //turn off amphibious - if (unit.Blueprint.Footprint.OccupancyCaps != 8) { - unit.Blueprint = SalemWaterOnlyBp - } - } else { //turn on - if (unit.Blueprint.Footprint.OccupancyCaps != 9) { - unit.Blueprint = SalemDefaultBp - } - } - } -} */ \ No newline at end of file