diff --git a/sfall/Modules/Objects.cpp b/sfall/Modules/Objects.cpp index 3b637231..b4e2113b 100644 --- a/sfall/Modules/Objects.cpp +++ b/sfall/Modules/Objects.cpp @@ -35,7 +35,7 @@ bool Objects::IsUniqueID(long id) { return (id > UniqueID::Start || (id >= fo::PLAYER_ID && id < 83536)); // 65535 maximum possible number of prototypes } -static void SetScriptObjectID(fo::GameObject* obj) { +void Objects::SetScriptObjectID(fo::GameObject* obj) { fo::ScriptInstance* script; if (fo::func::scr_ptr(obj->scriptId, &script) != -1) { script->ownerObjectId = obj->id; @@ -74,8 +74,11 @@ void Objects::SetNewEngineID(fo::GameObject* obj) { } static __declspec(naked) void item_identical_hack() { + static const DWORD item_identical_End = 0x477AD5; using namespace fo::Fields; __asm { + cmp esi, edi; // inv_item == place_item? (safeguard) + je identical; mov ecx, [edi]; // place_item id cmp ecx, Start; // start unique ID jg notIdentical; @@ -87,6 +90,9 @@ static __declspec(naked) void item_identical_hack() { cmp eax, ebx; notIdentical: retn; // if ZF == 0 then item is not identical +identical: + add esp, 4; + jmp item_identical_End; } } @@ -111,7 +117,7 @@ static void map_fix_critter_id() { if (obj->IsCritter()) { if (obj->id < fo::PLAYER_ID) { obj->id = npcStartID++; - SetScriptObjectID(obj); + Objects::SetScriptObjectID(obj); } Stats::UpdateHPStat(obj); } diff --git a/sfall/Modules/Objects.h b/sfall/Modules/Objects.h index fad6a348..13f26e42 100644 --- a/sfall/Modules/Objects.h +++ b/sfall/Modules/Objects.h @@ -36,6 +36,7 @@ public: static long uniqueID; static bool IsUniqueID(long id); + static void SetScriptObjectID(fo::GameObject* obj); static long __fastcall SetObjectUniqueID(fo::GameObject* obj); static long __fastcall SetSpecialID(fo::GameObject* obj); diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index 8819a8a9..fafab9d7 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -584,14 +584,16 @@ void mf_set_drugs_data(OpcodeContext& ctx) { void mf_set_unique_id(OpcodeContext& ctx) { fo::GameObject* obj = ctx.arg(0).object(); - long id; - if (ctx.arg(1).rawValue() == -1) { - id = fo::func::new_obj_id(); - obj->id = id; - } else { - id = Objects::SetObjectUniqueID(obj); + if (ctx.numArgs() > 1 && ctx.arg(1).rawValue() == -1) { + // unassign unique ID only if the object currently has one + if (obj->id > UniqueID::Start) { + obj->id = fo::func::new_obj_id(); + Objects::SetScriptObjectID(obj); + } + ctx.setReturn(obj->id); + return; } - ctx.setReturn(id); + ctx.setReturn(Objects::SetObjectUniqueID(obj)); } void mf_objects_in_radius(OpcodeContext& ctx) {