diff --git a/sfall/CheckAddress.cpp b/sfall/CheckAddress.cpp index ad8aa962..62e6a16f 100644 --- a/sfall/CheckAddress.cpp +++ b/sfall/CheckAddress.cpp @@ -10,7 +10,6 @@ namespace sfall std::multimap writeAddress; static std::vector excludeAddr = { - 0x42A14F, 0x42A178, 0x44E949, 0x44E94A, 0x44E937, 0x4F5F40, 0x4CB850, // from movies.cpp }; diff --git a/sfall/InputFuncs.cpp b/sfall/InputFuncs.cpp index 8c90b0fc..4812fd89 100644 --- a/sfall/InputFuncs.cpp +++ b/sfall/InputFuncs.cpp @@ -17,6 +17,7 @@ */ #define DIRECTINPUT_VERSION 0x0700 + #include #include #include diff --git a/sfall/Modules/AI.cpp b/sfall/Modules/AI.cpp index 81f68921..595660d7 100644 --- a/sfall/Modules/AI.cpp +++ b/sfall/Modules/AI.cpp @@ -330,6 +330,22 @@ skipMove: } } +static void __declspec(naked) ai_move_away_hook() { + static const DWORD ai_move_away_hook_Ret = 0x4289DA; + __asm { + test ebx, ebx; + jl fix; // distance arg < 0 + jmp fo::funcoffs::ai_cap_; +fix: + neg ebx; + mov eax, [esi + movePoints]; // Current Action Points + cmp ebx, eax; + cmovg ebx, eax; // if (distance > ap) dist = ap + add esp, 4; + jmp ai_move_away_hook_Ret; + } +} + //////////////////////////////////////////////////////////////////////////////// static long __fastcall RollFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) { @@ -436,6 +452,13 @@ void AI::init() { // Fix AI behavior for "Snipe" distance preference // The attacker will try to shoot the target instead of always running away from it at the beginning of the turn MakeCall(0x42B086, cai_perform_distance_prefs_hack); + + // Fix for ai_move_away_ engine function not working correctly in cases when needing to move a distance away from the target + // now the function also takes the distance argument in a negative value for moving away at a distance + HookCall(0x4289A7, ai_move_away_hook); + // also patch combat_safety_invalidate_weapon_func_ for returning out_range argument in a negative value + SafeWrite8(0x421628, 0xD0); // sub edx, eax > sub eax, edx + SafeWrite16(0x42162A, 0xFF40); // lea eax, [edx+1] > lea eax, [eax-1] } fo::GameObject* __stdcall AI::AIGetLastAttacker(fo::GameObject* target) { diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index a16bf127..3ebfb90a 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -1544,7 +1544,7 @@ end: } } -static void __declspec(naked) ai_move_steps_closer_hook() { +static void __declspec(naked) ai_combat_turn_run_hook() { __asm { call fo::funcoffs::combat_turn_run_; movzx dx, word ptr [esi + damageFlags]; // combat_data.results @@ -3040,7 +3040,11 @@ void BugFixes::init() // Fix for critters killed in combat by scripting still being able to move in their combat turn if the distance parameter // in their AI packages is set to stay_close/charge, or NPCsTryToSpendExtraAP is enabled - HookCall(0x42A1A8, ai_move_steps_closer_hook); // old 0x42B24D + HookCalls(ai_combat_turn_run_hook, { + 0x42A1A8, // ai_move_steps_closer_ (old 0x42B24D) + 0x42898D, // ai_run_away_ (potential fix) + 0x428AB3 // ai_move_away_ (potential fix) + }); // Fix instant death critical dlog("Applying instant death fix.", DL_INIT);