From fc3b7180af231be9314b1f50e828e0b455534a04 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 15 Jul 2019 09:59:58 +0800 Subject: [PATCH] Backported the code of COMBATDAMAGE hook from 4.x Moved instadeath crit fix from COMBATDAMAGE hook to BugFixes.cpp. Completed the compute_attack struct. Updated version number. --- artifacts/ddraw.ini | 2 +- sfall/BugFixes.cpp | 25 ++++++++ sfall/FalloutStructs.h | 29 +++++---- sfall/HookScripts.cpp | 129 +++++++++++++++++------------------------ sfall/version.h | 6 +- 5 files changed, 100 insertions(+), 91 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index a91a8153..a4367651 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -1,5 +1,5 @@ ;sfall configuration settings -;v3.8.19 +;v3.8.20 [Main] ;Change to 1 if you want to use command line args to tell sfall to use another ini file. diff --git a/sfall/BugFixes.cpp b/sfall/BugFixes.cpp index ba740efb..d9e1dd2a 100644 --- a/sfall/BugFixes.cpp +++ b/sfall/BugFixes.cpp @@ -1440,6 +1440,26 @@ end: } } +//zero damage insta death criticals fix (moved from compute_damage hook) +static void __fastcall InstantDeathFix(TComputeAttack &ctd) { + if (ctd.targetDamage == 0 && (ctd.targetFlags & DAM_DEAD)) { + ctd.targetDamage++; // set 1 hp damage + } +} + +static const DWORD ComputeDamageRet = 0x424BA7; +static void __declspec(naked) compute_damage_hack() { + __asm { + mov ecx, esi; // ctd + call InstantDeathFix; + // overwritten engine code + add esp, 0x34; + pop ebp; + pop edi; + jmp ComputeDamageRet; + } +} + static int currDescLen = 0; static bool showItemDescription = false; static void __stdcall AppendText(const char* text, const char* desc) { @@ -2573,6 +2593,11 @@ void BugFixesInit() // in their AI packages is set to stay_close/charge, or NPCsTryToSpendExtraAP is enabled HookCall(0x42A1A8, ai_move_steps_closer_hook); // 0x42B24D + // Fix instant death critical + dlog("Applying instant death fix.", DL_INIT); + MakeJump(0x424BA2, compute_damage_hack); + dlogr(" Done", DL_INIT); + // Fix missing AC/DR mod stats when examining ammo in the barter screen dlog("Applying fix for displaying ammo stats in barter screen.", DL_INIT); MakeCall(0x49B4AD, obj_examine_func_hack_ammo0, 2); diff --git a/sfall/FalloutStructs.h b/sfall/FalloutStructs.h index c387de74..21de93cd 100644 --- a/sfall/FalloutStructs.h +++ b/sfall/FalloutStructs.h @@ -78,20 +78,27 @@ struct TGameObj #pragma pack(push, 1) struct TComputeAttack { - TGameObj *attacker; - char gap_4[4]; - TGameObj *weapon; - char gap_C[4]; - long damageAttacker; - long flagsAttacker; - long rounds; - char gap_1C[4]; - TGameObj *target; + TGameObj* attacker; + long hitMode; + TGameObj* weapon; + long field_C; + long attackerDamage; + long attackerFlags; + long numRounds; + long message; + TGameObj* target; long targetTile; long bodyPart; - long damageTarget; - long flagsTarget; + long targetDamage; + long targetFlags; long knockbackValue; + TGameObj* mainTarget; + long numExtras; + TGameObj* extraTarget[6]; + long extraBodyPart[6]; + long extraDamage[6]; + long extraFlags[6]; + long extraKnockbackValue[6]; }; #pragma pack(pop) diff --git a/sfall/HookScripts.cpp b/sfall/HookScripts.cpp index 057ee6df..ad6f2bb2 100644 --- a/sfall/HookScripts.cpp +++ b/sfall/HookScripts.cpp @@ -366,76 +366,53 @@ skip: } } -static void __declspec(naked) CombatDamageHook() { +// 4.x backport +static void __fastcall ComputeDamageHook_Script(TComputeAttack &ctd, DWORD rounds, DWORD multiplier) { + BeginHook(); + argCount = 12; + + args[0] = (DWORD)ctd.target; // Target + args[1] = (DWORD)ctd.attacker; // Attacker + args[2] = ctd.targetDamage; // amountTarget + args[3] = ctd.attackerDamage; // amountSource + args[4] = ctd.targetFlags; // flagsTarget + args[5] = ctd.attackerFlags; // flagsSource + args[6] = (DWORD)ctd.weapon; + args[7] = ctd.bodyPart; + args[8] = multiplier; // damage multiplier + args[9] = rounds; // number of rounds + args[10] = ctd.knockbackValue; + args[11] = ctd.hitMode; // attack type + + RunHookScript(HOOK_COMBATDAMAGE); + + if (cRet > 0) { + ctd.targetDamage = rets[0]; + if (cRet > 1) { + ctd.attackerDamage = rets[1]; + if (cRet > 2) { + ctd.targetFlags = rets[2]; // flagsTarget + if (cRet > 3) { + ctd.attackerFlags = rets[3]; // flagsSource + if (cRet > 4) ctd.knockbackValue = rets[4]; + } + } + } + } + EndHook(); +} + +static void __declspec(naked) ComputeDamageHook() { __asm { - push edx; - push ebx; - push eax; + push ecx; + push ebx; // store dmg multiplier args[8] + push edx; // store num of rounds args[9] + push eax; // store ctd call compute_damage_; - pop edx; - - //zero damage insta death criticals fix - mov ebx, [edx+0x2c]; - test ebx, ebx; - jnz hookscript; - mov ebx, [edx+0x30]; - test bl, 0x80; - jz hookscript; - inc dword ptr ds:[edx+0x2c]; -hookscript: - hookbegin(12); - mov ebx, [edx+0x20]; - mov args[0x00], ebx; - mov ebx, [edx+0x00]; - mov args[0x04], ebx; - mov ebx, [edx+0x2c]; - mov args[0x08], ebx; - mov ebx, [edx+0x10]; - mov args[0x0c], ebx; - mov ebx, [edx+0x30]; - mov args[0x10], ebx; - mov ebx, [edx+0x14]; - mov args[0x14], ebx; - mov ebx, [edx+0x08]; - mov args[0x18], ebx; - mov ebx, [edx+0x28]; - mov args[0x1c], ebx; - pop ebx; // roll result - mov args[0x20], ebx; - pop ebx; // num rounds - mov args[0x24], ebx; - mov ebx, [edx+0x34]; // knockback value - mov args[0x28], ebx; - mov ebx, [edx+0x04]; // attack type - mov args[0x2c], ebx; - - pushad; - push HOOK_COMBATDAMAGE; - call RunHookScript; - popad; - - cmp cRet, 1; - jl end; - mov ebx, rets[0x00]; - mov [edx+0x2c], ebx; - cmp cRet, 2; - jl end; - mov ebx, rets[0x04]; - mov [edx+0x10], ebx; - cmp cRet, 3; - jl end; - mov ebx, rets[0x08]; - mov [edx+0x30], ebx; - cmp cRet, 4; - jl end; - mov ebx, rets[0x0c]; - mov [edx+0x14], ebx; - cmp cRet, 5; - jl end; - mov ebx, rets[0x10]; - mov [edx+0x34], ebx; // knockback -end: - hookend; + pop ecx; // restore ctd (eax) + pop edx; // restore num of rounds + call ComputeDamageHook_Script; // stack - arg multiplier + pop ecx; retn; } } @@ -1486,14 +1463,14 @@ static void HookScriptInit2() { HookCall(0x4109BF, &CalcDeathAnimHook2); LoadHookScript("hs_combatdamage", HOOK_COMBATDAMAGE); - HookCall(0x42326C, &CombatDamageHook); // check_ranged_miss() - HookCall(0x4233E3, &CombatDamageHook); // shoot_along_path() - for extra burst targets - HookCall(0x423AB7, &CombatDamageHook); // compute_attack() - HookCall(0x423BBF, &CombatDamageHook); // compute_attack() - HookCall(0x423DE7, &CombatDamageHook); // compute_explosion_on_extras() - HookCall(0x423E69, &CombatDamageHook); // compute_explosion_on_extras() - HookCall(0x424220, &CombatDamageHook); // attack_crit_failure() - HookCall(0x4242FB, &CombatDamageHook); // attack_crit_failure() + HookCall(0x42326C, ComputeDamageHook); // check_ranged_miss() + HookCall(0x4233E3, ComputeDamageHook); // shoot_along_path() - for extra burst targets + HookCall(0x423AB7, ComputeDamageHook); // compute_attack() + HookCall(0x423BBF, ComputeDamageHook); // compute_attack() + HookCall(0x423DE7, ComputeDamageHook); // compute_explosion_on_extras() + HookCall(0x423E69, ComputeDamageHook); // compute_explosion_on_extras() + HookCall(0x424220, ComputeDamageHook); // attack_crit_failure() + HookCall(0x4242FB, ComputeDamageHook); // attack_crit_failure() LoadHookScript("hs_ondeath", HOOK_ONDEATH); HookCall(0x4130CC, &OnDeathHook); diff --git a/sfall/version.h b/sfall/version.h index 92697cc9..dd78cf17 100644 --- a/sfall/version.h +++ b/sfall/version.h @@ -24,13 +24,13 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 8 -#define VERSION_BUILD 19 +#define VERSION_BUILD 20 #define VERSION_REV 0 #ifdef WIN2K -#define VERSION_STRING "3.8.19 win2k" +#define VERSION_STRING "3.8.20 win2k" #else -#define VERSION_STRING "3.8.19" +#define VERSION_STRING "3.8.20" #endif //#define CHECK_VAL (4)