From dbe2de310c804bc67d548e2a2ad32e530ae04d9a Mon Sep 17 00:00:00 2001 From: NovaRain Date: Sat, 29 May 2021 10:36:00 +0800 Subject: [PATCH] Fixed incorrect object type search when loading a game saved in combat --- sfall/FalloutEngine/Variables_def.h | 1 + sfall/Game/objects.cpp | 13 +++++++++++-- sfall/Game/objects.h | 3 +++ sfall/Modules/BugFixes.cpp | 29 +++++++++++++++++++++++++++++ sfall/Modules/Objects.cpp | 2 ++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/sfall/FalloutEngine/Variables_def.h b/sfall/FalloutEngine/Variables_def.h index 6f765749..e117a248 100644 --- a/sfall/FalloutEngine/Variables_def.h +++ b/sfall/FalloutEngine/Variables_def.h @@ -31,6 +31,7 @@ VAR3(crit_succ_eff, fo::CritInfo, 20, 9, 6) // 20 critters with 9 VAR_(critter_db_handle, fo::PathNode*) VAR_(critterClearObj, DWORD) VAR_(crnt_func, DWORD) +VAR_(cur_id, DWORD) VAR_(curr_anim_set, DWORD) VAR_(curr_anim_counter, DWORD) VAR_(curr_font_num, DWORD) diff --git a/sfall/Game/objects.cpp b/sfall/Game/objects.cpp index c599622d..e8cf4239 100644 --- a/sfall/Game/objects.cpp +++ b/sfall/Game/objects.cpp @@ -4,7 +4,7 @@ * */ -//#include "..\main.h" +#include "..\main.h" #include "..\FalloutEngine\Fallout2.h" #include "..\Modules\HookScripts\MiscHs.h" @@ -21,8 +21,17 @@ long Objects::is_within_perception(fo::GameObject* watcher, fo::GameObject* targ return sf::PerceptionRangeHook_Invoke(watcher, target, hookType, fo::func::is_within_perception(watcher, target)); } +// Alternative implementation of objFindObjPtrFromID_ engine function with the type of object to find +fo::GameObject* __fastcall Objects::FindObjectFromID(long id, long type) { + fo::GameObject* obj = fo::func::obj_find_first(); + while (obj) { + if (obj->id == id && obj->Type() == type) return obj; + obj = fo::func::obj_find_next(); + } + return nullptr; +} + void Objects::init() { - } } diff --git a/sfall/Game/objects.h b/sfall/Game/objects.h index eaab30a2..3cd3bfef 100644 --- a/sfall/Game/objects.h +++ b/sfall/Game/objects.h @@ -15,6 +15,9 @@ public: // Implementation of is_within_perception_ engine function with the HOOK_WITHINPERCEPTION hook static long is_within_perception(fo::GameObject* watcher, fo::GameObject* target, long hookType); + + // Alternative implementation of objFindObjPtrFromID_ engine function with the type of object to find + static fo::GameObject* __fastcall FindObjectFromID(long id, long type); }; } \ No newline at end of file diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index 872d7910..33ab4aa6 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -4,6 +4,8 @@ #include "HookScripts\InventoryHs.h" +#include "..\Game\objects.h" + #include "Drugs.h" #include "LoadGameHook.h" #include "ScriptExtender.h" @@ -1483,7 +1485,30 @@ static void __declspec(naked) Save_as_ASCII_hack() { } } +static void __declspec(naked) combat_load_hook_critter() { + __asm { + push ecx; + mov edx, OBJ_TYPE_CRITTER; + mov ecx, eax; + call game::Objects::FindObjectFromID; + pop ecx; + retn; + } +} + +static void __declspec(naked) combat_load_hook_item() { + __asm { + push ecx; + mov edx, OBJ_TYPE_ITEM; + mov ecx, eax; + call game::Objects::FindObjectFromID; + pop ecx; + retn; + } +} + static DWORD combatFreeMoveTmp = 0xFFFFFFFF; + static void __declspec(naked) combat_load_hook() { __asm { call fo::funcoffs::db_freadInt_; @@ -3429,6 +3454,10 @@ void BugFixes::init() // Fix for Sequence stat value not being printed correctly when using "print to file" option MakeCall(0x4396F5, Save_as_ASCII_hack, 2); + // Fix for the incorrect object type search when loading a game saved in combat mode + HookCalls(combat_load_hook_critter, {0x42113B, 0x42117D}); + HookCall(0x4211C0, combat_load_hook_item); + // Fix for Bonus Move APs being replenished when you save and load the game in combat //if (IniReader::GetConfigInt("Misc", "BonusMoveFix", 1)) { dlog("Applying fix for Bonus Move exploit.", DL_FIX); diff --git a/sfall/Modules/Objects.cpp b/sfall/Modules/Objects.cpp index d6184869..9f316380 100644 --- a/sfall/Modules/Objects.cpp +++ b/sfall/Modules/Objects.cpp @@ -95,6 +95,7 @@ pickNewID: // skip PM range (18000 - 83535) } // Reassigns object IDs to all critters upon first loading a map and updates their max HP stat +// TODO: for items? static void map_fix_critter_id() { long npcStartID = 4096; fo::GameObject* obj = fo::func::obj_find_first(); @@ -254,6 +255,7 @@ skip: void Objects::init() { LoadGameHook::OnGameReset() += []() { RestoreObjUnjamAllLocks(); + fo::var::cur_id = 4; }; HookCall(0x4A38A5, new_obj_id_hook);