From a3f22b67d890129119756e20d1717f69b311b929 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 6 Feb 2020 10:45:40 +0800 Subject: [PATCH] Fixed trying to loot corpses with the "NoSteal" flag (#280) --- artifacts/scripting/headers/define_extra.h | 10 ++++---- sfall/FalloutEngine/Enums.h | 18 ++++++++++++++ sfall/FalloutEngine/Functions.cpp | 5 +--- sfall/Modules/BugFixes.cpp | 29 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/artifacts/scripting/headers/define_extra.h b/artifacts/scripting/headers/define_extra.h index e57185c1..d97f9d0e 100644 --- a/artifacts/scripting/headers/define_extra.h +++ b/artifacts/scripting/headers/define_extra.h @@ -89,16 +89,16 @@ /* Critter flags */ #define CFLG_BARTER 2 // 0x00000002 - Barter (can trade with) -#define CFLG_NOSTEAL 32 // 0x00000020 - Steal (cannot steal from) +#define CFLG_NOSTEAL 32 // 0x00000020 - Steal (cannot be stolen from) #define CFLG_NODROP 64 // 0x00000040 - Drop (doesn't drop items) #define CFLG_NOLIMBS 128 // 0x00000080 - Limbs (cannot lose limbs) #define CFLG_NOAGES 256 // 0x00000100 - Ages (dead body does not disappear) -#define CFLG_NOHEAL 512 // 0x00000200 - Heal (damage is not cured with time) +#define CFLG_NOHEAL 512 // 0x00000200 - Heal (damage is not healed with time) #define CFLG_INVULN 1024 // 0x00000400 - Invulnerable (cannot be hurt) #define CFLG_FLATTN 2048 // 0x00000800 - Flatten (leaves no dead body) -#define CFLG_SPECIAL 4096 // 0x00001000 - Special (there is a special type of death) -#define CFLG_RANGED 8192 // 0x00002000 - Range (melee attack is possible at a distance) -#define CFLG_NOKNOCKDOWN 16384 // 0x00004000 - Knock (cannot be knocked down) +#define CFLG_SPECIAL 4096 // 0x00001000 - Special (has a special type of death) +#define CFLG_RANGED 8192 // 0x00002000 - Range (has extra hand-to-hand range) +#define CFLG_NOKNOCKDOWN 16384 // 0x00004000 - Knock (cannot be knocked back) /* Window flags */ #define WIN_FLAG_MOVEONTOP (0x4) diff --git a/sfall/FalloutEngine/Enums.h b/sfall/FalloutEngine/Enums.h index cd918c4e..d82ddffa 100644 --- a/sfall/FalloutEngine/Enums.h +++ b/sfall/FalloutEngine/Enums.h @@ -90,6 +90,24 @@ enum Animation : long ANIM_called_shot_pic = 64, }; +enum CritterFlags : long +{ + Sneak = 0x01, // Can sneak ? + Barter = 0x02, // Can trade with + Level = 0x04, // Level received ? + Addict = 0x08, // Drug addiction ? + NoSteal = 0x20, // Can't be stolen from + NoDrop = 0x40, // Doesn't drop items + NoLimbs = 0x80, // Can't lose limbs + DeadAges = 0x100, // Dead body does not disappear + NoHeal = 0x200, // Damage is not healed with time + Invlunerable = 0x400, // Is Invlunerable (cannot be hurt) + NotFlattens = 0x800, // Doesn't flatten on death (leaves no dead body) + SpecialDeath = 0x1000, // Has a special type of death + RangeHth = 0x2000, // Has extra hand-to-hand range + NoKnockBack = 0x4000, // Can't be knocked back +}; + enum DamageFlag : long { DAM_KNOCKED_OUT = 0x1, diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp index 7be1802d..f695f2b1 100644 --- a/sfall/FalloutEngine/Functions.cpp +++ b/sfall/FalloutEngine/Functions.cpp @@ -258,11 +258,8 @@ DWORD __fastcall interpretGetValue(Program* scriptPtr, DWORD &outType) { mov edx, eax; mov eax, ecx; call fo::funcoffs::interpretPopLong_; // pops value from Data stack (must be preceded by InterpretPopShort) - cmp dx, VAR_TYPE_STR2; - je getStr; cmp dx, VAR_TYPE_STR; - jne isNotStr; -getStr: + ja isNotStr; mov ebx, eax; mov eax, ecx; call fo::funcoffs::interpretGetString_; // retrieve string argument diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index beb27b66..8f968691 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -2495,6 +2495,30 @@ static void __declspec(naked) main_death_scene_hook() { } } +static void __declspec(naked) action_loot_container_hack() { + __asm { + cmp dword ptr [esp + 0x10 + 4], 0x44C1D9 + 5; + je fix; + xor eax, eax; // set ZF + retn; +fix: + sub esp, 4; + mov edx, esp; + call fo::funcoffs::proto_ptr_; + mov edx, [esp]; + add esp, 4; + test [edx + 0x20], NoSteal; // critter flags + jnz look; + retn; +look: + mov eax, esi; + mov edx, edi; + call fo::funcoffs::obj_examine_; + or eax, 1; // unset ZF + retn; + } +} + void BugFixes::init() { #ifndef NDEBUG @@ -3151,6 +3175,11 @@ void BugFixes::init() // Fix the playback of the speech sound file for the death screen HookCall(0x481409, main_death_scene_hook); + + // Fix for trying to loot corpses with the "NoSteal" flag + SafeWrite8(0x4123F2, CommonObj::protoId); + BlockCall(0x4123F3); + MakeCall(0x4123F8, action_loot_container_hack, 1); } }