bugfix: Prevent cases where weapons would partially fire and require reloading without actually firing a shot - #3416
Conversation
…reloading without actually firing a shot
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review. Walkthrough
ChangesAttack range validation
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Low Suggested reviewers: Merge Risk: ⚪ Minimal · up to The reported linked-turret ammunition loss is not established for current weapon configurations. No actionable merge-blocking risk remains after normal checks. Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 2 systems. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| #if !RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @bugfix Stubbjax 28/09/2026 The target may have moved out of range since we entered this | ||
| // state, so we check the range again to avoid partially firing the weapon. | ||
| if (!weapon->hasLeechRange()) |
There was a problem hiding this comment.
🟠 High AI/AIStates.cpp:5246
The range guard can still let a linked turret call fireWeapon out of range, consuming that weapon's clip/reload state without producing a shot. It validates only the currently selected weapon at line 5246, while the linked position-attack path fires every weapon slot in the loop at lines 5326–5340; validate each slot's weapon (including its own hasLeechRange() exemption) before calling fireWeapon.
🤖 Copy this AI Prompt to have your agent fix this:
In file @GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp around line 5246:
The range guard can still let a linked turret call `fireWeapon` out of range, consuming that weapon's clip/reload state without producing a shot. It validates only the currently selected `weapon` at line 5246, while the linked position-attack path fires every weapon slot in the loop at lines 5326–5340; validate each slot's weapon (including its own `hasLeechRange()` exemption) before calling `fireWeapon`.
|
| Bool inRange = m_att->isAttackingObject() | ||
| ? weapon->isWithinAttackRange(obj, victim) | ||
| : weapon->isWithinAttackRange(obj, getMachineGoalPosition()); | ||
|
|
||
| if (!inRange) | ||
| return STATE_FAILURE; |
There was a problem hiding this comment.
Linked turrets lose valid shots When linked turrets attack a position, this check tests only the current weapon, but the firing branch fires every linked weapon slot. If the target moves beyond the current weapon’s range while remaining within another linked weapon’s range,
STATE_FAILURE prevents that other weapon from firing a valid shot. Check the weapons that will fire rather than using one slot to gate all of them.
There was a problem hiding this comment.
Yes, this is a valid concern. weapon is only the weapon selected when the state is entered, but the multi-turret path below this check can fire all linked weapon slots. If that selected weapon is out of range while another linked weapon is still in range, this early STATE_FAILURE aborts the entire state before the valid linked weapon gets a chance to fire. The range guard should be applied per weapon in the linked-weapon firing path (or otherwise determine whether any weapon that will fire is in range), rather than gating the whole state using only weapon.
There was a problem hiding this comment.
So the complaint is that this piece only checks one weapon, but further down below there are more weapons being considered.
There was a problem hiding this comment.
Yes—that is the concern. This guard evaluates only the single weapon pointer captured before the multi-turret handling. The code below can then process/fire the linked weapon slots as well. Therefore, if the selected weapon is now out of range but another linked weapon is still in range, this early STATE_FAILURE aborts the state and suppresses a valid shot from that other weapon. The range decision should account for each weapon that the subsequent branch will actually fire (or allow the state to continue when at least one such weapon remains in range).
| } | ||
|
|
||
| #if !RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @bugfix Stubbjax 28/09/2026 The target may have moved out of range since we entered this |
There was a problem hiding this comment.
Is there an alternative way to deal with it by calling the update immediately instead of next frame?
There was a problem hiding this comment.
This was my initial consideration too but it seems like a much riskier/consequential change and there's seemingly no precedent for it.
There was a problem hiding this comment.
I understand it likely will be more complicated. Judging from the video the current fix addresses the issue only half way. The Jarmen no longer wastes a snipe with no effect, but it also stops moving and is unable to perform the shot when arguably it should be able to take the shot with no frame delay, which is the reason it stops moving in the first place. What happens now is that he needs to stand still for 1 frame which may or may not be enough to take the shot. Is the outcome different in 30 vs higher logic tick rates?
The fix seems ok for now, but maybe it should go further in the future. It is controversial, because it will be a buff for chasing weapons. It likely will be very good for all factions vs USA because USA relies on the evading Humvee playstyle.
Fixes #113
This change fixes an issue where weapons could partially fire and trigger their time and clip reloads without actually firing a shot. This could happen with all weapons, but those with long reload times are the most conspicuous, such as Jarmen Kell's sniper rifle or a Scorpion's rocket.
This occurred because the target-is-in-range checks are done prior to deciding to fire a weapon, but the actual firing of the weapon is done on the next frame. The weapon-firing logic has a few range guards which abort firing the weapon, but these checks come after the clip/reload/effect handling. Putting another range check before actually firing the weapon in the
AIAttackFireWeaponState::updateis the simplest/safest solution while maintaining retail compatibility.Before
Jarmen Kell fires upon the Humvee, but the shot does nothing
BEFORE.mp4
After
Jarmen Kell does not fire upon the Humvee
AFTER.mp4