diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 155c7fc6..81850eea 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -1,5 +1,5 @@ ;sfall configuration settings -;v3.8.38.1 +;v3.8.39 [Main] ;Set to 1 if you want to use command line arguments to tell sfall to use another ini file @@ -621,10 +621,10 @@ ExplosionsEmitLight=0 ;MovieTimer_artimer3=270 ;MovieTimer_artimer4=360 -;Set to 1 to add proper check for ammo before attacking and proper calculation of the number of burst rounds +;Set to 1 to add proper checks for ammo before attacking ;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 +CheckWeaponAmmoCost=1 ;Controls the speed of combat panel animations (lower - faster; valid range: 0..65535) CombatPanelAnimDelay=1000 diff --git a/artifacts/scripting/hookscripts.md b/artifacts/scripting/hookscripts.md index 0b5f4b81..56bc6440 100644 --- a/artifacts/scripting/hookscripts.md +++ b/artifacts/scripting/hookscripts.md @@ -395,7 +395,7 @@ int ret1 - The new maximum damage Runs when calculating ammo cost for a weapon. Doesn't affect damage, only how much ammo is spent.\ 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. +To add proper checks for ammo before attacking (hook type 1 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. diff --git a/artifacts/scripting/sfall function notes.md b/artifacts/scripting/sfall function notes.md index 50a37a26..0a5ddd78 100644 --- a/artifacts/scripting/sfall function notes.md +++ b/artifacts/scripting/sfall function notes.md @@ -1039,7 +1039,7 @@ sfall_funcX metarule functions `void sfall_func4("set_spray_settings", int centerMult, int centerDiv, int targetMult, int targetDiv)` - Allows to dynamically change the multipilers and divisors for the bullet distribution of burst attacks. All settings are automatically reset to default values (**ComputeSpray_\*** settings in ddraw.ini) after each attack action -- Should be called before the calculation of the bullet distribution (e.g. in `HOOK_TOHIT` or `HOOK_AMMOCOST` with **CheckWeaponAmmoCost=1** in ddraw.ini) +- Should be called before the calculation of the bullet distribution (e.g. in `HOOK_TOHIT` or `HOOK_AMMOCOST`) - `centerDiv/targetDiv`: the minimum value of divisor is 1 - `centerMult/targetMult`: multiplier values are capped at divisor values - __NOTE:__ refer to the description of **ComputeSpray_\*** settings in ddraw.ini for details of the bullet distribution of burst attacks diff --git a/sfall/Modules/BurstMods.cpp b/sfall/Modules/BurstMods.cpp index af45f364..e0d9a6e6 100644 --- a/sfall/Modules/BurstMods.cpp +++ b/sfall/Modules/BurstMods.cpp @@ -46,8 +46,8 @@ static long __fastcall ComputeSpray(DWORD* roundsLeftOut, DWORD* roundsRightOut, if (roundsCenter == 0) roundsCenter = 1; *roundsCenterOut = roundsCenter; - long roundsLeft = (totalRounds - roundsCenter) / 2; - long roundsRight = totalRounds - roundsCenter - roundsLeft; + long roundsLeft = (totalRounds - roundsCenter) / 2; // minimum possible value is 0 + long roundsRight = totalRounds - roundsCenter - roundsLeft; // is either equal to or one more than roundsLeft if (roundsLeft != roundsRight && fo::func::roll_random(0, 1)) { // randomize the distribution of one extra bullet roundsLeft++; roundsRight--; diff --git a/sfall/Modules/Combat.cpp b/sfall/Modules/Combat.cpp index 4c1ae391..28d7a3dd 100644 --- a/sfall/Modules/Combat.cpp +++ b/sfall/Modules/Combat.cpp @@ -86,12 +86,12 @@ static bool hookedAimedShot; static std::vector disabledAS; static std::vector forcedAS; -static bool checkWeaponAmmoCost; +//static bool checkWeaponAmmoCost; // Compares the cost (required count of rounds) for one shot with the current amount of ammo to make an attack or other checks -long __fastcall Combat::check_item_ammo_cost(fo::GameObject* weapon, fo::AttackType hitMode) { +static long __fastcall check_item_ammo_cost(fo::GameObject* weapon, fo::AttackType hitMode) { long currAmmo = game::Items::item_w_curr_ammo(weapon); - if (!checkWeaponAmmoCost || currAmmo <= 0) return currAmmo; + if (currAmmo <= 0) return 0; long rounds = 1; // default ammo for single shot @@ -119,7 +119,7 @@ static void __declspec(naked) combat_check_bad_shot_hook() { push edx; push ecx; // weapon mov edx, edi; // hitMode - call Combat::check_item_ammo_cost; + call check_item_ammo_cost; pop ecx; pop edx; retn; @@ -133,7 +133,7 @@ static void __declspec(naked) ai_search_inven_weap_hook() { push ecx; mov edx, ATKTYPE_RWEAPON_PRIMARY; // hitMode mov ecx, eax; // weapon - call Combat::check_item_ammo_cost; // enough ammo? + call check_item_ammo_cost; // enough ammo? pop ecx; retn; } @@ -175,7 +175,7 @@ static long __fastcall divide_burst_rounds_by_ammo_cost(long currAmmo, fo::GameO 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 - return (cost / roundsCost); // divide back to get proper number of rounds for damage calculations + return max(1, (cost / roundsCost)); // divide back to get proper number of rounds for damage calculations (minimum is 1) } static void __declspec(naked) compute_spray_hack() { @@ -579,9 +579,8 @@ void Combat::init() { // Disables secondary burst attacks for the critter MakeCall(0x429E44, ai_pick_hit_mode_hack_noBurst, 1); - checkWeaponAmmoCost = (IniReader::GetConfigInt("Misc", "CheckWeaponAmmoCost", 0) != 0); - if (checkWeaponAmmoCost) { - MakeCall(0x4234B3, compute_spray_hack, 1); + MakeCall(0x4234B3, compute_spray_hack, 1); // proper calculation of the number of burst rounds + if (IniReader::GetConfigInt("Misc", "CheckWeaponAmmoCost", 1)) { HookCall(0x4266E9, combat_check_bad_shot_hook); HookCall(0x429A37, ai_search_inven_weap_hook); // check if there is enough ammo to shoot HookCall(0x42A95D, ai_try_attack_hook); // jz func diff --git a/sfall/Modules/Combat.h b/sfall/Modules/Combat.h index 748ee307..16fa492a 100644 --- a/sfall/Modules/Combat.h +++ b/sfall/Modules/Combat.h @@ -50,8 +50,6 @@ public: static long determineHitChance; - static long __fastcall check_item_ammo_cost(fo::GameObject* weapon, fo::AttackType hitMode); - static bool IsBurstDisabled(fo::GameObject* critter); }; diff --git a/sfall/version.h b/sfall/version.h index b6aa5e82..3383b013 100644 --- a/sfall/version.h +++ b/sfall/version.h @@ -24,7 +24,7 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 8 -#define VERSION_BUILD 38 -#define VERSION_REV 1 +#define VERSION_BUILD 39 +#define VERSION_REV 0 -#define VERSION_STRING "3.8.38.1" +#define VERSION_STRING "3.8.39"