Added assignment of unique IDs to items/critters for event queue

* to prevent event queue being added to the incorrect object on the map.
This commit is contained in:
NovaRain
2019-07-09 21:47:27 +08:00
parent c3080a2db9
commit 8d1b959f20
3 changed files with 68 additions and 11 deletions
+18
View File
@@ -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
};
}
+47 -8
View File
@@ -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);
}
}
+3 -3
View File
@@ -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);