diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h index f984fe60..771d0709 100644 --- a/sfall/FalloutEngine/Functions_def.h +++ b/sfall/FalloutEngine/Functions_def.h @@ -21,7 +21,7 @@ WRAP_WATCOM_FFUNC7(long, createWindow, const char*, winName, long, x, long, y, l WRAP_WATCOM_FFUNC3(void, display_inventory, long, inventoryOffset, long, visibleOffset, long, mode) WRAP_WATCOM_FFUNC4(void, display_target_inventory, long, inventoryOffset, long, visibleOffset, DWORD*, targetInventory, long, mode) WRAP_WATCOM_FFUNC3(FrmFrameData*, frame_ptr, FrmHeaderData*, frm, long, frame, long, direction) -WRAP_WATCOM_FFUNC7(void, make_straight_path_func, fo::GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, rotationPtr, DWORD*, result, long, flags, void*, func) +WRAP_WATCOM_FFUNC7(void, make_straight_path_func, GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, rotationPtr, DWORD*, result, long, flags, void*, func) WRAP_WATCOM_FFUNC3(long, object_under_mouse, long, crSwitch, long, inclDude, long, elevation) WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value) WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value) @@ -93,7 +93,9 @@ WRAP_WATCOM_FUNC0(long, new_obj_id) // calculates bounding box (rectangle) for a given object WRAP_WATCOM_FUNC2(void, obj_bound, GameObject*, object, BoundRect*, boundRect) WRAP_WATCOM_FUNC2(long, obj_erase_object, GameObject*, object, BoundRect*, boundRect) -WRAP_WATCOM_FUNC2(long, obj_pid_new, fo::GameObject*, object, long, pid) +WRAP_WATCOM_FUNC0(GameObject*, obj_find_first) +WRAP_WATCOM_FUNC0(GameObject*, obj_find_next) +WRAP_WATCOM_FUNC2(long, obj_pid_new, GameObject*, object, long, pid) // checks/unjams jammed locks WRAP_WATCOM_FUNC1(long, obj_lock_is_jammed, GameObject*, object) WRAP_WATCOM_FUNC1(void, obj_unjam_lock, GameObject*, object) diff --git a/sfall/Modules/Objects.cpp b/sfall/Modules/Objects.cpp index 7f73f6d5..cde4f9ef 100644 --- a/sfall/Modules/Objects.cpp +++ b/sfall/Modules/Objects.cpp @@ -83,6 +83,34 @@ pickNewID: // skip PM range (18000 - 83535) } } +// Reassigns object IDs to all critters upon first loading a map +static void map_fix_critter_id() { + long npcStartID = 4096; + fo::GameObject* obj = fo::func::obj_find_first(); + while (obj) { + if (obj->Type() == fo::OBJ_TYPE_CRITTER && obj->id < PLAYER_ID) { + obj->id = npcStartID++; + } + obj = fo::func::obj_find_next(); + } +} + +static void __declspec(naked) map_load_file_hack() { + __asm { + jz mapVirgin; + retn; +mapVirgin: + call fo::funcoffs::wmMapIsSaveable_; + test eax, eax; + jnz saveable; + retn; +saveable: + call map_fix_critter_id; + xor eax, eax; // set ZF + retn; + } +} + void Objects::SetAutoUnjamLockTime(DWORD time) { if (!unjamTimeState) { BlockCall(0x4A364A); // disable auto unjam at midnight @@ -139,6 +167,10 @@ void Objects::init() { SafeWrite8(0x4A38B3, 0x90); // fix ID increment MakeCall(0x477A0E, item_identical_hack); // don't put item with unique ID to items stack + + // Fix mapper bug by reassigning object IDs to critters (for maps not yet visited) + MakeCall(0x482E6B, map_load_file_hack); + SafeWrite8(0x482E71, 0x85); // jz > jnz } }