From befea69909d07d1153f2a7f664458ea25791d251 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 18 May 2023 09:56:12 +0800 Subject: [PATCH] Fixed "divided by zero" error when returning 0 in AMMOCOST hook * with CheckWeaponAmmoCost=1 Added a value check to the return value of AMMOCOST hook. Updated hookscripts.md to reflect this change. --- artifacts/ddraw.ini | 2 +- artifacts/scripting/hooks.yml | 4 +++- artifacts/scripting/hookscripts.md | 4 +++- sfall/Modules/Combat.cpp | 3 ++- sfall/Modules/HookScripts/CombatHs.cpp | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 048068bc..286a9a4d 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -619,7 +619,7 @@ ExplosionsEmitLight=0 ;MovieTimer_artimer4=360 ;Set to 1 to add proper check for ammo before attacking and proper calculation of the number of burst rounds -;By default, weapons can make attacks when at least one ammo is left, regardless of ammo cost calculations +;By default, a weapon can perform an attack with at least one ammo, regardless of ammo cost calculation ;Note that enabling this option will prevent super cattle prods and mega power fists from attacking with only one ammo left CheckWeaponAmmoCost=0 diff --git a/artifacts/scripting/hooks.yml b/artifacts/scripting/hooks.yml index 7f47fa4f..9aa78917 100644 --- a/artifacts/scripting/hooks.yml +++ b/artifacts/scripting/hooks.yml @@ -296,9 +296,11 @@ id: HOOK_AMMOCOST doc: | Runs when calculating ammo cost for a weapon. Doesn't affect damage, only how much ammo is spent.
- By default, weapons can make attacks when at least 1 ammo is left, regardless of ammo cost calculations.
+ By default, a weapon can perform an attack with at least one ammo, regardless of ammo cost calculation.
To add proper check for ammo before attacking and proper calculation of the number of burst rounds (hook type 1 and 2 in `arg3`), set **CheckWeaponAmmoCost=1** in **Misc** section of ddraw.ini. + __NOTE:__ The return value must be greater than or equal to 0 to be valid. + ``` Item arg0 - The weapon int arg1 - Number of bullets in burst or 1 for single shots diff --git a/artifacts/scripting/hookscripts.md b/artifacts/scripting/hookscripts.md index cc693557..a4f2af19 100644 --- a/artifacts/scripting/hookscripts.md +++ b/artifacts/scripting/hookscripts.md @@ -394,9 +394,11 @@ int ret1 - The new maximum damage #### `HOOK_AMMOCOST (hs_ammocost.int)` Runs when calculating ammo cost for a weapon. Doesn't affect damage, only how much ammo is spent.\ -By default, weapons can make attacks when at least 1 ammo is left, regardless of ammo cost calculations.\ +By default, a weapon can perform an attack with at least one ammo, regardless of ammo cost calculation.\ To add proper check for ammo before attacking and proper calculation of the number of burst rounds (hook type 1 and 2 in `arg3`), set **CheckWeaponAmmoCost=1** in **Misc** section of ddraw.ini. +__NOTE:__ The return value must be greater than or equal to 0 to be valid. + ``` Item arg0 - The weapon int arg1 - Number of bullets in burst or 1 for single shots diff --git a/sfall/Modules/Combat.cpp b/sfall/Modules/Combat.cpp index 84035e52..663c2928 100644 --- a/sfall/Modules/Combat.cpp +++ b/sfall/Modules/Combat.cpp @@ -110,7 +110,7 @@ long __fastcall Combat::check_item_ammo_cost(fo::GameObject* weapon, fo::AttackT } // calculate the cost - long cost = (newRounds != rounds) ? newRounds / rounds : 1; // 1 - default cost + long cost = (newRounds != rounds) ? (newRounds / rounds) : 1; // 1 - default cost return (cost > currAmmo) ? 0 : currAmmo; // 0 - this will force "Not Enough Ammo" } @@ -171,6 +171,7 @@ static long __fastcall divide_burst_rounds_by_ammo_cost(long currAmmo, fo::GameO roundsCost = burstRounds; // rounds in burst (the number of rounds fired in the burst) AmmoCostHook_Script(2, weapon, roundsCost); // roundsCost returns the new cost } + if (roundsCost == 0) return burstRounds; // cost is free, skip the rest of calculation long cost = burstRounds * roundsCost; // amount of ammo required for this burst (multiplied by 1 or by the value returned from HOOK_AMMOCOST) if (cost > currAmmo) cost = currAmmo; // if cost ammo more than current ammo, set it to current diff --git a/sfall/Modules/HookScripts/CombatHs.cpp b/sfall/Modules/HookScripts/CombatHs.cpp index bdec6da5..fcda0800 100644 --- a/sfall/Modules/HookScripts/CombatHs.cpp +++ b/sfall/Modules/HookScripts/CombatHs.cpp @@ -350,7 +350,7 @@ int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD RunHookScript(HOOK_AMMOCOST); - if (cRet > 0) rounds = rets[0]; // override rounds + if (cRet > 0 && (long)rets[0] >= 0) rounds = rets[0]; // override rounds failed: EndHook();