diff --git a/addons/recorder/fnc_aceExplosives.sqf b/addons/recorder/fnc_aceExplosives.sqf index 3e41427..5908a46 100644 --- a/addons/recorder/fnc_aceExplosives.sqf +++ b/addons/recorder/fnc_aceExplosives.sqf @@ -38,34 +38,14 @@ if (!SHOULDSAVEEVENTS) exitWith {}; params ["_explosive", "_dir", "_pitch", "_unit"]; -// Resolve explosive metadata from config -private _explType = typeOf _explosive; -private _explosiveMag = getText(configFile >> "CfgAmmo" >> _explType >> "defaultMagazine"); -private _explosiveDisp = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "displayName"); -private _explosivePic = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "picture"); - -// Get placer's OCAP ID -private _unitOcapId = _unit getVariable [QGVARMAIN(id), -1]; -if (_unitOcapId isEqualTo -1) exitWith {}; - _explosive setVariable [QGVARMAIN(detonated), false]; -// Build :PLACED:CREATE: data — same format as vanilla mines in fnc_eh_fired_client.sqf -private _placedData = [ - EGVAR(recorder,captureFrameNo), // 0: captureFrameNo - -1, // 1: placedId (assigned by server) - _explType, // 2: className - _explosiveDisp, // 3: displayName - (getPosASL _explosive) joinString ",", // 4: position - _unitOcapId, // 5: firerOcapId - str (side group _unit), // 6: side - "put", // 7: weapon - _explosivePic // 8: magazineIcon -]; - -[QGVARMAIN(handlePlacedData), [_placedData, _explosive]] call CBA_fnc_serverEvent; - -// Attach lifecycle EHs — identical to vanilla path in fnc_eh_fired_client.sqf +// Attach lifecycle EHs on every machine. addEventHandler is local, and the +// EH only fires on the machine that owns the object at event-time, so +// registering everywhere keeps tracking resilient to locality transfers +// (e.g. placer disconnect → object transfers to server or another client). +// The server-side polling in fnc_eh_fired_server.sqf is a secondary safety +// net for the server-takeover case. _explosive addEventHandler ["HitExplosion", { params ["_explosive", "_hitEntity", "_explosiveOwner", "_hitThings"]; if (isNull _hitEntity) exitWith {}; @@ -111,3 +91,41 @@ _explosive addEventHandler ["Deleted", { ]; [QGVARMAIN(handlePlacedEvent), [_eventData]] call CBA_fnc_serverEvent; }]; + +// Send :PLACED:CREATE: from the server only, after a brief settle delay. +// ace_explosives_place fires before the explosive's position has synced on +// the server (getPosASL initially returns 0,0,~0; correct after ~1s), which +// previously caused recordings to show charges at the map origin. Reading +// after the delay on the server gives the authoritative settled position. +if (!isServer) exitWith {}; + +[{ + params ["_explosive", "_unit"]; + if (isNull _explosive || {isNull _unit}) exitWith {}; + + // Get placer's OCAP ID + private _unitOcapId = _unit getVariable [QGVARMAIN(id), -1]; + if (_unitOcapId isEqualTo -1) exitWith {}; + + // Resolve explosive metadata from config + private _explType = typeOf _explosive; + private _explosiveMag = getText(configFile >> "CfgAmmo" >> _explType >> "defaultMagazine"); + private _explosiveDisp = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "displayName"); + private _explosivePic = getText(configFile >> "CfgMagazines" >> _explosiveMag >> "picture"); + + // Build :PLACED:CREATE: data — same format as vanilla mines in fnc_eh_fired_client.sqf + private _placedData = [ + EGVAR(recorder,captureFrameNo), // 0: captureFrameNo + -1, // 1: placedId (assigned by server) + _explType, // 2: className + _explosiveDisp, // 3: displayName + (getPosASL _explosive) joinString ",", // 4: position + _unitOcapId, // 5: firerOcapId + str (side group _unit), // 6: side + "put", // 7: weapon + _explosivePic // 8: magazineIcon + ]; + + // handlePlacedData is registered server-side, so localEvent is sufficient + [QGVARMAIN(handlePlacedData), [_placedData, _explosive]] call CBA_fnc_localEvent; +}, [_explosive, _unit], 1] call CBA_fnc_waitAndExecute;