diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index b8a9523496..a0da68bfb9 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -12,41 +12,37 @@ if (isServer) then { [QGVAR(detonateAmmunition), LINKFUNC(detonateAmmunition)] call CBA_fnc_addEventHandler; }; -// Handle cleaning up effects when vehicle is deleted mid cook-off -[QGVAR(addCleanupHandlers), { - params ["_object"]; - - // Don't add a new EH if cook-off is run multiple times - if (!isNil {_object getVariable QGVAR(deletedEH)}) exitWith {}; - - _object setVariable [QGVAR(deletedEH), - _object addEventHandler ["Deleted", { - [QGVAR(cleanupEffects), _this select 0] call CBA_fnc_localEvent; - }] - ]; -}] call CBA_fnc_addEventHandler; - -[QGVAR(cleanupEffects), { - params ["_object"]; - - if (isServer) then { - // Reset, so that the object can cook-off again - _object setVariable [QGVAR(isCookingOff), nil, true]; - - // Remove effects from JIP - { - _x call CBA_fnc_removeGlobalEventJIP; - } forEach (_object getVariable [QGVAR(jipIDs), []]); - - _object setVariable [QGVAR(jipIDs), nil]; - }; - - // All effects are local (apart from sound, which is global, but is handled by server) +// Handle cleaning up effects when objects are deleted mid cook-off +["AllVehicles", "Deleted", { { deleteVehicle _x; - } forEach (_object getVariable [QGVAR(effects), []]); + } forEach ((_this select 0) getVariable [QGVAR(vehicleEffects), []]); +}, nil, nil, true] call CBA_fnc_addClassEventHandler; - _object setVariable [QGVAR(effects), nil]; +["ReammoBox_F", "Deleted", { + { + deleteVehicle _x; + } forEach ((_this select 0) getVariable [QGVAR(boxEffects), []]); +}, nil, nil, true] call CBA_fnc_addClassEventHandler; + +[QGVAR(cleanupVehicleEffects), { + params ["_object"]; + + { + deleteVehicle _x; + } forEach (_object getVariable [QGVAR(vehicleEffects), []]); + + _object setVariable [QGVAR(vehicleEffects), nil]; +}] call CBA_fnc_addEventHandler; + +[QGVAR(cleanupBoxEffects), { + params ["_object"]; + + { + deleteVehicle _x; + } forEach (_object getVariable [QGVAR(boxEffects), []]); + + _object setVariable [QGVAR(boxEffects), nil]; }] call CBA_fnc_addEventHandler; ["ReammoBox_F", "init", { diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index f278cb51ce..61a6631a8b 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -7,14 +7,15 @@ * Arguments: * 0: Vehicle * 1: Intensity of fire - * 2: Instigator (default: objNull) - * 3: Delay between smoke and fire enabled (default: true) - * 4: Ammo detonation chance (default: 0) - * 5: Detonate after cook-off (default: false) - * 6: Selection for fire source (default: "") - * 7: Can spawn fire ring (default: true) - * 8: Can spawn fire jet (default: true) - * 9: Maximum intensity (default: MAX_COOKOFF_INTENSITY) + * 2: Source (default: objNull) + * 3: Instigator (default: objNull) + * 4: Delay between smoke and fire enabled (default: true) + * 5: Ammo detonation chance (default: 0) + * 6: Detonate after cook-off (default: false) + * 7: Selection for fire source (default: "") + * 8: Can spawn fire ring (default: true) + * 9: Can spawn fire jet (default: true) + * 10: Maximum intensity (default: MAX_COOKOFF_INTENSITY) * * Return Value: * None @@ -31,6 +32,7 @@ if (GVAR(enable) == 0 || {GVAR(cookoffDuration) == 0}) exitWith {}; params [ "_vehicle", "_intensity", + ["_source", objNull], ["_instigator", objNull], ["_delayBetweenSmokeAndFire", true], ["_ammoDetonationChance", 0], @@ -41,6 +43,8 @@ params [ ["_maxIntensity", MAX_COOKOFF_INTENSITY] ]; +if !(_vehicle isKindOf "AllVehicles") exitWith {}; + // Check if cook-off is disabled on vehicle specifically if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; @@ -54,9 +58,6 @@ if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {}; _vehicle setVariable [QGVAR(isCookingOff), true, true]; -// Only required on the server, as the only effect to clean up is to remove the effects from the JIP queue -[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent; - // Limit maximum value of intensity to prevent very long cook-off times _intensity = _intensity min _maxIntensity; @@ -81,7 +82,6 @@ private _fireJipID = format [QGVAR(cookOffEffect_%1), hashValue _vehicle]; // Spawn smoke private _smokeJipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP; -_vehicle setVariable [QGVAR(jipIDs), [_smokeJipID, _fireJipID]]; // Save intensity for looping purposes _vehicle setVariable [QGVAR(intensity), _intensity]; @@ -94,21 +94,25 @@ if (_delayBetweenSmokeAndFire) then { [{ [{ - (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_fireJipID"]; + (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_source", "_instigator", "_fireSource", "_canRing", "_canJet", "_smokeJipID", "_fireJipID"]; private _intensity = _vehicle getVariable [QGVAR(intensity), 0]; if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith { (_this select 1) call CBA_fnc_removePerFrameHandler; + // Remove effects from JIP + _smokeJipID call CBA_fnc_removeGlobalEventJIP; + _fireJipID call CBA_fnc_removeGlobalEventJIP; + // Effects are deleted when vehicle is deleted if (isNull _vehicle) exitWith {}; - // Remove effects on server - [QGVAR(cleanupEffects), _vehicle] call CBA_fnc_localEvent; + // Remove effects + [QGVAR(cleanupVehicleEffects), _vehicle] call CBA_fnc_globalEvent; if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then { - _vehicle setDamage [1, true, _instigator, _instigator]; // because it's running on the server, killer and instigator can be set + _vehicle setDamage [1, true, _source, _instigator]; // because it's running on the server, killer and instigator can be set }; }; @@ -146,7 +150,7 @@ if (_delayBetweenSmokeAndFire) then { }; }; - if (_ammoDetonationChance > random 1 && {CBA_missionTime >= _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]}) then { + if (_ammoDetonationChance > random 1 && {_vehicle getVariable [QGVAR(nextExplosiveDetonation), 0] <= CBA_missionTime}) then { if (_fireSource isEqualTo "") then { _fireSource = selectRandom _positions; }; @@ -156,4 +160,4 @@ if (_delayBetweenSmokeAndFire) then { _vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60]; }; }, 0.25, _this] call CBA_fnc_addPerFrameHandler; -}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _fireJipID], _delay] call CBA_fnc_waitAndExecute; +}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _source, _instigator, _fireSource, _canRing, _canJet, _smokeJipID, _fireJipID], _delay] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index cfea21dd3e..564762ab87 100644 --- a/addons/cookoff/functions/fnc_cookOffBox.sqf +++ b/addons/cookoff/functions/fnc_cookOffBox.sqf @@ -5,7 +5,7 @@ * * Arguments: * 0: Ammo box - * 1: Killer (default: objNull) + * 1: Source (default: objNull) * 2: Instigator (default: objNull) * * Return Value: @@ -19,7 +19,10 @@ if (!isServer) exitWith {}; -params ["_box", ["_killer", objNull], ["_instigator", objNull]]; +params ["_box", ["_source", objNull], ["_instigator", objNull]]; + +// Make sure it's a box +if !(_box isKindOf "ReammoBox_F") exitWith {}; if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; @@ -28,7 +31,7 @@ _box setVariable [QGVAR(isCookingOff), true, true]; // Spawn cook-off effects on all connected machines private _jipID = [QGVAR(cookOffBoxLocal), [ _box, - _killer, + _source, _instigator, CBA_missionTime, random [SMOKE_DELAY / 2, SMOKE_DELAY, SMOKE_DELAY / 2 * 3] // generate random timer that is global synced diff --git a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf index e0510905c2..9b8435c007 100644 --- a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf +++ b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf @@ -5,7 +5,7 @@ * * Arguments: * 0: Box - * 1: Killer + * 1: Source * 2: Instigator * 3: Start time of the cook-off * 4: Smoke delay @@ -22,10 +22,10 @@ params ["", "", "", "_startTime", "_smokeDelay"]; [{ - params ["_box", "_killer", "_instigator"]; + params ["_box", "_source", "_instigator"]; - // Make sure effects are cleaned up if box is deleted - [QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent; + // If box was deleted before smoke could be spawned, just exit + if (isNull _box) exitWith {}; private _boxPos = ASLToAGL getPosASL _box; private _effects = []; @@ -46,8 +46,8 @@ params ["", "", "", "_startTime", "_smokeDelay"]; _effects pushBack _sound; // Detonate the ammunition - [QGVAR(detonateAmmunition), [_box, true, _killer, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent; + [QGVAR(detonateAmmunition), [_box, true, _source, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent; }; - _box setVariable [QGVAR(effects), _effects]; + _box setVariable [QGVAR(boxEffects), _effects]; }, _this, (_startTime - CBA_missionTime + _smokeDelay) max 0] call CBA_fnc_waitAndExecute; // this delay allows for synchronisation for JIP players diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index b428183cb3..6ef74e277f 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -6,7 +6,7 @@ * Arguments: * 0: Object * 1: Destroy when finished (default: false) - * 2: Killer (default: objNull) + * 2: Source (default: objNull) * 3: Instigator (default: objNull) * 4: Initial delay (default: 0) * @@ -21,7 +21,7 @@ if (!isServer) exitWith {}; -params ["_object", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]]; +params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_instigator", objNull], ["_initialDelay", 0]]; if (isNull _object) exitWith {}; @@ -47,12 +47,12 @@ _objectAmmo params ["_magazines", "_totalAmmo"]; // If the cook-off has finished, clean up the effects and destroy the object if (_magazines isEqualTo [] || {_totalAmmo <= 0}) exitWith { - [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; + [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; _object setVariable [QGVAR(cookoffMagazines), nil]; if (_destroyWhenFinished) then { - _object setDamage [1, true, _killer, _instigator]; + _object setDamage [1, true, _source, _instigator]; }; }; @@ -66,14 +66,14 @@ if (underwater _object || { !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) }) exitWith { - [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; + [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; _object setVariable [QGVAR(cookoffMagazines), nil]; }; // Initial delay allows for a delay for the first time this function runs in its cycle if (_initialDelay > 0) exitWith { - [FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; + [FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; }; private _magazineIndex = floor random (count _magazines); @@ -101,7 +101,7 @@ _totalAmmo = _totalAmmo - _removed; _object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]]; // Detonate the remaining ammo after a delay -[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; +[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; // Get magazine info, which is used to spawn projectiles private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 2f76ef9c77..b7ac629613 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -15,46 +15,32 @@ * Public: No */ -params ["_box", "", "_damage", "_source", "_ammo", "_hitIndex", "_instigator"]; +params ["_box", "", "_damage", "_source", "_ammo", "", "_instigator", "_hitPoint"]; if (!local _box) exitWith {}; // If it's already dead, ignore -if (damage _box >= 1) exitWith {}; +if (!alive _box) exitWith {}; // If cookoff for boxes is disabled, exit if (!GVAR(enableAmmobox) || {GVAR(ammoCookoffDuration) == 0}) exitWith {}; if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {}; -// Get hitpoint name -private _hitpoint = "#structural"; - -if (_hitIndex != -1) then { - _hitpoint = ((getAllHitPointsDamage _box) param [0, []]) select _hitIndex; -}; - -if !(_hitpoint == "#structural" && {_damage > 0.5}) exitWith {}; +if !(_hitPoint == "" && {_damage > 0.5}) exitWith {}; // "" means structural damage // Catch fire when hit by an explosive round if (IS_EXPLOSIVE_AMMO(_ammo)) then { [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; } else { - // Get change in damage - private _oldDamage = if (_hitpoint == "#structural") then { - damage _box - } else { - _box getHitIndex _hitIndex - }; - // There is a small chance of cooking a box off if it's shot by tracer ammo - if !(random 1 < _oldDamage * 0.05) exitWith {}; + if (random 1 >= _damage * 0.05) exitWith {}; // Need magazine to check for tracers private _magazine = if (_source == _instigator) then { currentMagazine _source } else { - _source currentMagazineTurret (_box unitTurret _instigator) + _source currentMagazineTurret (_source unitTurret _instigator) }; private _configMagazine = configFile >> "CfgMagazines" >> _magazine; diff --git a/addons/cookoff/functions/fnc_smoke.sqf b/addons/cookoff/functions/fnc_smoke.sqf index 6ff2726fa1..f060a98f61 100644 --- a/addons/cookoff/functions/fnc_smoke.sqf +++ b/addons/cookoff/functions/fnc_smoke.sqf @@ -5,7 +5,7 @@ * * Arguments: * 0: Vehicle - * 1: Selections for smoke to come out of (default: []) + * 1: Selections for smoke to come out of * * Return Value: * None @@ -16,10 +16,7 @@ * Public: No */ -params ["_vehicle", ["_positions", []]]; - -// Make sure effects are cleaned up if vehicle is deleted -[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent; +params ["_vehicle", "_positions"]; private _positionBarrelEnd = getText ([_vehicle, [0]] call CBA_fnc_getTurret >> "gunBeg"); @@ -44,4 +41,4 @@ private _effects = [_smokeBarrel]; _effects pushBack _smoke; } forEach _positions; -_vehicle setVariable [QGVAR(effects), _effects]; +_vehicle setVariable [QGVAR(vehicleEffects), _effects]; diff --git a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf index 5ff4d0e8f2..e1f0e7799d 100644 --- a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf +++ b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf @@ -47,7 +47,7 @@ if (_chanceOfFire >= random 1) exitWith { _source = ["hit_engine_point", "HitPoints"]; }; - [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, _canJet]] call CBA_fnc_serverEvent; + [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, _canJet]] call CBA_fnc_serverEvent; LOG_4("Cooking-off [%1] with a chance-of-fire [%2] - Delayed Smoke | Detonate after cookoff [%3 | %4]",_vehicle,_chanceOfFire,_delayWithSmoke,_detonateAfterCookoff); [_vehicle] spawn FUNC(abandon); LOG_1("[%1] is on fire is bailing",_vehicle);