Skip to content

Commit b2a43b5

Browse files
committed
fix: track static weapon shots bypassing FiredMan (ACE CSW compat)
ACE Crew Served Weapons fires static weapons via forceWeaponFire on the vehicle, which may not trigger the unit's FiredMan EH that OCAP relies on. For mortars with allowFireOnLoad, ACE also creates a temporary AI agent as gunner when the seat is empty (solo mortar use), and this agent has no OCAP ID. Add a StaticWeapon Fired class EH as fallback that catches vehicle-level firing events, resolves the gunner, and forwards to the existing tracking handlers. When the gunner is an ACE CSW agent (no OCAP ID), falls back to ace_csw_reloader to attribute the shot to the actual player who loaded the weapon. A dedup guard in eh_fired_client prevents double-tracking when both FiredMan and the vehicle Fired EH fire for the same projectile.
1 parent 7eca09e commit b2a43b5

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

addons/recorder/fnc_eh_fired_client.sqf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ if (isNil "_projectile") exitWith {
1515
false;
1616
};
1717

18+
// Dedup guard — when both FiredMan (unit) and Fired (vehicle) EHs fire for the
19+
// same shot, only the first one to run should process. The second sees
20+
// projectileData already set and exits.
21+
if (!isNil {_projectile getVariable QGVARMAIN(projectileData)}) exitWith {false};
22+
1823
// Zeus remote control fix: FiredMan fires on the controller's body, not the
1924
// controlled unit. bis_fnc_moduleRemoteControl_unit (local to the controller's
2025
// machine) gives us the actual unit doing the firing.

addons/recorder/fnc_eh_fired_server.sqf

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,38 @@ GVAR(trackedPlacedObjects) = createHashMap;
125125
// allow inheritance, don't exclude anything, and apply retroactively
126126
}, true, [], true] call CBA_fnc_addClassEventHandler;
127127

128+
// Fallback for static weapons whose shots bypass FiredMan on the gunner unit.
129+
// ACE Crew Served Weapons (CSW) fires the vehicle weapon via forceWeaponFire,
130+
// which may not trigger the unit's FiredMan EH. Additionally, for mortars with
131+
// allowFireOnLoad, ACE creates a temporary AI agent as gunner when the seat is
132+
// empty (solo mortar use) — this agent has no OCAP ID.
133+
// The dedup guard in eh_fired_client prevents double-tracking when both fire.
134+
["StaticWeapon", "Fired", {
135+
params ["_vehicle", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile"];
136+
137+
if (!local _vehicle) exitWith {};
138+
139+
// If FiredMan already handled this projectile, skip
140+
if (!isNil {_projectile getVariable QGVARMAIN(projectileData)}) exitWith {};
141+
142+
private _firer = gunner _vehicle;
143+
if (isNull _firer) exitWith {};
144+
145+
// ACE CSW agent fallback: when the gunner is a temporary agent (no OCAP ID),
146+
// the actual operator is stored as ace_csw_reloader on the vehicle.
147+
if ((_firer getVariable [QGVARMAIN(id), -1]) isEqualTo -1) then {
148+
private _reloader = _vehicle getVariable ["ace_csw_reloader", objNull];
149+
if (!isNull _reloader) then {
150+
_firer = _reloader;
151+
};
152+
};
153+
154+
// Forward to existing handlers with FiredMan-compatible params
155+
private _params = [_firer, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile, _vehicle];
156+
_params call FUNC(eh_fired_client);
157+
_params call FUNC(eh_firedMan);
158+
}, true, [], true] call CBA_fnc_addClassEventHandler;
159+
128160

129161
// Finally, we'll add a CBA Event Handler to take in the pre-processed fired data here on the server and send it to the extension.
130162
[QGVARMAIN(handleFiredManData), {

0 commit comments

Comments
 (0)