From 71a7545445edb9f0e62912865cb457336622f728 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 29 Feb 2024 13:19:30 +0800 Subject: [PATCH] Added additional check to AI weapon switching fix --- sfall/Game/combatAI.cpp | 4 ++-- sfall/Game/combatAI.h | 2 +- sfall/Modules/AI.cpp | 7 +++++-- sfall/Modules/HookScripts/CombatHs.cpp | 4 ++-- sfall/Modules/HookScripts/CombatHs.h | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sfall/Game/combatAI.cpp b/sfall/Game/combatAI.cpp index aefdaa5d..cf8d29ea 100644 --- a/sfall/Game/combatAI.cpp +++ b/sfall/Game/combatAI.cpp @@ -19,13 +19,13 @@ namespace game namespace sf = sfall; static const long aiUseItemAPCost = 2; -/* + // Implementation of ai_can_use_weapon_ engine function with the HOOK_CANUSEWEAPON hook bool CombatAI::ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode) { bool result = fo::func::ai_can_use_weapon(source, weapon, hitMode); return sf::CanUseWeaponHook_Invoke(result, source, weapon, hitMode); } -*/ + static long drugUsePerfFixMode; void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) { diff --git a/sfall/Game/combatAI.h b/sfall/Game/combatAI.h index 56da8b10..333830ee 100644 --- a/sfall/Game/combatAI.h +++ b/sfall/Game/combatAI.h @@ -15,7 +15,7 @@ class CombatAI { public: static void init(); - //static bool ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode); + static bool ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode); static void __stdcall ai_check_drugs(fo::GameObject* source); }; diff --git a/sfall/Modules/AI.cpp b/sfall/Modules/AI.cpp index f94090a9..3f9e38aa 100644 --- a/sfall/Modules/AI.cpp +++ b/sfall/Modules/AI.cpp @@ -243,10 +243,13 @@ static long __fastcall ai_try_attack_switch_fix(fo::GameObject* target, long &hi } } + bool canUseCurr = game::CombatAI::ai_can_use_weapon(source, weapon, hitMode); + // does the NPC have other weapons in inventory? fo::GameObject* item = fo::func::ai_search_inven_weap(source, 1, target); // search based on AP if (item) { - // is using a close range weapon? + if (!canUseCurr) return 1; // can't use current weapon, so switch anyway + // is it a close-range weapon? long wType = fo::func::item_w_subtype(item, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY); if (wType <= fo::AttackSubType::MELEE) { // unarmed and melee weapons, check the distance before switching if (!game::ai::AIHelpers::AttackInRange(source, item, target)) return -1; // target out of range, exit ai_try_attack_ @@ -255,7 +258,7 @@ static long __fastcall ai_try_attack_switch_fix(fo::GameObject* target, long &hi } // no other weapon in inventory - if (fo::func::item_w_range(source, fo::AttackType::ATKTYPE_PUNCH) >= fo::func::obj_dist(source, target)) { + if (!canUseCurr || fo::func::item_w_range(source, fo::AttackType::ATKTYPE_PUNCH) >= fo::func::obj_dist(source, target)) { hitMode = fo::AttackType::ATKTYPE_PUNCH; return 0; // change hit mode, continue attack cycle } diff --git a/sfall/Modules/HookScripts/CombatHs.cpp b/sfall/Modules/HookScripts/CombatHs.cpp index 78bc68d8..a4647f10 100644 --- a/sfall/Modules/HookScripts/CombatHs.cpp +++ b/sfall/Modules/HookScripts/CombatHs.cpp @@ -680,13 +680,13 @@ static void __declspec(naked) CanUseWeaponHook() { retn; } } -/* + bool CanUseWeaponHook_Invoke(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode) { return (HookScripts::HookHasScript(HOOK_CANUSEWEAPON)) ? CanUseWeaponHook_Script(result, source, weapon, hitMode) : result; } -*/ + //////////////////////////////////////////////////////////////////////////////// void Inject_ToHitHook() { diff --git a/sfall/Modules/HookScripts/CombatHs.h b/sfall/Modules/HookScripts/CombatHs.h index d9fc6c45..941447ec 100644 --- a/sfall/Modules/HookScripts/CombatHs.h +++ b/sfall/Modules/HookScripts/CombatHs.h @@ -26,6 +26,6 @@ int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD long CalcApCostHook_Invoke(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon); //void FindTargetHook_Invoke(fo::GameObject* targets[], fo::GameObject* attacker); //fo::GameObject* BestWeaponHook_Invoke(fo::GameObject* bestWeapon, fo::GameObject* source, fo::GameObject* weapon1, fo::GameObject* weapon2, fo::GameObject* target); -//bool CanUseWeaponHook_Invoke(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode); +bool CanUseWeaponHook_Invoke(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode); }