From 8d1b959f204307c69f2f714a33b7b44f212ba018 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 9 Jul 2019 21:47:27 +0800 Subject: [PATCH] Added assignment of unique IDs to items/critters for event queue * to prevent event queue being added to the incorrect object on the map. --- sfall/FalloutEngine/Enums.h | 18 ++++++++++++ sfall/Modules/Objects.cpp | 55 +++++++++++++++++++++++++++++++------ sfall/Modules/Objects.h | 6 ++-- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/sfall/FalloutEngine/Enums.h b/sfall/FalloutEngine/Enums.h index 74c9564e..b21b8e5f 100644 --- a/sfall/FalloutEngine/Enums.h +++ b/sfall/FalloutEngine/Enums.h @@ -740,4 +740,22 @@ namespace WinFlags { }; } +enum QueueType : long +{ + drug_effect_event = 0, // critter use drug + knockout_event = 1, // critter + addict_event = 2, // critter + script_timer_event = 3, // any object + game_time_event = 4, // no object + poison_event = 5, // dude + radiation_event = 6, // dude + flare_time_event = 7, // item + explode_event = 8, // item + item_trickle_event = 9, + sneak_event = 10, // dude + explode_fail_event = 11, // item + map_update_event = 12, + gsound_sfx_event = 13 // no object +}; + } diff --git a/sfall/Modules/Objects.cpp b/sfall/Modules/Objects.cpp index 7b5d4eb1..6afa3e4f 100644 --- a/sfall/Modules/Objects.cpp +++ b/sfall/Modules/Objects.cpp @@ -33,22 +33,22 @@ long Objects::uniqueID = UniqueID::Start; // current counter id, saving to sfall // Assigns a new unique identifier to an object if it has not been previously assigned // the identifier is saved with the object in the saved game and this can used in various script // player ID = 18000, all party members have ID = 18000 + its pid (file number of prototype) -long Objects::SetObjectUniqueID(fo::GameObject* obj) { +long __fastcall Objects::SetObjectUniqueID(fo::GameObject* obj) { long id = obj->id; - if (id > UniqueID::Start || obj == fo::var::obj_dude || (id >= PLAYER_ID && id < 83536)) return id; // 65535 maximum possible number of prototypes + if (id > UniqueID::Start || (id >= PLAYER_ID && id < 83536)) return id; // 65535 maximum possible number of prototypes - if ((DWORD)uniqueID >= UniqueID::End) uniqueID = UniqueID::Start; + if ((DWORD)uniqueID >= (DWORD)UniqueID::End) uniqueID = UniqueID::Start; obj->id = ++uniqueID; return uniqueID; } -// Assigns a unique ID in the negative range (0x8FFFFFFF - 0xFFFFFFFE) -long Objects::SetSpecialID(fo::GameObject* obj) { +// Assigns a unique ID in the negative range (0xFFFFFFF6 - 0x8FFFFFF7) +long __fastcall Objects::SetSpecialID(fo::GameObject* obj) { long id = obj->id; - if (id < -1 || id > UniqueID::Start) return id; + if (id <= -10 || id > UniqueID::Start) return id; - if ((DWORD)uniqueID >= UniqueID::End) uniqueID = UniqueID::Start; - id = ++uniqueID + UniqueID::End; + if ((DWORD)uniqueID >= (DWORD)UniqueID::End) uniqueID = UniqueID::Start; + id = -9 - (++uniqueID - UniqueID::Start); obj->id = id; return id; } @@ -111,6 +111,43 @@ saveable: } } +static void __declspec(naked) queue_add_hack() { + using namespace fo; + using namespace Fields; + __asm { + mov [edx + 8], edi; // queue.object + mov [edx], esi; // queue.time + test edi, edi; + jnz fix; + retn; +fix: + mov eax, [edi + protoId]; + and eax, 0x0F000000; + jnz notItem; // object is not an item? + push ecx; + push edx; + mov ecx, edi; + call Objects::SetSpecialID; + pop edx; + pop ecx; + retn; +notItem: + cmp ecx, script_timer_event; // QueueType + je end; + cmp eax, OBJ_TYPE_CRITTER << 24; + jne end; + push ecx; + push edx; + mov ecx, edi; + call Objects::SetObjectUniqueID; + pop edx; + pop ecx; +end: + xor edi, edi; // fix: don't set "Used" flag for critter objects + retn; + } +} + void Objects::SetAutoUnjamLockTime(DWORD time) { if (!unjamTimeState) { BlockCall(0x4A364A); // disable auto unjam at midnight @@ -171,6 +208,8 @@ void Objects::init() { // Fix mapper bug by reassigning object IDs to critters (for unvisited maps) MakeCall(0x482E6B, map_load_file_hack); SafeWrite8(0x482E71, 0x85); // jz > jnz + // Additionally fix object IDs for queue events + MakeCall(0x4A25BA, queue_add_hack); } } diff --git a/sfall/Modules/Objects.h b/sfall/Modules/Objects.h index f93be94c..cada4d4e 100644 --- a/sfall/Modules/Objects.h +++ b/sfall/Modules/Objects.h @@ -5,7 +5,7 @@ namespace sfall { -enum UniqueID { +enum UniqueID : long { Start = 0x0FFFFFFF, // start at 0x10000000 End = 0x7FFFFFFF }; @@ -17,8 +17,8 @@ public: static long uniqueID; - static long SetObjectUniqueID(fo::GameObject* obj); - static long SetSpecialID(fo::GameObject* obj); + static long __fastcall SetObjectUniqueID(fo::GameObject* obj); + static long __fastcall SetSpecialID(fo::GameObject* obj); static void SetNewEngineID(fo::GameObject* obj); static void SetAutoUnjamLockTime(DWORD time);