diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf index 4eec42fb1c4..f5bea2958f8 100644 --- a/addons/common/XEH_postInit.sqf +++ b/addons/common/XEH_postInit.sqf @@ -216,7 +216,9 @@ if (isServer) then { [QGVAR(setVectorDirAndUp), {(_this select 0) setVectorDirAndUp (_this select 1)}] call CBA_fnc_addEventHandler; [QGVAR(addWeaponItem), {(_this select 0) addWeaponItem [(_this select 1), (_this select 2)]}] call CBA_fnc_addEventHandler; [QGVAR(addMagazineTurret), {(_this select 0) addMagazineTurret (_this select 1)}] call CBA_fnc_addEventHandler; +[QGVAR(removeMagazineTurret), {(_this select 0) removeMagazineTurret [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler; [QGVAR(removeMagazinesTurret), {(_this select 0) removeMagazinesTurret [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler; +[QGVAR(setMagazineTurretAmmo), {(_this select 0) setMagazineTurretAmmo [_this select 1, _this select 2, _this select 3]}] call CBA_fnc_addEventHandler; [QGVAR(triggerAmmo), {triggerAmmo _this}] call CBA_fnc_addEventHandler; [QGVAR(setVanillaHitPointDamage), { diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf index 43ac730e09d..b6b97c856a2 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf @@ -39,16 +39,12 @@ if (_object getVariable [QGVAR(isAmmoDetonating), false]) exitWith {}; _object setVariable [QGVAR(isAmmoDetonating), true, true]; -_object setVariable [QGVAR(cookoffMagazines), _object call FUNC(getVehicleAmmo)]; +// Make sure that virtual magazines have been reset +_object setVariable [QGVAR(virtualMagazines), nil]; -// TODO: When setMagazineTurretAmmo and magazineTurretAmmo are fixed (https://feedback.bistudio.com/T79689), -// we can add gradual ammo removal during cook-off -if (GVAR(removeAmmoDuringCookoff)) then { - clearMagazineCargoGlobal _object; - - { - [QEGVAR(common,removeMagazinesTurret), [_object, _x select 0, _x select 1], _object, _x select 1] call CBA_fnc_turretEvent; - } forEach (magazinesAllTurrets _object); +// Save the vehicle's ammo, so it won't be removed during cook-off +if (!GVAR(removeAmmoDuringCookoff)) then { + _object setVariable [QGVAR(cookoffMagazines), [_object, true] call FUNC(getVehicleAmmo)]; }; [LINKFUNC(detonateAmmunitionServerLoop), [_object, _destroyWhenFinished, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf index 946cb4f7d8f..380849a1395 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf @@ -22,7 +22,15 @@ params ["_object", "_destroyWhenFinished", "_source", "_instigator"]; if (isNull _object) exitWith {}; -(_object getVariable QGVAR(cookoffMagazines)) params ["_magazines", "_totalAmmo"]; +// If the variable is set, it won't remove magazines +private _objectAmmo = _object getVariable QGVAR(cookoffMagazines); +private _removeAmmoDuringCookoff = isNil "_objectAmmo"; + +if (_removeAmmoDuringCookoff) then { + _objectAmmo = [_object, true] call FUNC(getVehicleAmmo); +}; + +_objectAmmo params ["_magazines", "_totalAmmo"]; private _hasFinished = _totalAmmo <= 0 || {_magazines isEqualTo []}; @@ -54,6 +62,7 @@ if ( // Reset variables, so the object can detonate its ammo again _object setVariable [QGVAR(cookoffMagazines), nil]; + _object setVariable [QGVAR(virtualMagazines), nil]; _object setVariable [QGVAR(isAmmoDetonating), nil, true]; // If done, destroy the object if necessary @@ -64,27 +73,72 @@ if ( private _magazineIndex = floor random (count _magazines); private _magazine = _magazines select _magazineIndex; -_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile"]; +_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile", "_magazineInfo"]; // Make sure ammo is at least 0 _ammoCount = _ammoCount max 0; // Remove some ammo, which will be detonated private _removed = _ammoCount min floor (1 + random (6 / GVAR(ammoCookoffDuration))); - -_ammoCount = _ammoCount - _removed; - -if (_ammoCount <= 0) then { - _magazines deleteAt _magazineIndex; +private _newAmmoCount = _ammoCount - _removed; + +// Remove ammo from magazines if enabled +if (_removeAmmoDuringCookoff) then { + switch (true) do { + // Turret magazines + case (_magazineInfo isEqualType []): { + // The chosen magazine is not guaranteed to the be one selected by setMagazineTurretAmmo, so get the current ammo count first + _newAmmoCount = ((_object magazineTurretAmmo [_magazineClassname, _magazineInfo]) - _removed) max 0; + + // Remove loaded magazine + if (_newAmmoCount <= 0) then { + [QEGVAR(common,removeMagazineTurret), [_object, _magazineClassname, _magazineInfo], _object, _magazineInfo] call CBA_fnc_turretEvent; + } else { + [QEGVAR(common,setMagazineTurretAmmo), [_object, _magazineClassname, _newAmmoCount, _magazineInfo], _object, _magazineInfo] call CBA_fnc_turretEvent; + }; + }; + // Inventory magazines + case (_magazineInfo isEqualTo false): { + // Remove selected magazine + _object addMagazineAmmoCargo [_magazineClassname, -1, _ammoCount]; + + // Add a new one with reduced ammo back + if (_newAmmoCount > 0) then { + _object addMagazineAmmoCargo [_magazineClassname, 1, _newAmmoCount]; + }; + }; + // Virtual magazines + case (_magazineInfo isEqualTo true): { + // Find the virtual magazines and update its count + private _virtualAmmo = _object getVariable [QGVAR(virtualMagazines), []]; + _magazineIndex = _virtualAmmo findIf {(_x select 0) == _magazineClassname}; + + if (_magazineIndex == -1) exitWith { + TRACE_1("no virtual magazine",_magazineClass); + }; + + if (_newAmmoCount <= 0) then { + _virtualAmmo deleteAt _magazineIndex; + } else { + (_virtualAmmo select _magazineIndex) set [1, _newAmmoCount]; // Remove ammo that was detonated + }; + }; + }; } else { - _magazine set [1, _ammoCount]; // remove ammo that was detonated + if (_newAmmoCount <= 0) then { + _magazines deleteAt _magazineIndex; + } else { + _magazine set [1, _newAmmoCount]; // Remove ammo that was detonated + }; }; private _timeBetweenAmmoDetonation = ((random 10 / sqrt _totalAmmo) min MAX_TIME_BETWEEN_AMMO_DET) max 0.1; TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation); -_totalAmmo = _totalAmmo - _removed; -_object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]]; +// Update total ammo value if mags aren't being removed (if they are, an updated total will be gotten upon the next ammo detonation iteration) +if (!_removeAmmoDuringCookoff) then { + _objectAmmo set [1, _totalAmmo - _removed]; +}; // Get magazine info, which is used to spawn projectiles private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; diff --git a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf index 35ca6fae263..daa7a19d44b 100644 --- a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf +++ b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf @@ -5,12 +5,14 @@ * * Arguments: * 0: Object + * 1: If the virtual magazine count should be set (default: false) * * Return Value: * 0: Ammo array * - 0: Magazine classname * - 1: Ammo count * - 2: If a projectile should be spawned upon detonation + * - 3: Additional info for detonation * 1: Total ammo count * * Example: @@ -19,7 +21,7 @@ * Public: No */ -params ["_object"]; +params ["_object", ["_setVirtualAmmoCount", false]]; TRACE_1("getVehicleAmmo",_object); private _ammoToDetonate = []; @@ -31,7 +33,7 @@ private _ammo = ""; // Get ammo from turrets { // If the turret is an FFV seat, it takes magazines from the soldier - _x params ["_magazine", "", "_count"]; + _x params ["_magazine", "_turretPath", "_count"]; if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then { _ammo = getText (_cfgMagazines >> _magazine >> "ammo"); @@ -42,7 +44,7 @@ private _ammo = ""; continue; }; - _ammoToDetonate pushBack [_magazine, _count, true]; + _ammoToDetonate pushBack [_magazine, _count, true, _turretPath]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAllTurrets [_object, true]); @@ -52,26 +54,42 @@ private _ammo = ""; _x params ["_magazine", "_count"]; if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then { - _ammoToDetonate pushBack [_magazine, _count, random 1 < 0.5]; + _ammoToDetonate pushBack [_magazine, _count, random 1 < 0.5, false]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAmmoCargo _object); -// Get ammo from transportAmmo / ace_rearm -private _configVehicle = configOf _object; -private _configSupply = (getNumber (_configVehicle >> "transportAmmo")) max (getNumber (_configVehicle >> QEGVAR(rearm,defaultSupply))); +private _virtualAmmo = _object getVariable QGVAR(virtualMagazines); -if (_object getVariable [QEGVAR(rearm,isSupplyVehicle), _configSupply > 0]) then { - TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _object); +if (isNil "_virtualAmmo") then { + // Get ammo from transportAmmo / ace_rearm + private _configVehicle = configOf _object; + private _configSupply = (getNumber (_configVehicle >> "transportAmmo")) max (getNumber (_configVehicle >> QEGVAR(rearm,defaultSupply))); - _ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000, false]; - _totalAmmo = _totalAmmo + 2000; + _virtualAmmo = []; - _ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100, true]; - _totalAmmo = _totalAmmo + 100; + if (_object getVariable [QEGVAR(rearm,isSupplyVehicle), _configSupply > 0]) then { + TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _object); - _ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10, true]; - _totalAmmo = _totalAmmo + 10; + _virtualAmmo pushBack ["2000Rnd_65x39_belt", 2000, false, true]; + _totalAmmo = _totalAmmo + 2000; + + _virtualAmmo pushBack ["20Rnd_105mm_HEAT_MP", 100, true, true]; + _totalAmmo = _totalAmmo + 100; + + _virtualAmmo pushBack ["SatchelCharge_Remote_Mag", 10, true, true]; + _totalAmmo = _totalAmmo + 10; + }; + + if (_setVirtualAmmoCount) then { + _object setVariable [QGVAR(virtualMagazines), _virtualAmmo]; + }; +} else { + { + _totalAmmo = _totalAmmo + (_x select 1); + } forEach _virtualAmmo; }; +_ammoToDetonate append _virtualAmmo; + [_ammoToDetonate, _totalAmmo]