From 4f33c32ba9aafe60d35a099e0d0b42cc0eee3bab Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 27 Jan 2024 09:14:10 +0100 Subject: [PATCH 01/27] Cook-off improvements --- addons/cookoff/ACE_Settings.hpp | 3 +- addons/cookoff/CfgCloudlets.hpp | 1 - addons/cookoff/CfgEden.hpp | 11 +- addons/cookoff/CfgEventHandlers.hpp | 1 - addons/cookoff/CfgSFX.hpp | 1 - addons/cookoff/CfgVehicles.hpp | 29 +-- addons/cookoff/XEH_PREP.hpp | 11 +- addons/cookoff/XEH_postInit.sqf | 105 ++++++---- addons/cookoff/functions/fnc_cookOff.sqf | 148 ++++++++------ addons/cookoff/functions/fnc_cookOffBox.sqf | 70 ++----- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 83 ++++++++ .../cookoff/functions/fnc_cookOffEffect.sqf | 169 +++++++++------- .../functions/fnc_detonateAmmunition.sqf | 189 +++++++++++------- addons/cookoff/functions/fnc_engineFire.sqf | 40 +--- .../cookoff/functions/fnc_engineFireLocal.sqf | 61 ++++++ .../cookoff/functions/fnc_getVehicleAmmo.sqf | 52 +++-- .../cookoff/functions/fnc_handleDamageBox.sqf | 84 ++++---- .../cookoff/functions/fnc_isMagazineFlare.sqf | 10 +- addons/cookoff/functions/fnc_smoke.sqf | 12 +- addons/cookoff/initSettings.inc.sqf | 82 ++++---- addons/cookoff/script_component.hpp | 1 + addons/cookoff/stringtable.xml | 154 ++------------ addons/grenades/functions/fnc_incendiary.sqf | 15 +- .../functions/fnc_addDamage.sqf | 4 +- .../vehicle_damage/functions/fnc_detonate.sqf | 2 +- .../functions/fnc_handleCookoff.sqf | 7 +- docs/wiki/framework/cookoff-framework.md | 37 +--- docs/wiki/framework/events-framework.md | 7 +- .../wiki/framework/vehicledamage-framework.md | 2 +- 29 files changed, 723 insertions(+), 668 deletions(-) create mode 100644 addons/cookoff/functions/fnc_cookOffBoxLocal.sqf create mode 100644 addons/cookoff/functions/fnc_engineFireLocal.sqf diff --git a/addons/cookoff/ACE_Settings.hpp b/addons/cookoff/ACE_Settings.hpp index ba4447dba99..f60a5276db4 100644 --- a/addons/cookoff/ACE_Settings.hpp +++ b/addons/cookoff/ACE_Settings.hpp @@ -1,4 +1,3 @@ - class ACE_Settings { class GVAR(enable) { movedToSqf = 1; @@ -6,7 +5,7 @@ class ACE_Settings { class GVAR(enableAmmobox) { movedToSQF = 1; }; - class GVAR(enableAmmoCookoff) { // For CBA Setting Switch: we can eliminate and just use (ammoCookoffDuration == 0) + class GVAR(enableAmmoCookoff) { movedToSQF = 1; }; class GVAR(ammoCookoffDuration) { diff --git a/addons/cookoff/CfgCloudlets.hpp b/addons/cookoff/CfgCloudlets.hpp index c1671777054..a328451a7b8 100644 --- a/addons/cookoff/CfgCloudlets.hpp +++ b/addons/cookoff/CfgCloudlets.hpp @@ -1,4 +1,3 @@ - class CfgCloudlets { class GVAR(CookOff) { interval = 0.004; diff --git a/addons/cookoff/CfgEden.hpp b/addons/cookoff/CfgEden.hpp index 2b58daa3043..12117cae3b0 100644 --- a/addons/cookoff/CfgEden.hpp +++ b/addons/cookoff/CfgEden.hpp @@ -1,4 +1,3 @@ - class Cfg3DEN { class Object { class AttributeCategories { @@ -7,9 +6,9 @@ class Cfg3DEN { class GVAR(enable) { property = QGVAR(enable); control = "Checkbox"; - displayName = CSTRING(enable_hd_name); - tooltip = CSTRING(enable_hd_tooltip); - expression = QUOTE(if !(_value) then {_this setVariable [ARR_3('%s',_value,true)];};); + displayName = CSTRING(enable_name); + tooltip = CSTRING(enable_tooltip); + expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]}); typeName = "BOOL"; condition = "objectVehicle"; defaultValue = QUOTE((GETMVAR(QGVAR(enable),0)) in [ARR_2(1,2)]); @@ -19,10 +18,10 @@ class Cfg3DEN { control = "Checkbox"; displayName = CSTRING(enableAmmoCookoff_name); tooltip = CSTRING(enableAmmoCookoff_tooltip); - expression = QUOTE(if !(_value) then {_this setVariable [ARR_3('%s',_value,true)];};); + expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]}); typeName = "BOOL"; condition = "objectHasInventoryCargo"; - defaultValue = QUOTE(if (_this isKindOf 'ReammoBox_F') then { GETMVAR(QGVAR(enableAmmobox),true) } else { GETMVAR(QGVAR(enableAmmoCookoff),true) };); + defaultValue = QUOTE(if (_this isKindOf 'ReammoBox_F') then {GETMVAR(QGVAR(enableAmmobox),true)} else {GETMVAR(QGVAR(enableAmmoCookoff),true)}); }; }; }; diff --git a/addons/cookoff/CfgEventHandlers.hpp b/addons/cookoff/CfgEventHandlers.hpp index 6c29240403a..f6503c2479b 100644 --- a/addons/cookoff/CfgEventHandlers.hpp +++ b/addons/cookoff/CfgEventHandlers.hpp @@ -1,4 +1,3 @@ - class Extended_PreStart_EventHandlers { class ADDON { init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); diff --git a/addons/cookoff/CfgSFX.hpp b/addons/cookoff/CfgSFX.hpp index 0d670ead863..24329862fc7 100644 --- a/addons/cookoff/CfgSFX.hpp +++ b/addons/cookoff/CfgSFX.hpp @@ -1,4 +1,3 @@ - class CfgSFX { class GVAR(CookOff_low) { name = QGVAR(cookoff_low); diff --git a/addons/cookoff/CfgVehicles.hpp b/addons/cookoff/CfgVehicles.hpp index 78cbd0c6234..86e0df83868 100644 --- a/addons/cookoff/CfgVehicles.hpp +++ b/addons/cookoff/CfgVehicles.hpp @@ -1,4 +1,3 @@ - class CfgVehicles { class Sound; class GVAR(Sound_low): Sound { @@ -7,7 +6,6 @@ class CfgVehicles { scope = 1; sound = QGVAR(CookOff_low); }; - class GVAR(Sound_mid): GVAR(Sound_low) { sound = QGVAR(CookOff_mid); }; @@ -17,47 +15,34 @@ class CfgVehicles { class Tank; class Tank_F: Tank { - GVAR(ammoLocation) = "HitHull"; GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"}; - GVAR(probability) = 0.5; - }; - class MBT_02_base_F: Tank_F { - GVAR(ammoLocation) = "HitTurret"; }; class Car_F; class Wheeled_APC_F: Car_F { - GVAR(ammoLocation) = "HitHull"; GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"}; - GVAR(probability) = 0.8; - // big explosions for wheeled APCs (same as for tanks) + // Big explosions for wheeled APCs (same as for tanks) explosionEffect = "FuelExplosionBig"; }; - - class MRAP_01_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0,-2,0}; + GVAR(engineSmokeOffset)[] = {0, -2, 0}; }; - class MRAP_02_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0,-2,0}; + GVAR(engineSmokeOffset)[] = {0, -2, 0}; }; - class MRAP_03_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0,-2,0}; + GVAR(engineSmokeOffset)[] = {0, -2, 0}; }; - class Quadbike_01_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0,1,0}; + GVAR(engineSmokeOffset)[] = {0, 1, 0}; }; class Truck_F; class Truck_02_base_F: Truck_F { - GVAR(engineSmokeOffset)[] = {0,-2.6,-0.1}; + GVAR(engineSmokeOffset)[] = {0, -2.6, -0.1}; }; - class Truck_02_MRL_base_F: Truck_02_base_F { - GVAR(engineSmokeOffset)[] = {0,0.3,-0.1}; + GVAR(engineSmokeOffset)[] = {0, 0.3, -0.1}; }; }; diff --git a/addons/cookoff/XEH_PREP.hpp b/addons/cookoff/XEH_PREP.hpp index 2cd87efaa7c..3dc602be705 100644 --- a/addons/cookoff/XEH_PREP.hpp +++ b/addons/cookoff/XEH_PREP.hpp @@ -1,10 +1,11 @@ - -PREP(handleDamageBox); -PREP(engineFire); PREP(cookOff); -PREP(smoke); -PREP(cookOffEffect); PREP(cookOffBox); +PREP(cookOffBoxLocal); +PREP(cookOffEffect); PREP(detonateAmmunition); +PREP(engineFire); +PREP(engineFireLocal); PREP(getVehicleAmmo); +PREP(handleDamageBox); PREP(isMagazineFlare); +PREP(smoke); diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index b9c81015950..400569afd67 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -1,60 +1,81 @@ #include "script_component.hpp" -[QGVAR(engineFire), FUNC(engineFire)] call CBA_fnc_addEventHandler; -[QGVAR(cookOff), { - params ["_vehicle"]; - if (local _vehicle) then { - _this call FUNC(cookOff); - }; -}] call CBA_fnc_addEventHandler; -[QGVAR(cookOffEffect), FUNC(cookOffEffect)] call CBA_fnc_addEventHandler; -[QGVAR(smoke), FUNC(smoke)] call CBA_fnc_addEventHandler; -[QGVAR(cookOffBox), FUNC(cookOffBox)] call CBA_fnc_addEventHandler; +[QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler; +[QGVAR(cookOffBoxLocal), LINKFUNC(cookOffBoxLocal)] call CBA_fnc_addEventHandler; +[QGVAR(cookOffEffect), LINKFUNC(cookOffEffect)] call CBA_fnc_addEventHandler; +[QGVAR(engineFireLocal), LINKFUNC(engineFireLocal)] call CBA_fnc_addEventHandler; +[QGVAR(smoke), LINKFUNC(smoke)] call CBA_fnc_addEventHandler; + +if (isServer) then { + [QGVAR(cookOffBox), LINKFUNC(cookOffBox)] call CBA_fnc_addEventHandler; + [QGVAR(engineFire), LINKFUNC(engineFire)] call CBA_fnc_addEventHandler; + [QGVAR(detonateAmmunition), LINKFUNC(detonateAmmunition)] call CBA_fnc_addEventHandler; +}; -// handle cleaning up effects when vehicle is deleted mid-cookoff +// Handle cleaning up effects when vehicle is deleted mid cook-off [QGVAR(addCleanupHandlers), { - params ["_vehicle"]; - - // Don't add a new EH if cookoff is run multiple times - if ((_vehicle getVariable [QGVAR(deletedEH), -1]) == -1) then { - private _deletedEH = _vehicle addEventHandler ["Deleted", { - params ["_vehicle"]; - - [QGVAR(cleanupEffects), [_vehicle]] call CBA_fnc_localEvent; - }]; - - _vehicle setVariable [QGVAR(deletedEH), _deletedEH]; - }; + // No effects on machines without interfaces + if (!hasInterface) exitWith {}; + + 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 ["_vehicle", ["_effects", []]]; + params ["_object", ["_effects", []]]; + + if (isServer) then { + // Reset, so that object can cook-off again + _object setVariable [QGVAR(isCookingOff), nil, true]; + + // Remove effects from JIP + private _jipID = _object getVariable QGVAR(jipID); - _effects = _effects + (_vehicle getVariable [QGVAR(effects), []]); - if (_effects isNotEqualTo []) then { - { deleteVehicle _x } count _effects; + if (isNil "_jipID") exitWith {}; + + _jipID call CBA_fnc_removeGlobalEventJIP; + + _object setVariable [QGVAR(jipID), nil]; }; + + // No effects on machines without interfaces + if (!hasInterface) exitWith {}; + + // All effects are local + _effects append (_object getVariable [QGVAR(effects), []]); + + if (_effects isEqualTo []) exitWith {}; + + { + deleteVehicle _x; + } forEach _effects; + + _object setVariable [QGVAR(effects), nil]; }] call CBA_fnc_addEventHandler; ["ReammoBox_F", "init", { - (_this select 0) addEventHandler ["HandleDamage", { - if ((_this select 0) getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmobox)]) then { - _this call FUNC(handleDamageBox); - }; - }]; + // Calling this function inside curly brackets allows the usage of "exitWith", which would be broken with "HandleDamage" otherwise + (_this select 0) addEventHandler ["HandleDamage", {_this call FUNC(handleDamageBox)}]; }, nil, nil, true] call CBA_fnc_addClassEventHandler; -// secondary explosions -["AllVehicles", "killed", { +// Secondary explosions +["AllVehicles", "Killed", { + if (!GVAR(enableAmmoCookoff) || {GVAR(ammoCookoffDuration) == 0}) exitWith {}; + params ["_vehicle", "", "", "_useEffects"]; - if ( - _useEffects && - _vehicle getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmoCookoff)] - ) then { - if (GVAR(ammoCookoffDuration) == 0) exitWith {}; - ([_vehicle] call FUNC(getVehicleAmmo)) params ["_mags", "_total"]; + + if (_useEffects && {_vehicle getVariable [QGVAR(enableAmmoCookoff), true]}) then { + (_vehicle call FUNC(getVehicleAmmo)) params ["_magazines", "_total"]; private _delay = (random MAX_AMMO_DETONATION_START_DELAY) max MIN_AMMO_DETONATION_START_DELAY; - [FUNC(detonateAmmunition), [_vehicle, _mags, _total], _delay] call CBA_fnc_waitAndExecute; + [QGVAR(detonateAmmunition), [_vehicle, _magazines, _total, false, objNull, objNull, _delay]] call CBA_fnc_serverEvent; }; -}, nil, ["Man","StaticWeapon"]] call CBA_fnc_addClassEventHandler; +}, nil, ["CAManBase", "StaticWeapon"]] call CBA_fnc_addClassEventHandler; diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 1d598cdb960..048b82beb2a 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -2,49 +2,70 @@ /* * Author: tcvm * Start a cook-off in the given vehicle. + * Spews flames in multiple directions at the same time (ring) or from the turret towards the sky (jet). * * Arguments: - * 0: Vehicle - * 1: Intensity of fire + * 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: Maximum intensity (default: MAX_COOKOFF_INTENSITY) + * 9: Can spawn fire jet (default: true) * * Return Value: * None * * Example: - * [(vehicle player), 3] call ace_cookoff_fnc_cookOff + * [vehicle player, 3] call ace_cookoff_fnc_cookOff * * Public: No */ -params ["_vehicle", "_intensity", ["_instigator", objNull], ["_smokeDelayEnabled", true], ["_ammoDetonationChance", 0], ["_detonateAfterCookoff", false], ["_fireSource", ""], ["_canRing", true], ["_maxIntensity", MAX_COOKOFF_INTENSITY, [0]], ["_canJet", true, [true]]]; +if (!isServer) exitWith {}; +if (GVAR(enable) == 0 || {GVAR(cookoffDuration) == 0}) exitWith {}; -if (GVAR(enable) == 0) exitWith {}; -if !(GVAR(enableFire)) exitWith {}; -if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] in [0, false]) exitWith {}; -// exit if cook-off enabled only for players and no players in vehicle crew found -if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] isEqualTo 1 && {fullCrew [_vehicle, "", false] findIf {isPlayer (_x select 0)} == -1}) exitWith {}; +params [ + "_vehicle", + "_intensity", + ["_instigator", objNull], + ["_delayBetweenSmokeAndFire", true], + ["_ammoDetonationChance", 0], + ["_detonateAfterCookoff", false], + ["_fireSource", ""], + ["_canRing", true], + ["_maxIntensity", MAX_COOKOFF_INTENSITY, [0]], + ["_canJet", true, [true]] +]; +// Check if cook-off is disabled on vehicle specifically +if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; + +// Exit if cook-off enabled only for players and no players in vehicle crew found +if ((GVAR(enable) isEqualTo 1) && {(crew _vehicle) findIf {isPlayer _x} == -1}) exitWith {}; TRACE_2("cooking off",_vehicle,_intensity); -TRACE_8("",_instigator,_smokeDelayEnabled,_ammoDetonationChance,_detonateAfterCookoff,_fireSource,_canRing,_maxIntensity,_canJet); +TRACE_8("",_instigator,_delayBetweenSmokeAndFire,_ammoDetonationChance,_detonateAfterCookoff,_fireSource,_canRing,_maxIntensity,_canJet); if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {}; -_vehicle setVariable [QGVAR(isCookingOff), true, true]; -[QGVAR(addCleanupHandlers), [_vehicle]] call CBA_fnc_globalEvent; +_vehicle setVariable [QGVAR(isCookingOff), true, true]; -// limit maximum value of intensity to prevent very long cook-off times +// Limit maximum value of intensity to prevent very long cook-off times _intensity = _intensity min _maxIntensity; -private _config = _vehicle call CBA_fnc_getObjectConfig; -private _positions = getArray (_config >> QGVAR(cookoffSelections)) select {(_vehicle selectionPosition _x) isNotEqualTo [0,0,0]}; +private _positions = getArray (configOf _vehicle >> QGVAR(cookoffSelections)) select {(_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]}; if (_positions isEqualTo []) then { WARNING_1("no valid selection for cookoff found. %1",typeOf _vehicle); + { - private _pos = _vehicle selectionPosition _x; - if (_pos isEqualTo [0, 0, 0]) exitWith {}; - _positions pushBack _x; + if ((_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]) then { + _positions pushBack _x; + }; } forEach DEFAULT_COMMANDER_HATCHES; if (_positions isEqualTo []) then { @@ -52,45 +73,49 @@ if (_positions isEqualTo []) then { }; }; +// Spawn smoke +private _jipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP; +_vehicle setVariable [QGVAR(jipID), _jipID]; + +// Save intensity for looping purposes +_vehicle setVariable [QGVAR(intensity), _intensity]; + private _delay = 0; -if (_smokeDelayEnabled) then { + +if (_delayBetweenSmokeAndFire) then { _delay = SMOKE_TIME + random SMOKE_TIME; }; -[QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEvent; [{ - params ["_vehicle", "_positions", "_intensity", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"]; - _vehicle setVariable [QGVAR(intensity), _intensity]; - private _smokeEffects = _vehicle getVariable [QGVAR(effects), []]; - [{ - params ["_args", "_pfh"]; - _args params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_smokeEffects"]; + (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"]; + private _intensity = _vehicle getVariable [QGVAR(intensity), 0]; - if (isNull _vehicle || {_intensity <= 1}) exitWith { - [QGVAR(cleanupEffects), [_vehicle, _smokeEffects]] call CBA_fnc_globalEvent; - _vehicle setVariable [QGVAR(isCookingOff), false, true]; - [_pfh] call CBA_fnc_removePerFrameHandler; + + if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + + // Effects are deleted when vehicle is deleted + if (isNull _vehicle) exitWith {}; + + // Remove effects globally + [QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent; if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then { - _vehicle setDamage [1, true]; + _vehicle setDamage [1, true, _instigator, _instigator]; // because it's running on the server, killer and instigator can be set }; }; - private _lastFlameTime = _vehicle getVariable [QGVAR(lastFlame), 0]; - private _nextFlameTime = _vehicle getVariable [QGVAR(nextFlame), 0]; - // Wait until we are ready for the next flame - // dt = Tcurrent - Tlast - // dt >= Tnext - if ((CBA_missionTime - _lastFlameTime) >= _nextFlameTime) then { - private _ring = (0.2 > random 1); - if (!_ring && _intensity >= 2) then { - _ring = (0.7 > random 1); - }; + if (CBA_missionTime >= _vehicle getVariable [QGVAR(nextFlame), 0]) then { + private _ring = false; - if !(_canRing) then { - _ring = false; + if (_canRing) then { + _ring = 0.2 > random 1; + + if (!_ring && {_intensity >= 2}) then { + _ring = 0.7 > random 1; + }; }; private _time = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME; @@ -99,31 +124,30 @@ if (_smokeDelayEnabled) then { _fireSource = selectRandom _positions; }; + // As the cook-off effect is max 20s, this is not synced with JIP players [QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _time, _fireSource, _intensity]] call CBA_fnc_globalEvent; - _intensity = _intensity - (0.5 max random 1); + _intensity = _intensity - (0.5 max random 1) / GVAR(cookoffDuration); + _vehicle setVariable [QGVAR(intensity), _intensity]; - _vehicle setVariable [QGVAR(lastFlame), CBA_missionTime]; - _vehicle setVariable [QGVAR(nextFlame), _time + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)]; + _vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _time + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)]; - { - [QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator]] call CBA_fnc_globalEvent; - } forEach crew _vehicle + // If there are any crew, burn them + if (["ace_fire"] call EFUNC(common,isModLoaded)) then { + { + [QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator]] call CBA_fnc_globalEvent; + } forEach (crew _vehicle); + }; }; - if (_ammoDetonationChance > random 1) then { - private _lastExplosiveDetonationTime = _vehicle getVariable [QGVAR(lastExplosiveDetonation), 0]; - private _nextExplosiveDetonation = _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]; + if (_ammoDetonationChance > random 1 && {CBA_missionTime >= _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]}) then { + if (_fireSource isEqualTo "") then { + _fireSource = selectRandom _positions; + }; - if ((CBA_missionTime - _lastExplosiveDetonationTime) > _nextExplosiveDetonation) then { - if (_fireSource isEqualTo "") then { - _fireSource = selectRandom _positions; - }; - createVehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld (_vehicle selectionPosition _fireSource)), [], 0 , "CAN_COLLIDE"]; + createVehicle ["ACE_ammoExplosionLarge", _vehicle modelToWorld (_vehicle selectionPosition _fireSource), [], 0 , "CAN_COLLIDE"]; - _vehicle setVariable [QGVAR(lastExplosiveDetonation), CBA_missionTime]; - _vehicle setVariable [QGVAR(nextExplosiveDetonation), random 60]; - }; + _vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60]; }; - }, 0.25, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _smokeEffects]] call CBA_fnc_addPerFrameHandler -}, [_vehicle, _positions, _intensity, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute; + }, 0.25, _this] call CBA_fnc_addPerFrameHandler; +}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index 8b8e60891cf..0a1d92944f5 100644 --- a/addons/cookoff/functions/fnc_cookOffBox.sqf +++ b/addons/cookoff/functions/fnc_cookOffBox.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: KoffeinFlummi, commy2, kymckay + * Author: KoffeinFlummi, commy2, kymckay, johnb43 * Start a cook-off in the given ammo box. * * Arguments: @@ -10,65 +10,29 @@ * None * * Example: - * [_box] call ace_cookoff_fnc_cookOffBox + * cursorObject call ace_cookoff_fnc_cookOffBox * * Public: No */ -params ["_box"]; +if (!isServer) exitWith {}; -if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; -_box setVariable [QGVAR(isCookingOff), true]; - -if (local _box) then { - [QGVAR(cookOffBox), _box] call CBA_fnc_globalEvent; -}; - -[{ - params ["_box"]; - - // Box will start smoking - private _smoke = "#particlesource" createVehicleLocal [0,0,0]; - _smoke setParticleClass "AmmoSmokeParticles2"; - _smoke attachTo [_box, [0,0,0]]; - - private _effects = [_smoke]; +params ["_box", "_killer", "_instigator"]; - if (isServer) then { - private _sound = createSoundSource ["Sound_Fire", position _box, [], 0]; - _effects pushBack _sound; - }; - - [{ - params ["_box", "_effects"]; - - // These functions are smart and do all the cooking off work - if (local _box) then { - if (GVAR(ammoCookoffDuration) == 0) exitWith {}; - ([_box] call FUNC(getVehicleAmmo)) params ["_mags", "_total"]; - [_box, _mags, _total] call FUNC(detonateAmmunition); - - // This shit is busy being on fire, magazines aren't accessible/usable - clearMagazineCargoGlobal _box; - }; - - // Light the fire (also handles lighting) - private _fire = "#particlesource" createVehicleLocal [0,0,0]; - _fire setParticleClass "AmmoBulletCore"; - _fire attachTo [_box, [0,0,0]]; +if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; - _effects pushBack _fire; +_box setVariable [QGVAR(isCookingOff), true, true]; - [{ - params ["_box", "_effects"]; +// Spawn cook-off effects on all connected machines +private _jipID = [QGVAR(cookOffBoxLocal), [ + _box, + _killer, + _instigator, + CBA_missionTime, + random [IGNITE_TIME / 2, IGNITE_TIME, IGNITE_TIME / 2 * 3], // generate random timers that are global + random [SMOKE_TIME / 2, SMOKE_TIME, SMOKE_TIME / 2 * 3] +]] call CBA_fnc_globalEventJIP; - { - deleteVehicle _x; - } forEach _effects; +[_jipID, _box] call CBA_fnc_removeGlobalEventJIP; - if (local _box) then { - _box setDamage 1; - }; - }, [_box, _effects], COOKOFF_TIME_BOX] call CBA_fnc_waitAndExecute; // TODO: Change so that box is alive until no ammo left, with locality in mind - }, [_box, _effects], SMOKE_TIME] call CBA_fnc_waitAndExecute; -}, _box, IGNITE_TIME] call CBA_fnc_waitAndExecute; +_box setVariable [QGVAR(jipID), _jipID]; diff --git a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf new file mode 100644 index 00000000000..2e0dd031a1d --- /dev/null +++ b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf @@ -0,0 +1,83 @@ +#include "..\script_component.hpp" +/* + * Author: KoffeinFlummi, commy2, kymckay, johnb43 + * Start a cook-off in the given ammo box. + * + * Arguments: + * 0: Ammo box + * + * Return Value: + * None + * + * Example: + * cursorObject call ace_cookoff_fnc_cookOffBox + * + * Public: No + */ + +params ["_box", "_killer", "_instigator", "_startTime", "_igniteTime", "_smokeTime"]; + +// Make sure effects are cleaned up if box is deleted +[QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent; + +// These time checks are for JIP players +private _delay = _startTime - CBA_missionTime + _igniteTime; + +if (_delay >= 0) then { + [{ + params ["_box"]; + + private _effects = []; + + // Box will start smoking + if (hasInterface) then { + private _smoke = "#particlesource" createVehicleLocal [0, 0, 0]; + _smoke setParticleClass "AmmoSmokeParticles2"; + _smoke attachTo [_box, [0, 0, 0]]; + + _effects pushBack _smoke; + }; + + if (isServer) then { + private _sound = createSoundSource ["Sound_Fire", ASLToAGL getPosASL _box, [], 0]; + _smoke attachTo [_sound]; + + _effects pushBack _sound; + }; + + _box setVariable [QGVAR(effects), _effects]; + }, _box, _delay] call CBA_fnc_waitAndExecute; +}; + +// Smoke happens later +_delay = _delay + _smokeTime; + +if (_delay >= 0) then { + // Light the fire (also handles lighting) + [{ + params ["_box", "_killer", "_instigator"]; + + if (hasInterface) then { + private _fire = "#particlesource" createVehicleLocal [0, 0, 0]; + + _fire setParticleClass "AmmoBulletCore"; + _fire attachTo [_box, [0, 0, 0]]; + + private _effects = _box getVariable [QGVAR(effects), []]; + + _effects pushBack _fire; + + _box setVariable [QGVAR(effects), _effects]; + }; + + // These functions are smart and do all the cooking off work + if (isServer) then { + (_box call FUNC(getVehicleAmmo)) params ["_magazines", "_total"]; + + [QGVAR(detonateAmmunition), [_box, _magazines, _total, true, _killer, _instigator]] call CBA_fnc_localEvent; + + // This shit is busy being on fire, magazines aren't accessible/usable + clearMagazineCargoGlobal _box; + }; + }, _this, _delay] call CBA_fnc_waitAndExecute; +}; diff --git a/addons/cookoff/functions/fnc_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index a907f676061..1cf1e3f8538 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -1,15 +1,15 @@ #include "..\script_component.hpp" /* * Author: tcvm - * Spawn cook-off effects + * Spawn cook-off effects. * * Arguments: - * 0: Vehicle - * 1: Spawn fire jet - * 2: Spawn fire ring - * 3: How long effect will last (Max 20 seconds) - * 4: What selection will fire originate from - * 5: Cookoff intensity value + * 0: Vehicle + * 1: Spawn fire jet + * 2: Spawn fire ring + * 3: Duration of effect (max 20 seconds) + * 4: What selection will fire originate from + * 5: Cookoff intensity value * * Return Value: * None @@ -20,60 +20,89 @@ * Public: No */ -params ["_obj", "_jet", "_ring", "_time", "_fireSelection", "_intensity"]; -private _light = "#lightpoint" createVehicleLocal [0,0,0]; -_light setLightBrightness 5; -_light setLightAmbient [0.8, 0.6, 0.2]; -_light setLightColor [1, 0.5, 0.2]; -_light lightAttachObject [_obj, [0,0,0]]; -_time = 0 max (_time min 20); +#define FLAME_SIZE 1.5 +#define FIRE_INTENSITY 6 + +params ["_vehicle", "_jet", "_ring", "_duration", "_fireSelection", "_intensity"]; + +// Spawn light +private _light = objNull; + +if (hasInterface) then { + _light = "#lightpoint" createVehicleLocal [0, 0, 0]; + _light setLightBrightness 5; + _light setLightAmbient [0.8, 0.6, 0.2]; + _light setLightColor [1, 0.5, 0.2]; + _light lightAttachObject [_vehicle, [0, 0, 0]]; +}; + +_duration = 0 max _duration min 20; private _sound = objNull; +private _fireKey = ""; + if (isServer) then { - // ironically biggest performance hit is this. Creating a new sound source takes up aprox 400 milliseconds. - // I dont think there is an alternative that takes into effect distance and whatever, but if you find one please fix! + // Spawn sound effect if (_jet || _ring) then { private _soundName = selectRandomWeighted [QGVAR(Sound_low), 0.1, QGVAR(Sound_mid), 0.25, QGVAR(Sound_high), 0.65]; - _sound = createSoundSource [_soundName, position _obj, [], 0]; + _sound = createSoundSource [_soundName, ASLToAGL getPosASL _vehicle, [], 0]; + _sound attachTo [_vehicle]; }; - if (_ring) then { - private _intensity = 6; - private _radius = 1.5 * ((boundingBoxReal _obj) select 2); - [QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, _obj]] call CBA_fnc_localEvent; + // Make the ring a source of fire + if (_ring && {["ace_fire"] call EFUNC(common,isModLoaded)}) then { + _fireKey = format [QGVAR(%1), hashValue _vehicle]; + + [QEGVAR(fire,addFireSource), [_vehicle, FLAME_SIZE * ((boundingBoxReal _vehicle) select 2), FIRE_INTENSITY, _fireKey]] call CBA_fnc_localEvent; }; }; [{ - params ["_args", "_pfh"]; - _args params ["_obj", "_jet", "_ring", "_time", "_startTime", "_light", "_fireSelection", "_sound", "_intensity"]; + (_this select 0) params ["_vehicle", "_jet", "_ring", "_duration", "_startTime", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"]; + private _elapsedTime = CBA_missionTime - _startTime; - if (_elapsedTime >= _time) exitWith { + + // Clean up effects once effects have finished or vehicle has been deleted + if (isNull _vehicle || {_elapsedTime >= _duration}) exitWith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + deleteVehicle _light; - deleteVehicle _sound; + if (isServer) then { - [QEGVAR(fire,removeFireSource), [_obj]] call CBA_fnc_localEvent; + deleteVehicle _sound; + + if (["ace_fire"] call EFUNC(common,isModLoaded)) then { + [QEGVAR(fire,removeFireSource), _fireKey] call CBA_fnc_localEvent; + }; }; - [_pfh] call CBA_fnc_removePerFrameHandler; }; - private _factor = (1 + (_elapsedTime / 2) min 2); - private _flameSize = 1.5; - if (_elapsedTime > (_time * (3 / 4))) then { - _factor = _factor * linearConversion [_time * (3 / 4), _time, _elapsedTime, 1, 0.5]; + private _factor = 1 + (_elapsedTime / 2) min 2; + + if (_elapsedTime > _duration * 3 / 4) then { + _factor = _factor * linearConversion [_duration * 3 / 4, _duration, _elapsedTime, 1, 0.5]; }; - _light setLightBrightness 5 * (_factor / 5); + // Make flame push object into ground to make effect seem more "alive" + if (_jet && !isGamePaused && {local _vehicle}) then { + private _force = [0, 0, _factor * -(0.5 min random 1.5) * (0.3 min random 1)] vectorMultiply getMass _vehicle; + _vehicle addForce [_force, vectorUpVisual _vehicle]; + }; + + // Don't spawn visual effects on machines without interfaces + if (!hasInterface) exitWith {}; + + _light setLightBrightness _factor; if (_jet) then { - private _particlePosition = (_obj selectionPosition _fireSelection) vectorAdd [-0.1 + random 0.2, -0.1 + random 0.2, 0]; + private _particlePosition = (_vehicle selectionPosition _fireSelection) vectorAdd [-0.1 + random 0.2, -0.1 + random 0.2, 0]; drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], "", "Billboard", 1, - (0.1 + (random 0.2)) * _factor, + (0.1 + random 0.2) * _factor, _particlePosition, [0, 0, 15 * (_factor / 2)], 0, @@ -87,69 +116,64 @@ if (isServer) then { 0, "", "", - _obj + _vehicle ]; - - // make flame push object into ground to make effect seem more "alive" - if (!isGamePaused && { local _obj }) then { - private _force = [0, 0, _factor * -(0.5 min random 1.5) * (0.3 min random 1)] vectorMultiply getMass _obj; - _obj addForce [_force, vectorUpVisual _obj]; - }; }; if (_ring) then { - private _ringOrigin = (_obj selectionPosition _fireSelection) vectorAdd [-0.1 + random 0.2, -0.1 + random 0.2, -1]; + private _ringOrigin = (_vehicle selectionPosition _fireSelection) vectorAdd [-0.1 + random 0.2, -0.1 + random 0.2, -1]; + drop [ ["\A3\data_f\ParticleEffects\Universal\Universal",16,2,32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, _ringOrigin, [0, 20 * (_factor / 2), 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, _ringOrigin, [0, -20 * (_factor / 2), 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, _ringOrigin, [20 * (_factor / 2), 0, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, [-0.1 + random 0.2, -0.1 + random 0.2, -1], [-20 * (_factor / 2), 0, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; private _dir = 20 * (_factor / 2); drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, _ringOrigin, [_dir, _dir, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2],[1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; _dir = -20 * (_factor / 2); @@ -159,9 +183,9 @@ if (isServer) then { _ringOrigin, [_dir, _dir, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2],[1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; _dir = 20 * (_factor / 2); @@ -171,31 +195,30 @@ if (isServer) then { _ringOrigin, [_dir, -_dir, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; _dir = 20 * (_factor / 2); drop [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], - "", "Billboard", 1, (0.1 + (random 0.2)) * _factor, + "", "Billboard", 1, (0.1 + random 0.2) * _factor, _ringOrigin, [-_dir, _dir, 0], 0, 10, 7.9, 0.075, - [1.25 * _factor, _flameSize * _factor], + [1.25 * _factor, FLAME_SIZE * _factor], [[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]], - [2 + random 1], 1, 0, "", "", _obj + [2 + random 1], 1, 0, "", "", _vehicle ]; }; - (getVehicleTIPars _obj) params ["_tiEngine", "_tiWheels", "_tiWeapon"]; - _obj setVehicleTIPars [ - // formula is designed to have the temperature ramp up quickly and then level out - (_tiEngine + (_intensity * 0.01))/1.005, - (_tiWheels + (_intensity * 0.004))/1.002, // wheels//tracks are further away from burning parts - (_tiWeapon + (_intensity * 0.01))/1.005 - ]; - -}, 0, [_obj, _jet, _ring, _time, CBA_missionTime, _light, _fireSelection, _sound, _intensity]] call CBA_fnc_addPerFrameHandler; + (getVehicleTIPars _vehicle) params ["_tiEngine", "_tiWheels", "_tiWeapon"]; + // Formula is designed to have the temperature ramp up quickly and then level out + _vehicle setVehicleTIPars [ + (_tiEngine + _intensity * 0.01) / 1.005, + (_tiWheels + _intensity * 0.004) / 1.002, // wheels//tracks are further away from burning parts + (_tiWeapon + _intensity * 0.01) / 1.005 + ]; +}, 0, [_vehicle, _jet, _ring, _duration, CBA_missionTime, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index b4d48f3120d..145bb99987c 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -1,135 +1,174 @@ #include "..\script_component.hpp" /* * Author: Glowbal - * Detonates ammunition from a vehicle until no ammo left + * Detonates ammunition from an object (e.g. vehicle or crate) until no ammo is left. * * Arguments: - * 0: vehicle - * 1: Ammo Array - * - 0: Magazine Classname - * - 1: Ammo Count - * 2: Total Ammo Count + * 0: Object + * 1: Magazine array + * - 0: Magazine classname + * - 1: Ammo count + * 2: Total ammo count + * 3: Destroy when finished (default: false) + * 4: Killer (default: objNull) + * 5: Instigator (default: objNull) + * 6: Initial delay (default: 0) * * Return Value: - * None + * Nothing Useful * * Example: - * [_vehicle, magazinesAmmo _vehicle] call ace_cookoff_fnc_detonateAmmunition + * [cursorObject, magazinesAmmo vehicle player, 1000] call ace_cookoff_fnc_detonateAmmunition * * Public: No */ -params ["_vehicle", "_magazines", "_totalAmmo"]; +if (!isServer) exitWith {}; -if (GVAR(enable) == 0) exitWith {}; -if !(GVAR(enableAmmoCookoff)) exitWith {}; +params ["_object", "_magazines", "_totalAmmo", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]]; -if (isNull _vehicle) exitWith {}; // vehicle got deleted -if (_magazines isEqualTo []) exitWith {}; // nothing to detonate anymore -if (underwater _vehicle) exitWith {}; +if (isNull _object) exitWith {}; -private _magazineIndex = floor random(count _magazines); -private _magazine = _magazines select _magazineIndex; -_magazine params ["_magazineClassname", "_amountOfMagazines"]; +// 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; -if (_amountOfMagazines > 0) exitWith { - private _removed = _amountOfMagazines min floor(1 + random(6 / GVAR(ammoCookoffDuration))); + if (_destroyWhenFinished) then { + _object setDamage [1, true, _killer, _instigator]; + }; +}; - _amountOfMagazines = _amountOfMagazines - _removed; - if (_amountOfMagazines <= 0) then { - _magazines deleteAt _magazineIndex; - } else { - _magazine set [1, _amountOfMagazines]; // clear out the magazine +// If the cook-off is interrupted or disabled, clean up the effects +if (underwater _object || { + if (GVAR(ammoCookoffDuration) == 0) exitWith {true}; + + if (_object isKindOf "ReammoBox_F") exitWith { + !(GVAR(enableAmmobox) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) }; - private _timeBetweenAmmoDetonation = (((random 10) / (sqrt _totalAmmo)) min MAX_TIME_BETWEEN_AMMO_DET) max 0.1; - TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation); - _totalAmmo = _totalAmmo - _removed; - private _ammo = getText (configFile >> "CfgMagazines" >> _magazineClassname >> "ammo"); - private _ammoCfg = configFile >> "CfgAmmo" >> _ammo; + !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) +}) exitWith { + [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; +}; + +// Initial delay allows for a delay for the first time this function runs in its cycle +if (_initialDelay > 0) exitWith { + [FUNC(detonateAmmunition), [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; +}; - private _speedOfAmmo = getNumber (configFile >> "CfgMagazines" >> _magazineClassname >> "initSpeed"); - private _simType = getText (_ammoCfg >> "simulation"); +private _magazineIndex = floor random (count _magazines); +private _magazine = _magazines select _magazineIndex; +_magazine params ["_magazineClassname", "_ammoCount"]; - private _effect2pos = _vehicle selectionPosition "destructionEffect2"; +// Make sure ammo is at least 0 +_ammoCount = _ammoCount max 0; - private _spawnProjectile = { - params ["_vehicle", "_ammo", "_speed", "_flyAway"]; +// Remove some ammo, which will be detonated +private _removed = _ammoCount min floor (1 + random (6 / GVAR(ammoCookoffDuration))); - private _spawnPos = _vehicle modelToWorld [-0.2 + (random 0.4), -0.2 + (random 0.4), random 3]; - if (_spawnPos select 2 < 0) then { - _spawnPos set [2, 0]; - }; +_ammoCount = _ammoCount - _removed; - private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"]; - if (_flyAway) then { - private _vectorAmmo = [(-1 + (random 2)), (-1 + (random 2)), -0.2 + (random 1)]; - private _velVec = _vectorAmmo vectorMultiply _speed; - _projectile setVectorDir _velVec; - _projectile setVelocity _velVec; - } else { - _projectile setDamage 1; - }; +if (_ammoCount <= 0) then { + _magazines deleteAt _magazineIndex; +} else { + _magazine set [1, _ammoCount]; // 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; - _projectile; +// Detonate the remaining ammo after a delay +[FUNC(detonateAmmunition), [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; + +// Get magazine info, which is used to spawn projectiles +private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; +private _ammo = getText (_configMagazine >> "ammo"); +private _configAmmo = configFile >> "CfgAmmo" >> _ammo; + +private _simType = toLower getText (_configAmmo >> "simulation"); +private _speed = random (getNumber (_configMagazine >> "initSpeed") / 10) max 1; + +private _effect2pos = _object selectionPosition "destructionEffect2"; + +// Spawns the projectiles, making them either fly in random directions or explode +private _fnc_spawnProjectile = { + params ["_object", "_ammo", "_speed", "_flyAway"]; + + private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3]; + + if (_spawnPos select 2 < 0) then { + _spawnPos set [2, 0]; }; - private _speed = random (_speedOfAmmo / 10) max 1; + private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"]; - if (toLower _simType == "shotbullet") then { - private _sound = selectRandom [QUOTE(PATHTO_R(sounds\light_crack_close.wss)), QUOTE(PATHTO_R(sounds\light_crack_close_filtered.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close_filtered.wss))]; - playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1250]; + if (_flyAway) then { + private _vectorAmmo = [-1 + random 2, -1 + random 2, -0.2 + random 1]; + private _vectorVelocity = _vectorAmmo vectorMultiply _speed; + + _projectile setVectorDir _vectorVelocity; + _projectile setVelocity _vectorVelocity; + } else { + _projectile setDamage 1; + }; +}; + +switch (_simType) do { + case "shotbullet": { + private _sound = selectRandom [QPATHTO_R(sounds\light_crack_close.wss), QPATHTO_R(sounds\light_crack_close_filtered.wss), QPATHTO_R(sounds\heavy_crack_close.wss), QPATHTO_R(sounds\heavy_crack_close_filtered.wss)]; + playSound3D [_sound, objNull, false, getPosASL _object, 2, 1, 1250]; if (random 1 < 0.6) then { - [_vehicle, _ammo, _speed, true] call _spawnProjectile; + [_object, _ammo, _speed, true] call _fnc_spawnProjectile; }; }; - if (toLower _simType == "shotshell") then { - private _sound = selectRandom [QUOTE(PATHTO_R(sounds\heavy_crack_close.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close_filtered.wss))]; - playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1300]; + case "shotshell": { + private _sound = selectRandom [QPATHTO_R(sounds\heavy_crack_close.wss), QPATHTO_R(sounds\heavy_crack_close_filtered.wss)]; + playSound3D [_sound, objNull, false, getPosASL _object, 2, 1, 1300]; if (random 1 < 0.15) then { - [_vehicle, _ammo, _speed, true] call _spawnProjectile; + [_object, _ammo, _speed, true] call _fnc_spawnProjectile; }; }; - if (toLower _simType == "shotgrenade") then { + case "shotgrenade": { if (random 1 < 0.9) then { _speed = 0; }; - [_vehicle, _ammo, _speed, random 1 < 0.5] call _spawnProjectile; + + [_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile; }; - if (toLower _simType in ["shotrocket", "shotmissile", "shotsubmunitions"]) then { + case "shotrocket"; + case "shotmissile"; + case "shotsubmunitions": { if (random 1 < 0.1) then { - private _sound = selectRandom [QUOTE(PATHTO_R(sounds\cannon_crack_close.wss)), QUOTE(PATHTO_R(sounds\cannon_crack_close_filtered.wss))]; - playSound3D [_sound, objNull, false, (getPosASL _vehicle), 3, 1, 1600]; + private _sound = selectRandom [QPATHTO_R(sounds\cannon_crack_close.wss), QPATHTO_R(sounds\cannon_crack_close_filtered.wss)]; + playSound3D [_sound, objNull, false, getPosASL _object, 3, 1, 1600]; - [_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile; + [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; } else { - createvehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld _effect2pos), [], 0 , "CAN_COLLIDE"]; + createVehicle ["ACE_ammoExplosionLarge", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; }; }; - if (toLower _simType in ["shotdirectionalbomb", "shotmine"]) then { + case "shotdirectionalbomb"; + case "shotmine": { if (random 1 < 0.5) then { // Not all explosives detonate on destruction, some have scripted alternatives - private _scripted = getNumber (_ammoCfg >> "triggerWhenDestroyed") == 1; - if !(_scripted) then { - _ammo = getText (_ammoCfg >> "ace_explosives_Explosive"); + if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then { + _ammo = getText (_configAmmo >> QEGVAR(explosives,explosive)); }; // If a scripted alternative doesn't exist use generic explosion if (_ammo != "") then { - [_vehicle, _ammo, 0, false] call _spawnProjectile; + [_object, _ammo, 0, false] call _fnc_spawnProjectile; } else { - createvehicle ["SmallSecondary", (_vehicle modelToWorld _effect2pos), [], 0 , "CAN_COLLIDE"]; + createVehicle ["SmallSecondary", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; }; }; }; - if (toLower _simType == "shotilluminating") then { + case "shotilluminating": { if (random 1 < 0.15) then { - [_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile; + [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; }; }; - - [FUNC(detonateAmmunition), [_vehicle, _magazines, _totalAmmo], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; }; -ERROR_1("mag with no ammo - %1", _magazine); diff --git a/addons/cookoff/functions/fnc_engineFire.sqf b/addons/cookoff/functions/fnc_engineFire.sqf index 118537b30a3..9b7160531e6 100644 --- a/addons/cookoff/functions/fnc_engineFire.sqf +++ b/addons/cookoff/functions/fnc_engineFire.sqf @@ -4,48 +4,28 @@ * Start fire in engine block of a car. * * Arguments: - * 0: Vehicle + * 0: Vehicle * * Return Value: * None * * Example: - * (vehicle player) call ace_cookoff_fnc_engineFire + * cursorObject call ace_cookoff_fnc_engineFire * * Public: No */ +if (!isServer) exitWith {}; + params ["_vehicle"]; +// If already smoking, stop if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {}; -_vehicle setVariable [QGVAR(isEngineSmoking), true]; - -if (local _vehicle) then { - [QGVAR(engineFire), _vehicle] call CBA_fnc_globalEvent; -}; - -private _offset = getArray (_vehicle call CBA_fnc_getObjectConfig >> QGVAR(engineSmokeOffset)); -if (_offset isEqualTo []) then { - _offset = [0,0,0]; -}; - -private _position = [ - 0, - (boundingBoxReal _vehicle select 1 select 1) - 2, - (boundingBoxReal _vehicle select 0 select 2) + 2 -] vectorAdd _offset; - -private _smoke = "#particlesource" createVehicleLocal [0,0,0]; -_smoke setParticleClass "ObjectDestructionSmoke1_2Smallx"; -_smoke attachTo [_vehicle, _position]; +_vehicle setVariable [QGVAR(isEngineSmoking), true]; -[{ - (_this select 0) params ["_vehicle", "_smoke", "_time"]; +// Spawn engine fire effects on all connected machines +private _jipID = [QGVAR(engineFireLocal), [_vehicle, CBA_missionTime + random [ENGINE_FIRE_TIME / 2, ENGINE_FIRE_TIME, ENGINE_FIRE_TIME / 2 * 3]]] call CBA_fnc_globalEventJIP; +[_jipID, _vehicle] call CBA_fnc_removeGlobalEventJIP; - if (isNull _vehicle || {!alive _vehicle} || {_vehicle getHitPointDamage "HitEngine" < 0.9} || {CBA_missionTime > _time}) then { - deleteVehicle _smoke; - _vehicle setVariable [QGVAR(isEngineSmoking), false]; - [_this select 1] call CBA_fnc_removePerFrameHandler; - }; -}, 5, [_vehicle, _smoke, CBA_missionTime + 240]] call CBA_fnc_addPerFrameHandler; +_vehicle setVariable [QGVAR(engineFireJipID), _jipID]; diff --git a/addons/cookoff/functions/fnc_engineFireLocal.sqf b/addons/cookoff/functions/fnc_engineFireLocal.sqf new file mode 100644 index 00000000000..845ced8bd88 --- /dev/null +++ b/addons/cookoff/functions/fnc_engineFireLocal.sqf @@ -0,0 +1,61 @@ +#include "..\script_component.hpp" +/* + * Author: KoffeinFlummi, commy2 + * Start fire in engine block of a car. + * + * Arguments: + * 0: Vehicle + * + * Return Value: + * None + * + * Example: + * cursorObject call ace_cookoff_fnc_engineFireLocal + * + * Public: No + */ + +params ["_vehicle", "_endTime"]; + +// For JIP players and if the time wasn't set properly +if (_endTime < CBA_missionTime) exitWith {}; + +private _smoke = objNull; + +if (hasInterface) then { + // Get offset for engine smoke if there is one + private _offset = getArray (configOf _vehicle >> QGVAR(engineSmokeOffset)); + + if (_offset isEqualTo []) then { + _offset = [0, 0, 0]; + }; + + private _position = [ + 0, + (boundingBoxReal _vehicle select 1 select 1) - 2, + (boundingBoxReal _vehicle select 0 select 2) + 2 + ] vectorAdd _offset; + + // Spawn smoke + _smoke = "#particlesource" createVehicleLocal [0, 0, 0]; + _smoke setParticleClass "ObjectDestructionSmoke1_2Smallx"; + _smoke attachTo [_vehicle, _position]; +}; + +[{ + (_this select 0) params ["_vehicle", "_smoke", "_endTime"]; + + if (!alive _vehicle || {_vehicle getHitPointDamage "HitEngine" < 0.9} || {CBA_missionTime >= _endTime}) exitWith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + + deleteVehicle _smoke; + + if (isNull _vehicle) exitWith {}; + + if (isServer) then { + (_vehicle getVariable [QGVAR(engineFireJipID), ""]) call CBA_fnc_removeGlobalEventJIP; + }; + + _vehicle setVariable [QGVAR(isEngineSmoking), false]; + }; +}, 5, [_vehicle, _smoke, _endTime]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf index f6be84c1f90..5f6603c4537 100644 --- a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf +++ b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf @@ -4,16 +4,16 @@ * Gets all magazines inside of a vehicle. * * Arguments: - * 0: Vehicle + * 0: Vehicle * * Return Value: - * 0: Ammo Array - * - 0: Magazine Classname - * - 1: Ammo Count - * 1: Total Ammo Count + * 0: Ammo array + * - 0: Magazine classname + * - 1: Ammo count + * 1: Total ammo count * * Example: - * [vehicle player] call ace_cookoff_fnc_getVehicleAmmo + * cursorObject call ace_cookoff_fnc_getVehicleAmmo * * Public: No */ @@ -23,42 +23,52 @@ TRACE_1("getVehicleAmmo",_vehicle); private _ammoToDetonate = []; private _totalAmmo = 0; +private _cfgMagazines = configFile >> "CfgMagazines"; +private _cfgAmmo = configFile >> "CfgAmmo"; +private _ammo = ""; // Get ammo from turrets { - _x params ["_mag", "_turret", "_count"]; - // if the turret is an FFV seat, it takes magazines from the soldier - if (_count > 0) then { - if (_mag call FUNC(isMagazineFlare)) then {continue}; - private _ammo = getText (configFile >> "CfgMagazines" >> _mag >> "ammo"); - private _model = getText (configFile >> "CfgAmmo" >> _ammo >> "model"); - if (_model == "\A3\weapons_f\empty") exitWith {TRACE_3("skipping",_mag,_ammo,_model);}; - _ammoToDetonate pushBack [_mag, _count]; + // If the turret is an FFV seat, it takes magazines from the soldier + _x params ["_magazine", "", "_count"]; + + if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then { + _ammo = getText (_cfgMagazines >> _magazine >> "ammo"); + + if (getText (_cfgAmmo >> _ammo >> "model") == "\A3\weapons_f\empty") then { + TRACE_2("skipping",_magazine,_ammo); + + continue; + }; + + _ammoToDetonate pushBack [_magazine, _count]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAllTurrets [_vehicle, true]); // Get ammo from cargo space { - _x params ["_mag", "_count"]; - if (_count > 0) then { - if (_mag call FUNC(isMagazineFlare)) then {continue}; - _ammoToDetonate pushBack [_mag, _count]; + _x params ["_magazine", "_count"]; + + if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then { + _ammoToDetonate pushBack [_magazine, _count]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAmmoCargo _vehicle); // Get ammo from transportAmmo / ace_rearm -private _vehCfg = configOf _vehicle; +private _configVehicle = configOf _vehicle; +private _configSupply = (getNumber (_configVehicle >> "transportAmmo")) max (getNumber (_configVehicle >> QEGVAR(rearm,defaultSupply))); -private _configSupply = (getNumber (_vehCfg >> "transportAmmo")) max (getNumber (_vehCfg >> QEGVAR(rearm,defaultSupply))); -if (_vehicle getVariable [QEGVAR(rearm,isSupplyVehicle), (_configSupply > 0)]) then { +if (_vehicle getVariable [QEGVAR(rearm,isSupplyVehicle), _configSupply > 0]) then { TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _vehicle); _ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000]; _totalAmmo = _totalAmmo + 2000; + _ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100]; _totalAmmo = _totalAmmo + 100; + _ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10]; _totalAmmo = _totalAmmo + 10; }; diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index dfc5cb7267c..2f76ef9c772 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -1,13 +1,13 @@ #include "..\script_component.hpp" /* * Author: KoffeinFlummi, commy2 - * Handles all incoming damage for boxi + * Handles all incoming damage for boxes. * * Arguments: * HandleDamage EH * * Return Value: - * Damage to be inflicted. + * Damage to be inflicted (can be nil) * * Example: * _this call ace_cookoff_fnc_handleDamageBox @@ -15,58 +15,60 @@ * Public: No */ -params ["_vehicle", "", "_damage", "_source", "_ammo", "_hitIndex", "_shooter"]; +params ["_box", "", "_damage", "_source", "_ammo", "_hitIndex", "_instigator"]; -// it's already dead, who cares? -if (damage _vehicle >= 1) exitWith {}; +if (!local _box) exitWith {}; -// If cookoff is disabled exit -if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] in [0, false]) exitWith {}; +// If it's already dead, ignore +if (damage _box >= 1) exitWith {}; -// get hitpoint name +// 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 = toLower ((getAllHitPointsDamage _vehicle param [0, []]) select _hitIndex); + _hitpoint = ((getAllHitPointsDamage _box) param [0, []]) select _hitIndex; }; -// get change in damage -private _oldDamage = 0; +if !(_hitpoint == "#structural" && {_damage > 0.5}) exitWith {}; -if (_hitpoint isEqualTo "#structural") then { - _oldDamage = damage _vehicle; +// Catch fire when hit by an explosive round +if (IS_EXPLOSIVE_AMMO(_ammo)) then { + [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; } else { - _oldDamage = _vehicle getHitIndex _hitIndex; -}; + // 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 (_hitpoint == "#structural" && _damage > 0.5) then { - // Almost always catch fire when hit by an explosive - if (IS_EXPLOSIVE_AMMO(_ammo)) then { - _vehicle call FUNC(cookOffBox); + // Need magazine to check for tracers + private _magazine = if (_source == _instigator) then { + currentMagazine _source } else { - // Need magazine to check for tracers - private _mag = ""; - if (_source == _shooter) then { - _mag = currentMagazine _source; - } else { - _mag = _source currentMagazineTurret ([_shooter] call CBA_fnc_turretPath); - }; - private _magCfg = configFile >> "CfgMagazines" >> _mag; + _source currentMagazineTurret (_box unitTurret _instigator) + }; + + private _configMagazine = configFile >> "CfgMagazines" >> _magazine; + + // Magazine could have changed during flight time (just ignore if so) + if (getText (_configMagazine >> "ammo") == _ammo) then { + // If magazine's tracer density is high enough then low chance for cook off + private _tracers = getNumber (_configMagazine >> "tracersEvery"); - // Magazine could have changed during flight time (just ignore if so) - if (getText (_magCfg >> "ammo") == _ammo) then { - // If magazine's tracer density is high enough then low chance for cook off - private _tracers = getNumber (_magCfg >> "tracersEvery"); - if (_tracers >= 1 && {_tracers <= 4}) then { - if (random 1 < _oldDamage*0.05) then { - _vehicle call FUNC(cookOffBox); - }; - }; + if (_tracers >= 1 && {_tracers <= 4}) then { + [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; }; - - // prevent destruction, let cook-off handle it if necessary - _damage min 0.89 -} else { - _damage }; + +// Prevent destruction, let cook-off handle it if necessary +_damage min 0.89 diff --git a/addons/cookoff/functions/fnc_isMagazineFlare.sqf b/addons/cookoff/functions/fnc_isMagazineFlare.sqf index b6c8a604be3..fd6ea996411 100644 --- a/addons/cookoff/functions/fnc_isMagazineFlare.sqf +++ b/addons/cookoff/functions/fnc_isMagazineFlare.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: Cyruz - * Checks if the magazine has ammo which is a flare + * Checks if the magazine's ammo are flares. * * Arguments: * 0: Magazine @@ -10,15 +10,15 @@ * 0: If magazine is type of flare * * Example: - * ["3Rnd_UGL_FlareWhite_F"] call ace_cookoff_fnc_isMagazineFlare + * "3Rnd_UGL_FlareWhite_F" call ace_cookoff_fnc_isMagazineFlare * * Public: No */ params ["_magazine"]; -private _ammo = getText (configFile >> "CfgMagazines" >> _magazine >> "ammo"); -private _intensity = getNumber (configFile >> "CfgAmmo" >> _ammo >> "intensity"); -private _flare = getNumber (configFile >> "CfgAmmo" >> _ammo >> QEGVAR(grenades,flare)); +private _configAmmo = configFile >> "CfgAmmo" >> getText (configFile >> "CfgMagazines" >> _magazine >> "ammo"); +private _intensity = getNumber (_configAmmo >> "intensity"); +private _flare = getNumber (_configAmmo >> QEGVAR(grenades,flare)); _intensity != 0 || _flare == 1 diff --git a/addons/cookoff/functions/fnc_smoke.sqf b/addons/cookoff/functions/fnc_smoke.sqf index ce50043413f..6ff2726fa1b 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 (default: []) * * Return Value: * None @@ -18,10 +18,12 @@ params ["_vehicle", ["_positions", []]]; -private _turretConfig = [_vehicle, [0]] call CBA_fnc_getTurret; -private _positionBarrelEnd = getText (_turretConfig >> "gunBeg"); +// Make sure effects are cleaned up if vehicle is deleted +[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent; -// smoke out of cannon and hatches +private _positionBarrelEnd = getText ([_vehicle, [0]] call CBA_fnc_getTurret >> "gunBeg"); + +// Smoke out of cannon and hatches private _smokeBarrel = "#particlesource" createVehicleLocal [0, 0, 0]; _smokeBarrel setParticleClass "MediumDestructionSmoke"; _smokeBarrel attachTo [_vehicle, [0, 0, 0], _positionBarrelEnd]; @@ -31,7 +33,7 @@ private _effects = [_smokeBarrel]; { private _position = [0, -2, 0]; - if (_x isNotEqualTo "#noselection") then { + if (_x != "#noselection") then { _position = _vehicle selectionPosition _x; }; diff --git a/addons/cookoff/initSettings.inc.sqf b/addons/cookoff/initSettings.inc.sqf index 8912636fd6a..afaaabc1b05 100644 --- a/addons/cookoff/initSettings.inc.sqf +++ b/addons/cookoff/initSettings.inc.sqf @@ -1,69 +1,69 @@ [ - QGVAR(enable), "LIST", - [LSTRING(enable_hd_name), LSTRING(enable_hd_tooltip)], + QGVAR(enable), + "LIST", + [LSTRING(enable_name), LSTRING(enable_tooltip)], LSTRING(category_displayName), [[0, 1, 2], ["STR_A3_OPTIONS_DISABLED", ELSTRING(common,playerOnly), ELSTRING(common,playersAndAI)], 2], - true, // isGlobal - {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + 1, + {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(enableFire), "CHECKBOX", - [LSTRING(enableFire_name), LSTRING(enableFire_tooltip)], + QGVAR(cookoffDuration), + "SLIDER", + [LSTRING(cookoffDuration_name), LSTRING(cookoffDuration_tooltip)], LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(enableFire), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart + [0, 5, 1, 1], + 1, + {[QGVAR(cookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(destroyVehicleAfterCookoff), "CHECKBOX", - [LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)], + QGVAR(probabilityCoef), + "SLIDER", + [LSTRING(probabilityCoef_name), LSTRING(probabilityCoef_tooltip)], LSTRING(category_displayName), - false, // default value - true, // isGlobal - {[QGVAR(destroyVehicleAfterCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart + [0, 5, 1, 1], + 1, + {[QGVAR(probabilityCoef), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(enableAmmoCookoff), "CHECKBOX", - [LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)], + QGVAR(destroyVehicleAfterCookoff), + "CHECKBOX", + [LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)], LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(enableAmmoCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart + false, + 1, + {[QGVAR(destroyVehicleAfterCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(enableAmmobox), "CHECKBOX", - [LSTRING(enableBoxCookoff_name), LSTRING(enableBoxCookoff_tooltip)], + QGVAR(enableAmmoCookoff), + "CHECKBOX", + [LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)], LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(enableAmmobox), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + true, + 1, + {[QGVAR(enableAmmoCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(ammoCookoffDuration), "SLIDER", - [LSTRING(ammoCookoffDuration_name), LSTRING(ammoCookoffDuration_tooltip)], + QGVAR(enableAmmobox), + "CHECKBOX", + [LSTRING(enableBoxCookoff_name), LSTRING(enableBoxCookoff_tooltip)], LSTRING(category_displayName), - [0,5,1,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] - true, // isGlobal - {[QGVAR(ammoCookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + true, + 1, + {[QGVAR(enableAmmobox), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(probabilityCoef), "SLIDER", - [LSTRING(probabilityCoef_name), LSTRING(probabilityCoef_tooltip)], + QGVAR(ammoCookoffDuration), + "SLIDER", + [LSTRING(ammoCookoffDuration_name), LSTRING(ammoCookoffDuration_tooltip)], LSTRING(category_displayName), - [0,5,1,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] - true, // isGlobal - {[QGVAR(probabilityCoef), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + [0, 5, 1, 1], + 1, + {[QGVAR(ammoCookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; diff --git a/addons/cookoff/script_component.hpp b/addons/cookoff/script_component.hpp index 03b3e5c5f57..9e00ea970ee 100644 --- a/addons/cookoff/script_component.hpp +++ b/addons/cookoff/script_component.hpp @@ -24,6 +24,7 @@ #define SMOKE_TIME 10.5 #define COOKOFF_TIME 14 // Cook off time should be 20s at most due to length of sound files #define COOKOFF_TIME_BOX 82.5 // Cook off time for boxes should be significant to allow time for ammo to burn +#define ENGINE_FIRE_TIME 240 #define MIN_TIME_BETWEEN_FLAMES 5 #define MAX_TIME_BETWEEN_FLAMES 15 #define MAX_TIME_BETWEEN_AMMO_DET 25 diff --git a/addons/cookoff/stringtable.xml b/addons/cookoff/stringtable.xml index 76aebcad60e..5959a237825 100644 --- a/addons/cookoff/stringtable.xml +++ b/addons/cookoff/stringtable.xml @@ -2,7 +2,7 @@ - ACE Cook off + ACE Cook-off ACE Detonación inducida por calor ACE Detonazione Munizioni ACE 殉爆效果 @@ -16,38 +16,14 @@ ACE Cook off ACE Vznícení munice - - Damage handling and turret effects - Daño y efectos de torreta - Schadensberechnung und Geschützturmeffekte - 損傷処理と砲塔の効果 - Обработка урона и эффектов срыва башни - Manipulação de dano e efeitos de torre - Dégâts et effets de tourelle - 傷害控制及炮塔效果 - 损坏处理和炮塔效果 - Gestione danni ed effetti torretta - Poškodit ovládání a efekty věže - Obsługa obrażeń i efekty wieży - 피해량 조절 및 포탑에 효과 부여 + + Enable vehicle cook-off - - Changes damage handling for cook off and turret explosion effects - Cambia el daño de la detonación inducida por calor y los efectos de la explosión de la torreta - Ändert die Schadensberechnung für die Durchzündung und die Explosionseffekte des Geschützturmes - 誘爆の損傷処理と砲塔の爆発効果を変更します。 - Изменяет обработку урона для возгорания и эффекта срыва башни - Modifica a manipulação de dano para o cozinhamento de munição e efeitos de explosão da torre - Modifie la gestion des dégâts pour l'auto-inflammation et les effets d'explosion de tourelle. - 更改殉爆以及炮塔爆炸之傷害控制 - 改变殉爆和炮塔爆炸的损坏处理效果 - Modifica la gestione dei danni per l'esplosione di munizioni e gli effetti di esplosione della torretta - Změní poškození ovládání a efekty výbuchu veže - Zmienia obsługę obrażeń podczas samozapłonu i eksplozji wieży - 쿡오프로 인해 피해량의 변화와 포탑 터짐현상을 결정합니다. + + Enables vehicle cook-off effects (fire and sound). - Enable ammo box cook off + Enable ammo box cook-off Habilitar detonación inducida por calor en las cajas de munición 弾薬箱の誘爆を有効化 Durchzündung für Munitionskisten ermöglichen @@ -77,97 +53,31 @@ Zapíná vznícení munice v krabicích. - Enable Ammunition cook off - Habilitar la detonación inducida por calor en la munición - 弾薬の誘爆を有効化 - Durchzündung für Munition ermöglichen - 탄약 쿡오프 현상 활성화 - Aktywuj samozapłon amunicji - Auto-inflammation des munitions - Abilita Esplosione Munizioni - 開啟彈藥殉爆效果 - 开启弹药殉爆效果 - Разрешить детонацию боекомплекта - Permitir cozinhar munição - Povolit vznícení munice + Enable vehicle ammo cook-off - Enables Ammunition cook off. Fires ammunition projectiles while vehicle is on fire and has ammunition. - Habilita la detonación inducida por calor en la munición. Dispara proyectiles de munición mientras el vehículo está ardiendo y tiene munición - 弾薬が誘爆します。車両が燃えると、搭載している弾薬が激しく燃え上がります。 - Ermöglicht Durchzündung von Munition. Feuert Projektile der Munition ab, solange das Fahrzeug brennt und Munition besitzt. - Aktywuje samozapłon amunicji. Wystrzeliwuje pociski podczas gdy pojazd płonie i posiada amunicję. - Permet l'auto-inflammation des munitions. Tire des projectiles tant que le véhicule est en feu et contient des munitions. - Abilita l'esplosione di munizioni. Spara proiettili di munizioni quando il veicolo va a fuoco e contiene ancora munizioni. - 開啟彈藥殉爆效果。當一台載有彈藥的載具起火時, 將會有殉爆的效果 - 开启弹药殉爆效果。当一台载有弹药的载具起火时,将会有殉爆的效果。 - 쿡오프 현상을 활성화 합니다. 이것은 탄약에 불이 붙어 있는 동안 주변에 발사체를 발사합니다. - Активирует детонацию боекомплекта в горящей технике. - Permite que a munição cozinhe. Dispara projéteis de munição enquanto o veículo está em chamas e tem munição. - Zapíná vznícení munice. Vystřeluje projektily po dobu kdy vozidlo hoří a má munici. + Enables cooking off of vehicle ammunition. Fires ammunition projectiles while vehicle has ammunition remaining. + + + Vehicle cook-off duration multiplier + + + Multiplier for how long vehicle cook-off lasts.\nSetting to 0 will disable cookoff. - Ammunition cook off duration - Duración de la detonación inducida por calor de la munición - Munitionsdurchzündungsdauer - Czas trwania samozapłonu amunicji - 弾薬の誘爆持続時間 - Durée d'auto-inflammation des munitions - Durata Esplosione Munizioni - 彈藥殉爆效果持續時間 - 弹药殉爆效果持续时间 - 쿡오프 지속 시간 - Длительность детонации боеприпасов - Duração do cozinhamento de munição - Doba trvání vznícení munice + Ammo cook-off duration multiplier - Multiplier for how long cook off lasts [Setting to 0 will disable ammo cookoff] - Multiplicador de cuanto dura la detonación inducida por calor [Ponerlo a cero la deshabilita] - Faktor für die Munitionsdurchzündungsdauer [0 zum Deaktivieren] - Multiplicateur permettant de régler la durée durant laquelle les munitions continuent d'exploser [Une valeur de 0 désactive l'auto-inflammation]. - Mnożnik decydujący jak długo ma trwać samozapłon amunicji [Ustawienie na 0 spowoduje wyłącznie samozapłonu] - 誘爆の持続時間を乗数で設定します。[0 に設定で誘爆を無効化] - Moltiplicatore della durata delle esplosioni di munizioni [Se impostato su 0 disabiliterà le esplosioni delle munizioni] - 設定彈藥殉爆效果會持續多久時間 [輸入0來關閉殉爆效果] - 设定弹药殉爆效果会持续多久时间 [输入0来关闭殉爆效果] - 쿡오프 지속 시간의 배수 [0 이면 비활성] - Множитель длительности детонации [0 - отключает детонацию боеприпасов] - Multiplicação da duração do cozinhamento [0 faz com que o cozinhamento seja desativado] - Multiplikátor doby trvání vznícení munice [Nastavte 0 pro vypnutí vznícení munice] + Multiplier for how long ammunition cook-off lasts, for both vehicles and ammo boxes.\nSetting to 0 will disable ammo cookoff. - Cook-off probability coefficient - Coeficiente de probabilidad de detonación inducida por calor - 誘爆の可能性係数 - Coefficiente Probabilità Esplosione - Faktor für Wahrscheinlichkeit der Durchzündung - 殉爆發生機率係數 - 殉爆发生机率系数 - Coefficient de probabilité d'auto-inflammation - Współczynnik prawdopodobieństwa samozapłonu - Коэф. вероятности детонации - Probabilidade de Cozinhar - Koeficient pravděpodobnosti vznícení munice - 쿡오프 발생 확률 계수 + Vehicle cook-off probability multiplier - Multiplier for cook-off probability. Higher value results in higher cook-off probability - Multiplicador de probabilidad de detonación inducida por calor. Valores más altos producen mayor probabilidad - 誘爆する可能性の乗数。高い値では誘爆する可能性が高まります。 - Moltiplicatore per la probabilità dell'esplosione di munizioni. Un valore più alto aumenta la probabilità. - Faktor für Wahrscheinlichkeit der Durchzündung. Ein höherer Wert führt zu höherer Durchzündungswahrscheinlichkeit. - 調整殉爆發生機率係數。值越高代表越容易發生殉爆 - 调整殉爆发生机率系数。值越高代表越容易发生殉爆。 - Multiplicateur de probabilité de l'auto-inflammation. Plus la valeur est élevée, plus la probabilité de combustion est grande. - Mnożnik prawdopodobieństwa samozapłonu. Większa wartość oznacza większe prawdopodobieństwo samozapłonu - Множитель коэффициента вероятности детонации. Чем выше значение, тем выше вероятность - Multiplicador para a chance de cozinhamento. Valores mais altos aumentam as chances de ocorrer. - Multiplikátor pro pravděpodobnost vznícení munice. Vyšší hodnota znamená vyšší šanci vznícení munice. - 쿡오프가 일어날 확률에 계수를 곱합니다. 더 큰 숫자는 더 높은 확률의 쿡오프를 일으킵니다. + Multiplier for vehicle cook-off probability. Higher value results in higher cook-off probability.\nSetting to 0 will disable cookoff. - Destroy Vehicles After Cook-off + Destroy vehicles after cook-off 쿡오프 후 차량 파괴 殉爆发生后摧毁载具 Уничтожать технику после детонации @@ -189,31 +99,5 @@ Contrôle si les véhicules seront toujours détruits après l'auto-inflammation. Define se os veículos serão sempre destruídos após cozinhamento. - - Enable Cook-Off Vehicle Fire - 誘爆火災を有効化 - Véhicules - Feu durant l'auto-inflammation - Вкл. горение техники от детонации - Aktiviert das in Brand setzen des Fahrzeugs während des Durchzündens der Munition - Abilita incendiamento veicoli - Włącz pożar pojazdu podczas samozapłonu - 启用殉爆载具火灾 - 차량 쿡오프 화재 활성화 - Habilitar incendio a causa de la detonación inducida por calor - Ativar incêndio de veículo durante cozinhamento - - - Whether or not vehicles will catch on fire during cook-off - 誘爆により車両が炎上するかどうかを設定します。 - Définit si les véhicules prennent feu durant l'auto-inflammation de leurs munitions. - Будет ли техника гореть при детонации боеприпасов - Ob Fahrzeuge in Brand gesetzt werden, während deren Munition durchzündet. - Determina se veicoli cominceranno a bruciare se le loro munizioni esplodono. - Określa, czy pojazdy zapalą się podczas samozapłonu ich amunicji. - 车辆在殉爆过程中是否会起火 - 쿡오프가 일어나면 차량에 불이 붙습니다. - Define si los vehículos salen ardiendo despues de una detonación inducida por calor. - Define se os veículos pegarão fogo durante o cozinhamento. - diff --git a/addons/grenades/functions/fnc_incendiary.sqf b/addons/grenades/functions/fnc_incendiary.sqf index 11d89d4ca53..e1e27325764 100644 --- a/addons/grenades/functions/fnc_incendiary.sqf +++ b/addons/grenades/functions/fnc_incendiary.sqf @@ -175,10 +175,12 @@ if (isServer) then { }; if (_x isKindOf "ReammoBox_F") then { if ( - "ace_cookoff" call EFUNC(common,isModLoaded) && - {GETVAR(_x,EGVAR(cookoff,enableAmmoCookoff),EGVAR(cookoff,enableAmmobox))} + (["ace_cookoff"] call EFUNC(common,isModLoaded)) && + {EGVAR(cookoff,enableAmmobox)} && + {EGVAR(cookoff,ammoCookoffDuration) != 0} && + {_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]} ) then { - _x call EFUNC(cookoff,cookOffBox); + [QEGVAR(cookOff,cookOffBox), [_box, objNull, objNull]] call CBA_fnc_serverEvent; } else { _x setDamage 1; }; @@ -232,10 +234,7 @@ private _enginePosition = _vehicle modelToWorld (_vehicle selectionPosition _eng if (_position distance _enginePosition < EFFECT_SIZE * 2) then { _vehicle setHit [_engineSelection, 1]; - if ("ace_cookoff" call EFUNC(common,isModLoaded)) then { - private _enabled = _vehicle getVariable [QEGVAR(cookoff,enable), EGVAR(cookoff,enable)]; - if (_enabled in [2, true] || {_enabled isEqualTo 1 && {fullCrew [_vehicle, "", false] findIf {isPlayer (_x select 0)} != -1}}) then { - _vehicle call EFUNC(cookoff,engineFire); - }; + if (["ace_cookoff"] call EFUNC(common,isModLoaded)) then { + [QEGVAR(cookoff,engineFire), _vehicle] call CBA_fnc_serverEvent; }; }; diff --git a/addons/vehicle_damage/functions/fnc_addDamage.sqf b/addons/vehicle_damage/functions/fnc_addDamage.sqf index 75d72da3406..017feffcebb 100644 --- a/addons/vehicle_damage/functions/fnc_addDamage.sqf +++ b/addons/vehicle_damage/functions/fnc_addDamage.sqf @@ -37,6 +37,6 @@ if (_hitIndex >= 0) then { _vehicle setHitPointDamage [_hitPoint, _damage, true]; }; -if (_hitPoint isEqualTo "hitengine" && { _damage > 0.9 }) then { - _vehicle call EFUNC(cookoff,engineFire); +if (_hitPoint == "hitengine" && {_damage > 0.9}) then { + [QEGVAR(cookoff,engineFire), _vehicle] call CBA_fnc_serverEvent; }; diff --git a/addons/vehicle_damage/functions/fnc_detonate.sqf b/addons/vehicle_damage/functions/fnc_detonate.sqf index 67d64da442b..437570292d2 100644 --- a/addons/vehicle_damage/functions/fnc_detonate.sqf +++ b/addons/vehicle_damage/functions/fnc_detonate.sqf @@ -23,7 +23,7 @@ if (_vehicleAmmo isEqualTo []) then { _vehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo); }; -([_vehicle] + _vehicleAmmo) call EFUNC(cookoff,detonateAmmunition); +[QEGVAR(cookoff,detonateAmmunition), [_vehicle] + _vehicleAmmo] call CBA_fnc_serverEvent; if ((_vehicleAmmo select 1) > 0) then { { diff --git a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf index a6e73355425..453454d08c2 100644 --- a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf +++ b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf @@ -23,7 +23,9 @@ params ["_vehicle", "_chanceOfFire", "_intensity", ["_injurer", objNull], ["_hitPart", ""], ["_canRing", false], ["_canJet", true]]; -private _alreadyCookingOff = _vehicle getVariable [QGVAR(cookingOff), false]; +private _alreadyCookingOff = _vehicle getVariable [QEGVAR(cookoff,isCookingOff), false]; + +_chanceOfFire = _chanceOfFire * EGVAR(cookoff,probabilityCoef); if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith { private _configOf = configOf _vehicle; @@ -45,8 +47,7 @@ if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith { }; // sending nil for _maxIntensity (9th param) to use default value in ace_cookoff_fnc_cookOff - [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, nil, _canJet]] call CBA_fnc_localEvent; - _vehicle setVariable [QGVAR(cookingOff), true]; + [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, nil, _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); diff --git a/docs/wiki/framework/cookoff-framework.md b/docs/wiki/framework/cookoff-framework.md index b53fea2049c..6b8f26182c0 100644 --- a/docs/wiki/framework/cookoff-framework.md +++ b/docs/wiki/framework/cookoff-framework.md @@ -12,43 +12,22 @@ version: patch: 0 --- -## 1. Disabling / Enabling Cook off for individual vehicles +## 1. Disabling cook-off for individual vehicles -You can dynamically enable and/or disable vehicle cook off for individual vehicles by using `setVariable`: +Cook-off can be disabled for a specific vehicle. "Cook-off" refers to the fire effects (visual & sounds) that happen when a vehicle is cooking off: ``` -VEHICLE setVariable ["ace_cookoff_enable", true, true]; +_vehicle setVariable ["ace_cookoff_enable", false, true]; ``` -The above will enable cook off for that specific vehicle, no matter the mission settings. +Mission settings will always apply however, so you can't enable cook-off on a vehicle if the mission settings have cook-off for vehicles disabled. -Likewise, cook off can also be disabled for a specific vehicle: +## 2. Disabling ammunition cook-off for individual vehicles and boxes -``` -VEHICLE setVariable ["ace_cookoff_enable", false, true]; -``` - -## 2. Cook off probability - -You can set the probability of cook off for individual vehicle types by changing the `ace_cookoff_probability` value in the vehicle's config: +Ammunition cook-off can be disabled for a specific vehicle or box. "Ammunition cook-off" refers to the ammunition exploding in a burning vehicle: ``` -class MyVehicle { - ace_cookoff_probability = 0.6; -}; +_vehicleOrBox setVariable ["ace_cookoff_enableAmmoCookoff", false, true]; ``` -Global cook off probability can also be adjusted with the `ace_cookoff_probabilityCoef` mission setting. - -Higher values will make cook-off more probable, whilst lower values will make cook-off less probable. - -## 3. Ignore damage to turret - -For use on vehicles when damage to the main turret would not cause a vehicle cookoff. -e.g. RCWS turrets - -``` -class MyVehicle { - ace_vehicle_damage_turretFireProb = 0; -}; -``` +Mission settings will always apply however, so you can't enable ammunition cook-off on a vehicle or box if the mission settings have ammunition cook-off disabled. diff --git a/docs/wiki/framework/events-framework.md b/docs/wiki/framework/events-framework.md index c29f271719c..f4edcbad4c1 100644 --- a/docs/wiki/framework/events-framework.md +++ b/docs/wiki/framework/events-framework.md @@ -110,9 +110,10 @@ MenuType: 0 = Interaction, 1 = Self Interaction | Event Key | Parameters | Locality | Type | Description | |----------|---------|---------|---------|---------|---------| -|`ace_cookoff_cookOff` | _vehicle | Global | Listen | Vehicle cook off has started -|`ace_cookoff_cookOffBox` | _box | Global | Listen | Ammo box cook off has started -|`ace_cookoff_engineFire` | _vehicle | Global | Listen | Engine fire has started +|`ace_cookoff_cookOff` | [_vehicle, _intensity, _instigator, _smokeDelayEnabled, _ammoDetonationChance, _detonateAfterCookoff, _fireSource, _canRing, _maxIntensity, _canJet] | Server | Callable | Start vehicle cook-off +|`ace_cookoff_cookOffBox` | [_box, _killer, _instigator] | Server | Callable | Start ammo box cook-off +|`ace_cookoff_detonateAmmunition` | [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator, _initialDelay"] | Server | Callable | Start ammo detonation +|`ace_cookoff_engineFire` | _vehicle | Server | Callable | Start engine fire ### 2.11 Attach (`ace_attach`) diff --git a/docs/wiki/framework/vehicledamage-framework.md b/docs/wiki/framework/vehicledamage-framework.md index 7e22bccf5db..60d60e9676f 100644 --- a/docs/wiki/framework/vehicledamage-framework.md +++ b/docs/wiki/framework/vehicledamage-framework.md @@ -47,7 +47,7 @@ Default: 0.5 #### 1.1.5 `ace_vehicle_damage_turretFireProb` -The probabilitiy for the vehicle to catch on fire upon its turret being penetrated +The probability for the vehicle to catch on fire upon its turret being penetrated Default: 0.2 From d7dafa4d402c7c1d2b4c9e5435122c3f379115b3 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:48:54 +0100 Subject: [PATCH 02/27] More changes --- addons/cookoff/XEH_postInit.sqf | 5 +- addons/cookoff/functions/fnc_cookOff.sqf | 2 +- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 9 +--- .../cookoff/functions/fnc_cookOffEffect.sqf | 3 +- .../functions/fnc_detonateAmmunition.sqf | 52 +++++++++++++------ .../cookoff/functions/fnc_getVehicleAmmo.sqf | 10 ++-- addons/cookoff/initSettings.inc.sqf | 10 ++++ addons/cookoff/stringtable.xml | 17 ++++++ .../vehicle_damage/functions/fnc_detonate.sqf | 13 ++--- .../functions/fnc_handleCookoff.sqf | 18 ++----- .../functions/fnc_processHit.sqf | 10 ++-- addons/vehicle_damage/initSettings.inc.sqf | 10 ---- addons/vehicle_damage/stringtable.xml | 24 --------- 13 files changed, 86 insertions(+), 97 deletions(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index 400569afd67..1546cb49f9c 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -73,9 +73,6 @@ if (isServer) then { params ["_vehicle", "", "", "_useEffects"]; if (_useEffects && {_vehicle getVariable [QGVAR(enableAmmoCookoff), true]}) then { - (_vehicle call FUNC(getVehicleAmmo)) params ["_magazines", "_total"]; - - private _delay = (random MAX_AMMO_DETONATION_START_DELAY) max MIN_AMMO_DETONATION_START_DELAY; - [QGVAR(detonateAmmunition), [_vehicle, _magazines, _total, false, objNull, objNull, _delay]] call CBA_fnc_serverEvent; + [QGVAR(detonateAmmunition), [_vehicle, false, objNull, objNull, (random MAX_AMMO_DETONATION_START_DELAY) max MIN_AMMO_DETONATION_START_DELAY]] call CBA_fnc_serverEvent; }; }, nil, ["CAManBase", "StaticWeapon"]] call CBA_fnc_addClassEventHandler; diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 048b82beb2a..46fe4f9a3d2 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -107,7 +107,7 @@ if (_delayBetweenSmokeAndFire) then { }; // Wait until we are ready for the next flame - if (CBA_missionTime >= _vehicle getVariable [QGVAR(nextFlame), 0]) then { + if (_vehicle getVariable [QGVAR(nextFlame), 0] <= CBA_missionTime) then { private _ring = false; if (_canRing) then { diff --git a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf index 2e0dd031a1d..499e5f2a706 100644 --- a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf +++ b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf @@ -70,14 +70,9 @@ if (_delay >= 0) then { _box setVariable [QGVAR(effects), _effects]; }; - // These functions are smart and do all the cooking off work + // Detonate the ammunition if (isServer) then { - (_box call FUNC(getVehicleAmmo)) params ["_magazines", "_total"]; - - [QGVAR(detonateAmmunition), [_box, _magazines, _total, true, _killer, _instigator]] call CBA_fnc_localEvent; - - // This shit is busy being on fire, magazines aren't accessible/usable - clearMagazineCargoGlobal _box; + [QGVAR(detonateAmmunition), [_box, true, _killer, _instigator]] call CBA_fnc_localEvent; }; }, _this, _delay] call CBA_fnc_waitAndExecute; }; diff --git a/addons/cookoff/functions/fnc_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index 1cf1e3f8538..0447959a598 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -84,9 +84,10 @@ if (isServer) then { }; // Make flame push object into ground to make effect seem more "alive" - if (_jet && !isGamePaused && {local _vehicle}) then { + if (_jet && !isGamePaused && {local _vehicle} && {_vehicle getVariable [QGVAR(nextForceTime), 0] <= CBA_missionTime}) then { private _force = [0, 0, _factor * -(0.5 min random 1.5) * (0.3 min random 1)] vectorMultiply getMass _vehicle; _vehicle addForce [_force, vectorUpVisual _vehicle]; + _vehicle setVariable [QGVAR(nextForceTime), CBA_missionTime + 0.01]; // this prevents bad behaviour when setAccTime is small }; // Don't spawn visual effects on machines without interfaces diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index 145bb99987c..3a66befa5c3 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -1,34 +1,50 @@ #include "..\script_component.hpp" /* - * Author: Glowbal + * Author: Glowbal, johnb43 * Detonates ammunition from an object (e.g. vehicle or crate) until no ammo is left. * * Arguments: * 0: Object - * 1: Magazine array - * - 0: Magazine classname - * - 1: Ammo count - * 2: Total ammo count - * 3: Destroy when finished (default: false) - * 4: Killer (default: objNull) - * 5: Instigator (default: objNull) - * 6: Initial delay (default: 0) + * 1: Destroy when finished (default: false) + * 2: Killer (default: objNull) + * 3: Instigator (default: objNull) + * 4: Initial delay (default: 0) * * Return Value: * Nothing Useful * * Example: - * [cursorObject, magazinesAmmo vehicle player, 1000] call ace_cookoff_fnc_detonateAmmunition + * [cursorObject] call ace_cookoff_fnc_detonateAmmunition * * Public: No */ if (!isServer) exitWith {}; -params ["_object", "_magazines", "_totalAmmo", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]]; +params ["_object", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]]; if (isNull _object) exitWith {}; +private _vehicleAmmo = _object getVariable QGVAR(cookoffMagazines); + +if (isNil "_vehicleAmmo") then { + _vehicleAmmo = _object call FUNC(getVehicleAmmo); + + _object setVariable [QGVAR(cookoffMagazines), _vehicleAmmo]; + + // 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; + + { + _object removeMagazinesTurret [_x select 0, _x select 1]; + } forEach (magazinesAllTurrets _object); + }; +}; + +_vehicleAmmo 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; @@ -53,12 +69,12 @@ if (underwater _object || { // Initial delay allows for a delay for the first time this function runs in its cycle if (_initialDelay > 0) exitWith { - [FUNC(detonateAmmunition), [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; + [FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; }; private _magazineIndex = floor random (count _magazines); private _magazine = _magazines select _magazineIndex; -_magazine params ["_magazineClassname", "_ammoCount"]; +_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile"]; // Make sure ammo is at least 0 _ammoCount = _ammoCount max 0; @@ -78,8 +94,10 @@ private _timeBetweenAmmoDetonation = ((random 10 / sqrt _totalAmmo) min MAX_TIME TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation); _totalAmmo = _totalAmmo - _removed; +_object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]]; + // Detonate the remaining ammo after a delay -[FUNC(detonateAmmunition), [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; +[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; // Get magazine info, which is used to spawn projectiles private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; @@ -87,12 +105,14 @@ private _ammo = getText (_configMagazine >> "ammo"); private _configAmmo = configFile >> "CfgAmmo" >> _ammo; private _simType = toLower getText (_configAmmo >> "simulation"); -private _speed = random (getNumber (_configMagazine >> "initSpeed") / 10) max 1; - +private _speed = linearConversion [0, 1, random 1, 1, 20, true]; private _effect2pos = _object selectionPosition "destructionEffect2"; // Spawns the projectiles, making them either fly in random directions or explode private _fnc_spawnProjectile = { + // If the magazines are inside of the cargo (inventory), don't let their projectiles escape the interior of the vehicle + if (!_spawnProjectile) exitWith {}; + params ["_object", "_ammo", "_speed", "_flyAway"]; private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3]; diff --git a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf index 5f6603c4537..235e142d27b 100644 --- a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf +++ b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf @@ -41,7 +41,7 @@ private _ammo = ""; continue; }; - _ammoToDetonate pushBack [_magazine, _count]; + _ammoToDetonate pushBack [_magazine, _count, true]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAllTurrets [_vehicle, true]); @@ -51,7 +51,7 @@ private _ammo = ""; _x params ["_magazine", "_count"]; if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then { - _ammoToDetonate pushBack [_magazine, _count]; + _ammoToDetonate pushBack [_magazine, _count, false]; _totalAmmo = _totalAmmo + _count; }; } forEach (magazinesAmmoCargo _vehicle); @@ -63,13 +63,13 @@ private _configSupply = (getNumber (_configVehicle >> "transportAmmo")) max (get if (_vehicle getVariable [QEGVAR(rearm,isSupplyVehicle), _configSupply > 0]) then { TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _vehicle); - _ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000]; + _ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000, false]; _totalAmmo = _totalAmmo + 2000; - _ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100]; + _ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100, true]; _totalAmmo = _totalAmmo + 100; - _ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10]; + _ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10, true]; _totalAmmo = _totalAmmo + 10; }; diff --git a/addons/cookoff/initSettings.inc.sqf b/addons/cookoff/initSettings.inc.sqf index afaaabc1b05..d06e1bdfab8 100644 --- a/addons/cookoff/initSettings.inc.sqf +++ b/addons/cookoff/initSettings.inc.sqf @@ -67,3 +67,13 @@ 1, {[QGVAR(ammoCookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; + +[ + QGVAR(removeAmmoDuringCookoff), + "CHECKBOX", + [LSTRING(removeAmmoDuringCookoff_name), LSTRING(removeAmmoDuringCookoff_tooltip)], + LSTRING(category_displayName), + true, + 1, + {[QGVAR(removeAmmoDuringCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; diff --git a/addons/cookoff/stringtable.xml b/addons/cookoff/stringtable.xml index 5959a237825..51c67564f50 100644 --- a/addons/cookoff/stringtable.xml +++ b/addons/cookoff/stringtable.xml @@ -99,5 +99,22 @@ Contrôle si les véhicules seront toujours détruits après l'auto-inflammation. Define se os veículos serão sempre destruídos após cozinhamento. + + Enable ammo removal during cook-off + 誘爆中の弾薬除去を有効/無効にする + Retirer les munitions durant l'auto-inflammation + Aktiviert/Deaktiviert Entfernung der Munition beim Durchzünden + Abilita rimozione munizioni dopo l'esplosione + Włącz/Wyłącz usuwanie amunicji podczas samozapłonu + 启用/禁用殉爆过程中的弹药移除功能 + 쿡오프시 탄약 제거 활성화/비활성화 + Удалять боеприпасы из-за детонации + Habilita/Deshabilita ka eliminación de munición durante la detonación inducida por calor + + + Removes all ammo during cook-off. + Retire des munitions des véhicules durant une auto-inflammation. + Entfernt Munition während dem Durchzünden der Munition eines Fahrzeuges. + diff --git a/addons/vehicle_damage/functions/fnc_detonate.sqf b/addons/vehicle_damage/functions/fnc_detonate.sqf index 437570292d2..dcb8080c6c9 100644 --- a/addons/vehicle_damage/functions/fnc_detonate.sqf +++ b/addons/vehicle_damage/functions/fnc_detonate.sqf @@ -6,7 +6,6 @@ * Arguments: * 0: The vehicle * 1: Person who caused detonation (default: objNull) - * 2: An array of vehicle ammo in vehicle (default: []) * * Return Value: * None @@ -17,15 +16,9 @@ * Public: No */ -params ["_vehicle", ["_injurer", objNull], ["_vehicleAmmo", []]]; +params ["_vehicle", ["_injurer", objNull]]; -if (_vehicleAmmo isEqualTo []) then { - _vehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo); -}; - -[QEGVAR(cookoff,detonateAmmunition), [_vehicle] + _vehicleAmmo] call CBA_fnc_serverEvent; - -if ((_vehicleAmmo select 1) > 0) then { +if (((_vehicle call EFUNC(cookoff,getVehicleAmmo)) select 1) > 0) then { { // random amount of injuries for "_i" from 0 to random 5 do { @@ -33,3 +26,5 @@ if ((_vehicleAmmo select 1) > 0) then { }; } forEach crew _vehicle; }; + +[QEGVAR(cookoff,detonateAmmunition), [_vehicle, false, _injurer, _injurer]] call CBA_fnc_serverEvent; diff --git a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf index 453454d08c2..26823f24933 100644 --- a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf +++ b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf @@ -23,11 +23,12 @@ params ["_vehicle", "_chanceOfFire", "_intensity", ["_injurer", objNull], ["_hitPart", ""], ["_canRing", false], ["_canJet", true]]; -private _alreadyCookingOff = _vehicle getVariable [QEGVAR(cookoff,isCookingOff), false]; +// Ignore if the vehicle is already cooking off +if (_vehicle getVariable [QEGVAR(cookoff,isCookingOff), false]) exitWith {true}; _chanceOfFire = _chanceOfFire * EGVAR(cookoff,probabilityCoef); -if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith { +if (_chanceOfFire >= random 1) exitWith { private _configOf = configOf _vehicle; private _fireDetonateChance = [_configOf >> QGVAR(detonationDuringFireProb), "number", 0] call CBA_fnc_getConfigEntry; if (_canRing) then { @@ -52,21 +53,8 @@ if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith { [_vehicle] spawn FUNC(abandon); LOG_1("[%1] is on fire is bailing",_vehicle); - // cant setVehicleAmmo 0 here because it removes FFV unit's ammo - if (GVAR(removeAmmoDuringCookoff)) then { - private _ammo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo); - _ammo params ["_magazines"]; - TRACE_1("removing magazines",_magazines); - { - _x params ["_magazine"]; - _vehicle removeMagazines _magazine; - } forEach _magazines; - }; true }; -// Avoid RPT spam -if (_alreadyCookingOff) exitWith { true }; - LOG_2("[%1] No Cook-off - Chance of fire [%2]",_vehicle,_chanceOfFire); false diff --git a/addons/vehicle_damage/functions/fnc_processHit.sqf b/addons/vehicle_damage/functions/fnc_processHit.sqf index 48d6ec00557..ed05a171d47 100644 --- a/addons/vehicle_damage/functions/fnc_processHit.sqf +++ b/addons/vehicle_damage/functions/fnc_processHit.sqf @@ -119,12 +119,12 @@ if (_isCar) then { _ammoEffectiveness = (_ammoEffectiveness + (_ammoEffectiveness * 0.5)) min 1; }; -private _currentVehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo); +private _currentVehicleAmmo = _vehicle call EFUNC(cookoff,getVehicleAmmo); private _chanceOfDetonation = 0; private _explosiveAmmoCount = 0; private _nonExplosiveAmmoCount = 0; -if (count (_currentVehicleAmmo select 0) isNotEqualTo 0) then { +if ((_currentVehicleAmmo select 1) > 0) then { private _magConfig = configFile >> "CfgMagazines"; private _ammoConfig = configFile >> "CfgAmmo"; private _countOfExplodableAmmo = 0; @@ -163,7 +163,7 @@ switch (_hitArea) do { _chanceOfFire = 0; // no cookoff for cars }; - if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { + if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { [_vehicle] call FUNC(knockOut); }; @@ -191,7 +191,7 @@ switch (_hitArea) do { _chanceOfFire = 0; // no cookoff for cars }; - if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { + if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { [_vehicle, _hitIndex, _hitpointName, 0.89 * _penChance] call FUNC(addDamage); [_vehicle] call FUNC(knockOut); }; @@ -265,7 +265,7 @@ switch (_hitArea) do { _chanceOfFire = 0; // no cookoff for cars }; - if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { + if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith { [_vehicle] call FUNC(knockOut); }; diff --git a/addons/vehicle_damage/initSettings.inc.sqf b/addons/vehicle_damage/initSettings.inc.sqf index ae322a6fd88..0d3f324af2f 100644 --- a/addons/vehicle_damage/initSettings.inc.sqf +++ b/addons/vehicle_damage/initSettings.inc.sqf @@ -8,16 +8,6 @@ true // Needs mission restart ] call CBA_settings_fnc_init; -[ - QGVAR(removeAmmoDuringCookoff), "CHECKBOX", - [LSTRING(removeAmmoAfterCookoff_setting_enable), LSTRING(removeAmmoAfterCookoff_setting_description)], - LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(removeAmmoDuringCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart -] call CBA_settings_fnc_init; - [ QGVAR(enableCarDamage), "CHECKBOX", [LSTRING(carDamage_setting_enable), LSTRING(carDamage_setting_description)], diff --git a/addons/vehicle_damage/stringtable.xml b/addons/vehicle_damage/stringtable.xml index 5581408f745..4a8fdb42643 100644 --- a/addons/vehicle_damage/stringtable.xml +++ b/addons/vehicle_damage/stringtable.xml @@ -49,30 +49,6 @@ Продвинутое повреждение машин Habilitar/Deshabilitar daño avanzado de coche (Experimental) - - Removes all vehicle ammo after cook-off - 誘爆後に車両から全ての弾薬を削除 - Retire toutes les munitions des véhicules après une auto-inflammation. - Entfernt die gesamte Munition nach dem Durchzünden der Munition eines Fahrzeuges. - Rimuove tutte le munizioni dal veicolo dopo l'esplosione delle stesse - Usuwa całą amunicję z pojazdu po samozapłonie - 殉爆后移除所有车辆弹药 - 쿡오프 현상 후 차량에서 모든 탄약을 제거합니다. - Удалять все боеприпасы из техники после их детонации - Elimina toda la munición del vehículo despues ser inducida a detonar por calor - - - Enable/Disable Ammo Removal During Cook-Off - 誘爆中の弾薬除去を有効/無効にする - Retirer les munitions durant l'auto-inflammation - Aktiviert/Deaktiviert Entfernung der Munition beim Durchzünden - Abilita rimozione munizioni dopo l'esplosione - Włącz/Wyłącz usuwanie amunicji podczas samozapłonu - 启用/禁用殉爆过程中的弹药移除功能 - 쿡오프시 탄약 제거 활성화/비활성화 - Удалять боеприпасы из-за детонации - Habilita/Deshabilita ka eliminación de munición durante la detonación inducida por calor - Wreck (Turret) Épave (tourelle) From e52990d52a3210de773194a0af9e8cccea01fe3b Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 3 Feb 2024 17:51:05 +0100 Subject: [PATCH 03/27] Update fnc_getVehicleAmmo.sqf --- addons/cookoff/functions/fnc_getVehicleAmmo.sqf | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf index 235e142d27b..797e96e9c30 100644 --- a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf +++ b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf @@ -10,6 +10,7 @@ * 0: Ammo array * - 0: Magazine classname * - 1: Ammo count + * - 2: If a projectile should be spawned upon detonation * 1: Total ammo count * * Example: From c0a951491b2f6adc9ec4039707a2377914a4e526 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 3 Feb 2024 19:23:49 +0100 Subject: [PATCH 04/27] Better engine fire placement --- addons/cookoff/CfgVehicles.hpp | 20 ---------- .../cookoff/functions/fnc_engineFireLocal.sqf | 38 ++++++++++++------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/addons/cookoff/CfgVehicles.hpp b/addons/cookoff/CfgVehicles.hpp index 86e0df83868..4451d120802 100644 --- a/addons/cookoff/CfgVehicles.hpp +++ b/addons/cookoff/CfgVehicles.hpp @@ -25,24 +25,4 @@ class CfgVehicles { // Big explosions for wheeled APCs (same as for tanks) explosionEffect = "FuelExplosionBig"; }; - class MRAP_01_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0, -2, 0}; - }; - class MRAP_02_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0, -2, 0}; - }; - class MRAP_03_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0, -2, 0}; - }; - class Quadbike_01_base_F: Car_F { - GVAR(engineSmokeOffset)[] = {0, 1, 0}; - }; - - class Truck_F; - class Truck_02_base_F: Truck_F { - GVAR(engineSmokeOffset)[] = {0, -2.6, -0.1}; - }; - class Truck_02_MRL_base_F: Truck_02_base_F { - GVAR(engineSmokeOffset)[] = {0, 0.3, -0.1}; - }; }; diff --git a/addons/cookoff/functions/fnc_engineFireLocal.sqf b/addons/cookoff/functions/fnc_engineFireLocal.sqf index 845ced8bd88..625a6d3fe9c 100644 --- a/addons/cookoff/functions/fnc_engineFireLocal.sqf +++ b/addons/cookoff/functions/fnc_engineFireLocal.sqf @@ -23,18 +23,32 @@ if (_endTime < CBA_missionTime) exitWith {}; private _smoke = objNull; if (hasInterface) then { - // Get offset for engine smoke if there is one - private _offset = getArray (configOf _vehicle >> QGVAR(engineSmokeOffset)); + private _hitPoints = getAllHitPointsDamage _vehicle; - if (_offset isEqualTo []) then { - _offset = [0, 0, 0]; + // Get hitpoint for engine + private _index = (_hitPoints select 0) findIf {_x == "hitengine"}; + + // Get corresponding selection + private _position = if (_index != -1) then { + _vehicle selectionPosition [(_hitPoints select 1) select _index, "HitPoints", "AveragePoint"] + } else { + [0, 0, 0] }; - private _position = [ - 0, - (boundingBoxReal _vehicle select 1 select 1) - 2, - (boundingBoxReal _vehicle select 0 select 2) + 2 - ] vectorAdd _offset; + if (_position isEqualTo [0, 0, 0]) then { + // Get offset for engine smoke if there is one + private _offset = getArray (configOf _vehicle >> QGVAR(engineSmokeOffset)); + + if (_offset isEqualTo []) then { + _offset = [0, 0, 0]; + }; + + _position = [ + 0, + (boundingBoxReal _vehicle select 1 select 1) - 2, + (boundingBoxReal _vehicle select 0 select 2) + 2 + ] vectorAdd _offset; + }; // Spawn smoke _smoke = "#particlesource" createVehicleLocal [0, 0, 0]; @@ -50,11 +64,9 @@ if (hasInterface) then { deleteVehicle _smoke; - if (isNull _vehicle) exitWith {}; + if (isNull _vehicle || !isServer) exitWith {}; - if (isServer) then { - (_vehicle getVariable [QGVAR(engineFireJipID), ""]) call CBA_fnc_removeGlobalEventJIP; - }; + (_vehicle getVariable [QGVAR(engineFireJipID), ""]) call CBA_fnc_removeGlobalEventJIP; _vehicle setVariable [QGVAR(isEngineSmoking), false]; }; From 26f73e1a984dd081257fb58d086b1cc41e725ff9 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:48:44 +0100 Subject: [PATCH 05/27] Update fnc_detonateAmmunition.sqf --- addons/cookoff/functions/fnc_detonateAmmunition.sqf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index 3a66befa5c3..cb1d04416ff 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -49,6 +49,8 @@ _vehicleAmmo params ["_magazines", "_totalAmmo"]; if (_magazines isEqualTo [] || {_totalAmmo <= 0}) exitWith { [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; + _object setVariable [QGVAR(cookoffMagazines), nil]; + if (_destroyWhenFinished) then { _object setDamage [1, true, _killer, _instigator]; }; @@ -65,6 +67,8 @@ if (underwater _object || { !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) }) exitWith { [QGVAR(cleanupEffects), _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 From 49ca715baf9e9567d25925fe348691d916351bef Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 4 Feb 2024 10:55:09 +0100 Subject: [PATCH 06/27] Update XEH_postInit.sqf --- addons/cookoff/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index 2ae1f90c153..811dd295a97 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -86,7 +86,7 @@ if (hasInterface) then { private _distance = _object distance (positionCameraToWorld [0, 0, 0]); - TRACE_3("",_object,_sound,_maxDistance); + TRACE_2("",_object,_sound); // 3 classes of distances: close, mid and far, each having different sound files private _classDistance = switch (true) do { From 16ffa2f26c2374b4141315f2f842901fce68c82c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 4 Feb 2024 14:38:18 +0100 Subject: [PATCH 07/27] Update fnc_getVehicleAmmo.sqf --- addons/cookoff/functions/fnc_getVehicleAmmo.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf index 05e109ba162..df4385d30da 100644 --- a/addons/cookoff/functions/fnc_getVehicleAmmo.sqf +++ b/addons/cookoff/functions/fnc_getVehicleAmmo.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: PabstMirror - * Gets all magazines inside of a vehicle. + * Gets all magazines inside of an object. * * Arguments: * 0: Object From 0de629ec2e27a636444710f03361dde2d24719a1 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 5 Feb 2024 13:28:13 +0100 Subject: [PATCH 08/27] Update events-framework.md --- docs/wiki/framework/events-framework.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wiki/framework/events-framework.md b/docs/wiki/framework/events-framework.md index f4edcbad4c1..bf20842db00 100644 --- a/docs/wiki/framework/events-framework.md +++ b/docs/wiki/framework/events-framework.md @@ -112,7 +112,7 @@ MenuType: 0 = Interaction, 1 = Self Interaction |----------|---------|---------|---------|---------|---------| |`ace_cookoff_cookOff` | [_vehicle, _intensity, _instigator, _smokeDelayEnabled, _ammoDetonationChance, _detonateAfterCookoff, _fireSource, _canRing, _maxIntensity, _canJet] | Server | Callable | Start vehicle cook-off |`ace_cookoff_cookOffBox` | [_box, _killer, _instigator] | Server | Callable | Start ammo box cook-off -|`ace_cookoff_detonateAmmunition` | [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator, _initialDelay"] | Server | Callable | Start ammo detonation +|`ace_cookoff_detonateAmmunition` | [_object, _destroyWhenFinished, _killer, _instigator, _initialDelay"] | Server | Callable | Start ammo detonation |`ace_cookoff_engineFire` | _vehicle | Server | Callable | Start engine fire From ed4cea6c4a11fde0f53e4fc619ff1108c8669aab Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:31:27 +0100 Subject: [PATCH 09/27] Various improvements --- addons/cookoff/XEH_postInit.sqf | 30 ++----- addons/cookoff/functions/fnc_cookOff.sqf | 38 +++++---- addons/cookoff/functions/fnc_cookOffBox.sqf | 9 +- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 85 +++++++------------ .../cookoff/functions/fnc_cookOffEffect.sqf | 19 +++-- .../cookoff/functions/fnc_engineFireLocal.sqf | 14 ++- addons/cookoff/script_component.hpp | 8 +- addons/grenades/functions/fnc_incendiary.sqf | 2 +- .../functions/fnc_handleCookoff.sqf | 3 +- 9 files changed, 90 insertions(+), 118 deletions(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index 811dd295a97..b8a9523496e 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -1,12 +1,12 @@ #include "script_component.hpp" -[QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler; [QGVAR(cookOffBoxLocal), LINKFUNC(cookOffBoxLocal)] call CBA_fnc_addEventHandler; [QGVAR(cookOffEffect), LINKFUNC(cookOffEffect)] call CBA_fnc_addEventHandler; [QGVAR(engineFireLocal), LINKFUNC(engineFireLocal)] call CBA_fnc_addEventHandler; [QGVAR(smoke), LINKFUNC(smoke)] call CBA_fnc_addEventHandler; if (isServer) then { + [QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler; [QGVAR(cookOffBox), LINKFUNC(cookOffBox)] call CBA_fnc_addEventHandler; [QGVAR(engineFire), LINKFUNC(engineFire)] call CBA_fnc_addEventHandler; [QGVAR(detonateAmmunition), LINKFUNC(detonateAmmunition)] call CBA_fnc_addEventHandler; @@ -14,9 +14,6 @@ if (isServer) then { // Handle cleaning up effects when vehicle is deleted mid cook-off [QGVAR(addCleanupHandlers), { - // No effects on machines without interfaces - if (!hasInterface) exitWith {}; - params ["_object"]; // Don't add a new EH if cook-off is run multiple times @@ -30,33 +27,24 @@ if (isServer) then { }] call CBA_fnc_addEventHandler; [QGVAR(cleanupEffects), { - params ["_object", ["_effects", []]]; + params ["_object"]; if (isServer) then { - // Reset, so that object can cook-off again + // Reset, so that the object can cook-off again _object setVariable [QGVAR(isCookingOff), nil, true]; // Remove effects from JIP - private _jipID = _object getVariable QGVAR(jipID); - - if (isNil "_jipID") exitWith {}; - - _jipID call CBA_fnc_removeGlobalEventJIP; + { + _x call CBA_fnc_removeGlobalEventJIP; + } forEach (_object getVariable [QGVAR(jipIDs), []]); - _object setVariable [QGVAR(jipID), nil]; + _object setVariable [QGVAR(jipIDs), nil]; }; - // No effects on machines without interfaces - if (!hasInterface) exitWith {}; - - // All effects are local - _effects append (_object getVariable [QGVAR(effects), []]); - - if (_effects isEqualTo []) exitWith {}; - + // All effects are local (apart from sound, which is global, but is handled by server) { deleteVehicle _x; - } forEach _effects; + } forEach (_object getVariable [QGVAR(effects), []]); _object setVariable [QGVAR(effects), nil]; }] call CBA_fnc_addEventHandler; diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 46fe4f9a3d2..f278cb51ce7 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -13,8 +13,8 @@ * 5: Detonate after cook-off (default: false) * 6: Selection for fire source (default: "") * 7: Can spawn fire ring (default: true) - * 8: Maximum intensity (default: MAX_COOKOFF_INTENSITY) - * 9: Can spawn fire jet (default: true) + * 8: Can spawn fire jet (default: true) + * 9: Maximum intensity (default: MAX_COOKOFF_INTENSITY) * * Return Value: * None @@ -37,8 +37,8 @@ params [ ["_detonateAfterCookoff", false], ["_fireSource", ""], ["_canRing", true], - ["_maxIntensity", MAX_COOKOFF_INTENSITY, [0]], - ["_canJet", true, [true]] + ["_canJet", true], + ["_maxIntensity", MAX_COOKOFF_INTENSITY] ]; // Check if cook-off is disabled on vehicle specifically @@ -54,6 +54,9 @@ 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; @@ -73,9 +76,12 @@ if (_positions isEqualTo []) then { }; }; +// Not guaranteed to be active/used, but reserve it nonetheless +private _fireJipID = format [QGVAR(cookOffEffect_%1), hashValue _vehicle]; + // Spawn smoke -private _jipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP; -_vehicle setVariable [QGVAR(jipID), _jipID]; +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]; @@ -83,23 +89,23 @@ _vehicle setVariable [QGVAR(intensity), _intensity]; private _delay = 0; if (_delayBetweenSmokeAndFire) then { - _delay = SMOKE_TIME + random SMOKE_TIME; + _delay = random [SMOKE_DELAY, 1.5 * SMOKE_DELAY, 2 * SMOKE_DELAY]; }; [{ [{ - (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"]; + (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_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; + (_this select 1) call CBA_fnc_removePerFrameHandler; // Effects are deleted when vehicle is deleted if (isNull _vehicle) exitWith {}; - // Remove effects globally - [QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent; + // Remove effects on server + [QGVAR(cleanupEffects), _vehicle] call CBA_fnc_localEvent; if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then { _vehicle setDamage [1, true, _instigator, _instigator]; // because it's running on the server, killer and instigator can be set @@ -118,19 +124,19 @@ if (_delayBetweenSmokeAndFire) then { }; }; - private _time = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME; + private _duration = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME; if (_fireSource isEqualTo "") then { _fireSource = selectRandom _positions; }; - // As the cook-off effect is max 20s, this is not synced with JIP players - [QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _time, _fireSource, _intensity]] call CBA_fnc_globalEvent; + // Sync for JIP players + [QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _fireSource, _intensity, CBA_missionTime, _duration], _fireJipID] call CBA_fnc_globalEventJIP; _intensity = _intensity - (0.5 max random 1) / GVAR(cookoffDuration); _vehicle setVariable [QGVAR(intensity), _intensity]; - _vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _time + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)]; + _vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _duration + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)]; // If there are any crew, burn them if (["ace_fire"] call EFUNC(common,isModLoaded)) then { @@ -150,4 +156,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], _delay] call CBA_fnc_waitAndExecute; +}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _fireJipID], _delay] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index 0a1d92944f5..cfea21dd3e3 100644 --- a/addons/cookoff/functions/fnc_cookOffBox.sqf +++ b/addons/cookoff/functions/fnc_cookOffBox.sqf @@ -5,6 +5,8 @@ * * Arguments: * 0: Ammo box + * 1: Killer (default: objNull) + * 2: Instigator (default: objNull) * * Return Value: * None @@ -17,7 +19,7 @@ if (!isServer) exitWith {}; -params ["_box", "_killer", "_instigator"]; +params ["_box", ["_killer", objNull], ["_instigator", objNull]]; if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; @@ -29,10 +31,9 @@ private _jipID = [QGVAR(cookOffBoxLocal), [ _killer, _instigator, CBA_missionTime, - random [IGNITE_TIME / 2, IGNITE_TIME, IGNITE_TIME / 2 * 3], // generate random timers that are global - random [SMOKE_TIME / 2, SMOKE_TIME, SMOKE_TIME / 2 * 3] + random [SMOKE_DELAY / 2, SMOKE_DELAY, SMOKE_DELAY / 2 * 3] // generate random timer that is global synced ]] call CBA_fnc_globalEventJIP; [_jipID, _box] call CBA_fnc_removeGlobalEventJIP; -_box setVariable [QGVAR(jipID), _jipID]; +_box setVariable [QGVAR(jipIDs), [_jipID]]; diff --git a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf index 499e5f2a706..e0510905c23 100644 --- a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf +++ b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf @@ -1,78 +1,53 @@ #include "..\script_component.hpp" /* * Author: KoffeinFlummi, commy2, kymckay, johnb43 - * Start a cook-off in the given ammo box. + * Spawns local cook-off effects for ammo boxes. * * Arguments: - * 0: Ammo box + * 0: Box + * 1: Killer + * 2: Instigator + * 3: Start time of the cook-off + * 4: Smoke delay * * Return Value: * None * * Example: - * cursorObject call ace_cookoff_fnc_cookOffBox + * [cursorObject, player, player, CBA_missionTime, 10, 60] call ace_cookoff_fnc_cookOffBoxLocal * * Public: No */ -params ["_box", "_killer", "_instigator", "_startTime", "_igniteTime", "_smokeTime"]; +params ["", "", "", "_startTime", "_smokeDelay"]; -// Make sure effects are cleaned up if box is deleted -[QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent; +[{ + params ["_box", "_killer", "_instigator"]; -// These time checks are for JIP players -private _delay = _startTime - CBA_missionTime + _igniteTime; + // Make sure effects are cleaned up if box is deleted + [QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent; -if (_delay >= 0) then { - [{ - params ["_box"]; + private _boxPos = ASLToAGL getPosASL _box; + private _effects = []; - private _effects = []; + // Box will start smoking + if (hasInterface) then { + private _smoke = createVehicleLocal ["#particlesource", _boxPos, [], 0, "CAN_COLLIDE"]; + _smoke setParticleClass "AmmoSmokeParticles2"; + _smoke attachTo [_box]; - // Box will start smoking - if (hasInterface) then { - private _smoke = "#particlesource" createVehicleLocal [0, 0, 0]; - _smoke setParticleClass "AmmoSmokeParticles2"; - _smoke attachTo [_box, [0, 0, 0]]; + _effects pushBack _smoke; + }; - _effects pushBack _smoke; - }; + if (isServer) then { + private _sound = createSoundSource ["Sound_Fire", _boxPos, [], 0]; + _sound attachTo [_box]; - if (isServer) then { - private _sound = createSoundSource ["Sound_Fire", ASLToAGL getPosASL _box, [], 0]; - _smoke attachTo [_sound]; - - _effects pushBack _sound; - }; - - _box setVariable [QGVAR(effects), _effects]; - }, _box, _delay] call CBA_fnc_waitAndExecute; -}; - -// Smoke happens later -_delay = _delay + _smokeTime; - -if (_delay >= 0) then { - // Light the fire (also handles lighting) - [{ - params ["_box", "_killer", "_instigator"]; - - if (hasInterface) then { - private _fire = "#particlesource" createVehicleLocal [0, 0, 0]; - - _fire setParticleClass "AmmoBulletCore"; - _fire attachTo [_box, [0, 0, 0]]; - - private _effects = _box getVariable [QGVAR(effects), []]; - - _effects pushBack _fire; - - _box setVariable [QGVAR(effects), _effects]; - }; + _effects pushBack _sound; // Detonate the ammunition - if (isServer) then { - [QGVAR(detonateAmmunition), [_box, true, _killer, _instigator]] call CBA_fnc_localEvent; - }; - }, _this, _delay] call CBA_fnc_waitAndExecute; -}; + [QGVAR(detonateAmmunition), [_box, true, _killer, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent; + }; + + _box setVariable [QGVAR(effects), _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_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index 0447959a598..6f8bd84e04c 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -7,15 +7,16 @@ * 0: Vehicle * 1: Spawn fire jet * 2: Spawn fire ring - * 3: Duration of effect (max 20 seconds) - * 4: What selection will fire originate from - * 5: Cookoff intensity value + * 3: What selection fire will originate from + * 4: Cookoff intensity value + * 5: Start time + * 6: Duration of effect (max 20 seconds) * * Return Value: * None * * Example: - * [vehicle player, true, false, 15, "commander_turret"] call ace_cookoff_fnc_cookOffEffect + * [vehicle player, true, false, "commander_turret", 6, CBA_missionTime, 15] call ace_cookoff_fnc_cookOffEffect * * Public: No */ @@ -23,7 +24,7 @@ #define FLAME_SIZE 1.5 #define FIRE_INTENSITY 6 -params ["_vehicle", "_jet", "_ring", "_duration", "_fireSelection", "_intensity"]; +params ["_vehicle", "_jet", "_ring", "_fireSelection", "_intensity", "_startTime", "_duration"]; // Spawn light private _light = objNull; @@ -51,20 +52,20 @@ if (isServer) then { // Make the ring a source of fire if (_ring && {["ace_fire"] call EFUNC(common,isModLoaded)}) then { - _fireKey = format [QGVAR(%1), hashValue _vehicle]; + _fireKey = format [QGVAR(cookoffFire_%1), hashValue _vehicle]; [QEGVAR(fire,addFireSource), [_vehicle, FLAME_SIZE * ((boundingBoxReal _vehicle) select 2), FIRE_INTENSITY, _fireKey]] call CBA_fnc_localEvent; }; }; [{ - (_this select 0) params ["_vehicle", "_jet", "_ring", "_duration", "_startTime", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"]; + (_this select 0) params ["_vehicle", "_jet", "_ring", "_startTime", "_duration", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"]; private _elapsedTime = CBA_missionTime - _startTime; // Clean up effects once effects have finished or vehicle has been deleted if (isNull _vehicle || {_elapsedTime >= _duration}) exitWith { - [_this select 1] call CBA_fnc_removePerFrameHandler; + (_this select 1) call CBA_fnc_removePerFrameHandler; deleteVehicle _light; @@ -222,4 +223,4 @@ if (isServer) then { (_tiWheels + _intensity * 0.004) / 1.002, // wheels//tracks are further away from burning parts (_tiWeapon + _intensity * 0.01) / 1.005 ]; -}, 0, [_vehicle, _jet, _ring, _duration, CBA_missionTime, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler; +}, 0, [_vehicle, _jet, _ring, _startTime, _duration, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/cookoff/functions/fnc_engineFireLocal.sqf b/addons/cookoff/functions/fnc_engineFireLocal.sqf index 625a6d3fe9c..65d1670ed26 100644 --- a/addons/cookoff/functions/fnc_engineFireLocal.sqf +++ b/addons/cookoff/functions/fnc_engineFireLocal.sqf @@ -51,7 +51,7 @@ if (hasInterface) then { }; // Spawn smoke - _smoke = "#particlesource" createVehicleLocal [0, 0, 0]; + _smoke = createVehicleLocal ["#particlesource", ASLToAGL getPosASL _vehicle, [], 0, "CAN_COLLIDE"];; _smoke setParticleClass "ObjectDestructionSmoke1_2Smallx"; _smoke attachTo [_vehicle, _position]; }; @@ -60,14 +60,20 @@ if (hasInterface) then { (_this select 0) params ["_vehicle", "_smoke", "_endTime"]; if (!alive _vehicle || {_vehicle getHitPointDamage "HitEngine" < 0.9} || {CBA_missionTime >= _endTime}) exitWith { - [_this select 1] call CBA_fnc_removePerFrameHandler; + (_this select 1) call CBA_fnc_removePerFrameHandler; deleteVehicle _smoke; if (isNull _vehicle || !isServer) exitWith {}; - (_vehicle getVariable [QGVAR(engineFireJipID), ""]) call CBA_fnc_removeGlobalEventJIP; + _vehicle setVariable [QGVAR(isEngineSmoking), nil]; - _vehicle setVariable [QGVAR(isEngineSmoking), false]; + private _jipID = _vehicle getVariable QGVAR(engineFireJipID); + + if (isNil "_jipID") exitWith {}; + + _jipID call CBA_fnc_removeGlobalEventJIP; + + _vehicle setVariable [QGVAR(engineFireJipID), nil]; }; }, 5, [_vehicle, _smoke, _endTime]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/cookoff/script_component.hpp b/addons/cookoff/script_component.hpp index 3e819845159..7c812cd84b0 100644 --- a/addons/cookoff/script_component.hpp +++ b/addons/cookoff/script_component.hpp @@ -20,10 +20,9 @@ // Stages of cookoff in order (in seconds) // Should be no un-synced randomness in these as the effects must be ran on each client -#define IGNITE_TIME 3 -#define SMOKE_TIME 10.5 +#define SMOKE_DELAY 10.5 +#define DETONATION_DELAY 3 #define COOKOFF_TIME 14 // Cook off time should be 20s at most due to length of sound files -#define COOKOFF_TIME_BOX 82.5 // Cook off time for boxes should be significant to allow time for ammo to burn #define ENGINE_FIRE_TIME 240 #define MIN_TIME_BETWEEN_FLAMES 5 #define MAX_TIME_BETWEEN_FLAMES 15 @@ -33,9 +32,6 @@ #define MIN_AMMO_DETONATION_START_DELAY 1 // Min time to wait before a vehicle's ammo starts to cookoff #define MAX_AMMO_DETONATION_START_DELAY 6 // Max time to wait before a vehicle's ammo starts to cookoff -// Delay between flame effect for players in a cooking off vehicle -#define FLAME_EFFECT_DELAY 0.4 - // Common commander hatch defines for default vehicles #define DEFAULT_COMMANDER_HATCHES ["osa_poklop_commander", "hatch_commander_axis"] diff --git a/addons/grenades/functions/fnc_incendiary.sqf b/addons/grenades/functions/fnc_incendiary.sqf index e1e27325764..77cf8153a46 100644 --- a/addons/grenades/functions/fnc_incendiary.sqf +++ b/addons/grenades/functions/fnc_incendiary.sqf @@ -180,7 +180,7 @@ if (isServer) then { {EGVAR(cookoff,ammoCookoffDuration) != 0} && {_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]} ) then { - [QEGVAR(cookOff,cookOffBox), [_box, objNull, objNull]] call CBA_fnc_serverEvent; + [QEGVAR(cookOff,cookOffBox), _box] call CBA_fnc_serverEvent; } else { _x setDamage 1; }; diff --git a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf index 26823f24933..5ff4d0e8f2e 100644 --- a/addons/vehicle_damage/functions/fnc_handleCookoff.sqf +++ b/addons/vehicle_damage/functions/fnc_handleCookoff.sqf @@ -47,8 +47,7 @@ if (_chanceOfFire >= random 1) exitWith { _source = ["hit_engine_point", "HitPoints"]; }; - // sending nil for _maxIntensity (9th param) to use default value in ace_cookoff_fnc_cookOff - [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, nil, _canJet]] call CBA_fnc_serverEvent; + [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _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); From 51aa46c81fc0da75485e555e844342b0a77e0b69 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 6 Feb 2024 01:06:30 +0100 Subject: [PATCH 10/27] Separate effect handling --- addons/cookoff/XEH_postInit.sqf | 46 +++++++++---------- addons/cookoff/functions/fnc_cookOff.sqf | 40 ++++++++-------- addons/cookoff/functions/fnc_cookOffBox.sqf | 9 ++-- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 12 ++--- .../functions/fnc_detonateAmmunition.sqf | 14 +++--- .../cookoff/functions/fnc_handleDamageBox.sqf | 24 ++-------- addons/cookoff/functions/fnc_smoke.sqf | 9 ++-- .../functions/fnc_handleCookoff.sqf | 2 +- 8 files changed, 71 insertions(+), 85 deletions(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index b8a9523496e..a0da68bfb96 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 {}; +// Handle cleaning up effects when objects are deleted mid cook-off +["AllVehicles", "Deleted", { + { + deleteVehicle _x; + } forEach ((_this select 0) getVariable [QGVAR(vehicleEffects), []]); +}, nil, nil, true] call CBA_fnc_addClassEventHandler; - _object setVariable [QGVAR(deletedEH), - _object addEventHandler ["Deleted", { - [QGVAR(cleanupEffects), _this select 0] call CBA_fnc_localEvent; - }] - ]; -}] call CBA_fnc_addEventHandler; +["ReammoBox_F", "Deleted", { + { + deleteVehicle _x; + } forEach ((_this select 0) getVariable [QGVAR(boxEffects), []]); +}, nil, nil, true] call CBA_fnc_addClassEventHandler; -[QGVAR(cleanupEffects), { +[QGVAR(cleanupVehicleEffects), { params ["_object"]; - if (isServer) then { - // Reset, so that the object can cook-off again - _object setVariable [QGVAR(isCookingOff), nil, true]; + { + deleteVehicle _x; + } forEach (_object getVariable [QGVAR(vehicleEffects), []]); - // Remove effects from JIP - { - _x call CBA_fnc_removeGlobalEventJIP; - } forEach (_object getVariable [QGVAR(jipIDs), []]); + _object setVariable [QGVAR(vehicleEffects), nil]; +}] call CBA_fnc_addEventHandler; - _object setVariable [QGVAR(jipIDs), nil]; - }; +[QGVAR(cleanupBoxEffects), { + params ["_object"]; - // All effects are local (apart from sound, which is global, but is handled by server) { deleteVehicle _x; - } forEach (_object getVariable [QGVAR(effects), []]); + } forEach (_object getVariable [QGVAR(boxEffects), []]); - _object setVariable [QGVAR(effects), nil]; + _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 f278cb51ce7..61a6631a8bd 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 cfea21dd3e3..564762ab871 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 e0510905c23..9b8435c0071 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 b428183cb3d..6ef74e277f5 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 2f76ef9c772..b7ac629613b 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 6ff2726fa1b..f060a98f613 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 5ff4d0e8f2e..e1f0e7799d1 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); From d277fa9f678a2313eede620feb8de600ec1bbbc0 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:32:13 +0100 Subject: [PATCH 11/27] Tweaks --- addons/cookoff/XEH_postInit.sqf | 20 ++++++++++++++------ addons/cookoff/functions/fnc_cookOff.sqf | 3 +++ addons/cookoff/functions/fnc_cookOffBox.sqf | 6 +++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index a0da68bfb96..ce4dac75db6 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -17,13 +17,13 @@ if (isServer) then { { deleteVehicle _x; } forEach ((_this select 0) getVariable [QGVAR(vehicleEffects), []]); -}, nil, nil, true] call CBA_fnc_addClassEventHandler; +}, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; ["ReammoBox_F", "Deleted", { { deleteVehicle _x; } forEach ((_this select 0) getVariable [QGVAR(boxEffects), []]); -}, nil, nil, true] call CBA_fnc_addClassEventHandler; +}, true, [], true] call CBA_fnc_addClassEventHandler; [QGVAR(cleanupVehicleEffects), { params ["_object"]; @@ -45,21 +45,29 @@ if (isServer) then { _object setVariable [QGVAR(boxEffects), nil]; }] call CBA_fnc_addEventHandler; +// Ammo box damage handling ["ReammoBox_F", "init", { // Calling this function inside curly brackets allows the usage of "exitWith", which would be broken with "HandleDamage" otherwise (_this select 0) addEventHandler ["HandleDamage", {_this call FUNC(handleDamageBox)}]; -}, nil, nil, true] call CBA_fnc_addClassEventHandler; +}, true, [], true] call CBA_fnc_addClassEventHandler; -// Secondary explosions +// Vehicle ammo cook-off (secondary explosions) ["AllVehicles", "Killed", { if (!GVAR(enableAmmoCookoff) || {GVAR(ammoCookoffDuration) == 0}) exitWith {}; params ["_vehicle", "", "", "_useEffects"]; if (_useEffects && {_vehicle getVariable [QGVAR(enableAmmoCookoff), true]}) then { - [QGVAR(detonateAmmunition), [_vehicle, false, objNull, objNull, (random MAX_AMMO_DETONATION_START_DELAY) max MIN_AMMO_DETONATION_START_DELAY]] call CBA_fnc_serverEvent; + // We don't need to pass source and instigator, as vehicle is already dead + [QGVAR(detonateAmmunition), [ + _vehicle, + false, + objNull, + objNull, + random [MIN_AMMO_DETONATION_START_DELAY, (MIN_AMMO_DETONATION_START_DELAY + MAX_AMMO_DETONATION_START_DELAY) / 2, MAX_AMMO_DETONATION_START_DELAY] + ] call CBA_fnc_serverEvent; }; -}, nil, ["CAManBase", "StaticWeapon"]] call CBA_fnc_addClassEventHandler; +}, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; if (hasInterface) then { // Plays a sound locally, so that different sounds can be used for various distances diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 61a6631a8bd..cf6e5db616a 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -43,8 +43,11 @@ params [ ["_maxIntensity", MAX_COOKOFF_INTENSITY] ]; +// Make sure it's a vehicle (important, because deleted EH is assigned to AllVehicles only in postInit) if !(_vehicle isKindOf "AllVehicles") exitWith {}; +if (_vehicle isKindOf "CAManBase" || {_vehicle isKindOf "StaticWeapon"}) exitWith {}; + // Check if cook-off is disabled on vehicle specifically if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index 564762ab871..4fbc6b66b5a 100644 --- a/addons/cookoff/functions/fnc_cookOffBox.sqf +++ b/addons/cookoff/functions/fnc_cookOffBox.sqf @@ -18,12 +18,16 @@ */ if (!isServer) exitWith {}; +if (!GVAR(enableAmmobox) || {GVAR(ammoCookoffDuration) == 0}) exitWith {}; params ["_box", ["_source", objNull], ["_instigator", objNull]]; -// Make sure it's a box +// Make sure it's a box (important, because deleted EH is assigned to ReammoBox_F only in postInit) if !(_box isKindOf "ReammoBox_F") exitWith {}; +if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {}; + +// Allow only 1 cook-off per box at a time if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; _box setVariable [QGVAR(isCookingOff), true, true]; From 2646cc12ce969b34385c23a0bd024d3c0ad9d83f Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:36:18 +0100 Subject: [PATCH 12/27] Update XEH_postInit.sqf --- addons/cookoff/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index ce4dac75db6..673fbac963a 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -65,7 +65,7 @@ if (isServer) then { objNull, objNull, random [MIN_AMMO_DETONATION_START_DELAY, (MIN_AMMO_DETONATION_START_DELAY + MAX_AMMO_DETONATION_START_DELAY) / 2, MAX_AMMO_DETONATION_START_DELAY] - ] call CBA_fnc_serverEvent; + ]] call CBA_fnc_serverEvent; }; }, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; From 0deada7a3dcdd3fd28a0d69f9601126a0500c523 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:58:59 +0100 Subject: [PATCH 13/27] Prevent double ammo detonation --- addons/common/XEH_postInit.sqf | 1 + addons/cookoff/XEH_PREP.hpp | 1 + .../functions/fnc_detonateAmmunition.sqf | 180 ++---------------- .../fnc_detonateAmmunitionServer.sqf | 171 +++++++++++++++++ 4 files changed, 187 insertions(+), 166 deletions(-) create mode 100644 addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf index af4b33d49b8..d31ad129913 100644 --- a/addons/common/XEH_postInit.sqf +++ b/addons/common/XEH_postInit.sqf @@ -192,6 +192,7 @@ if (isServer) then { [QGVAR(switchMove), {(_this select 0) switchMove (_this select 1)}] call CBA_fnc_addEventHandler; [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(removeMagazinesTurret), {(_this select 0) removeMagazinesTurret [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler; [QGVAR(setVanillaHitPointDamage), { params ["_object", "_hitPointAnddamage"]; diff --git a/addons/cookoff/XEH_PREP.hpp b/addons/cookoff/XEH_PREP.hpp index 3dc602be705..dfc3b7b130d 100644 --- a/addons/cookoff/XEH_PREP.hpp +++ b/addons/cookoff/XEH_PREP.hpp @@ -3,6 +3,7 @@ PREP(cookOffBox); PREP(cookOffBoxLocal); PREP(cookOffEffect); PREP(detonateAmmunition); +PREP(detonateAmmunitionServer); PREP(engineFire); PREP(engineFireLocal); PREP(getVehicleAmmo); diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index 6ef74e277f5..6bc3744f66c 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* - * Author: Glowbal, johnb43 - * Detonates ammunition from an object (e.g. vehicle or crate) until no ammo is left. + * Author: johnb43 + * Starts ammunition detonating from an object. * * Arguments: * 0: Object @@ -11,7 +11,7 @@ * 4: Initial delay (default: 0) * * Return Value: - * Nothing Useful + * None * * Example: * [cursorObject] call ace_cookoff_fnc_detonateAmmunition @@ -25,171 +25,19 @@ params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_ins if (isNull _object) exitWith {}; -private _objectAmmo = _object getVariable QGVAR(cookoffMagazines); +// Don't have an object detonate its ammo twice +if (!isNil {_object getVariable QGVAR(cookoffMagazines)}) exitWith {}; -if (isNil "_objectAmmo") then { - _objectAmmo = _object call FUNC(getVehicleAmmo); +_object setVariable [QGVAR(cookoffMagazines), _object call FUNC(getVehicleAmmo)]; - _object setVariable [QGVAR(cookoffMagazines), _objectAmmo]; +// 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; - // 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; - - { - _object removeMagazinesTurret [_x select 0, _x select 1]; - } forEach (magazinesAllTurrets _object); - }; -}; - -_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(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; - - _object setVariable [QGVAR(cookoffMagazines), nil]; - - if (_destroyWhenFinished) then { - _object setDamage [1, true, _source, _instigator]; - }; -}; - -// If the cook-off is interrupted or disabled, clean up the effects -if (underwater _object || { - if (GVAR(ammoCookoffDuration) == 0) exitWith {true}; - - if (_object isKindOf "ReammoBox_F") exitWith { - !(GVAR(enableAmmobox) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) - }; - - !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) -}) exitWith { - [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, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; -}; - -private _magazineIndex = floor random (count _magazines); -private _magazine = _magazines select _magazineIndex; -_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile"]; - -// 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; -} else { - _magazine set [1, _ammoCount]; // remove ammo that was detonated + { + [QEGVAR(common,removeMagazinesTurret), [_object, _x select 0, _x select 1], _object, _x select 1] call CBA_fnc_turretEvent; + } forEach (magazinesAllTurrets _object); }; -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]]; - -// Detonate the remaining ammo after a delay -[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; -private _ammo = getText (_configMagazine >> "ammo"); -private _configAmmo = configFile >> "CfgAmmo" >> _ammo; - -private _simType = toLower getText (_configAmmo >> "simulation"); -private _speed = linearConversion [0, 1, random 1, 1, 20, true]; -private _effect2pos = _object selectionPosition "destructionEffect2"; - -// Spawns the projectiles, making them either fly in random directions or explode -private _fnc_spawnProjectile = { - // If the magazines are inside of the cargo (inventory), don't let their projectiles escape the interior of the vehicle - if (!_spawnProjectile) exitWith {}; - - params ["_object", "_ammo", "_speed", "_flyAway"]; - - private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3]; - - if (_spawnPos select 2 < 0) then { - _spawnPos set [2, 0]; - }; - - private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"]; - - if (_flyAway) then { - private _vectorAmmo = [-1 + random 2, -1 + random 2, -0.2 + random 1]; - private _vectorVelocity = _vectorAmmo vectorMultiply _speed; - - _projectile setVectorDir _vectorVelocity; - _projectile setVelocity _vectorVelocity; - } else { - _projectile setDamage 1; - }; -}; - -switch (_simType) do { - case "shotbullet": { - [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; - - if (random 1 < 0.6) then { - [_object, _ammo, _speed, true] call _fnc_spawnProjectile; - }; - }; - case "shotshell": { - [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; - - if (random 1 < 0.15) then { - [_object, _ammo, _speed, true] call _fnc_spawnProjectile; - }; - }; - case "shotgrenade": { - if (random 1 < 0.9) then { - _speed = 0; - }; - - [_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile; - }; - case "shotrocket"; - case "shotmissile"; - case "shotsubmunitions": { - if (random 1 < 0.1) then { - [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; - - [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; - } else { - createVehicle ["ACE_ammoExplosionLarge", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; - }; - }; - case "shotdirectionalbomb"; - case "shotmine": { - if (random 1 < 0.5) then { - // Not all explosives detonate on destruction, some have scripted alternatives - if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then { - _ammo = getText (_configAmmo >> QEGVAR(explosives,explosive)); - }; - - // If a scripted alternative doesn't exist use generic explosion - if (_ammo != "") then { - [_object, _ammo, 0, false] call _fnc_spawnProjectile; - } else { - createVehicle ["SmallSecondary", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; - }; - }; - }; - case "shotilluminating": { - if (random 1 < 0.15) then { - [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; - }; - }; -}; +[FUNC(detonateAmmunitionServer), [_object, _destroyWhenFinished, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf new file mode 100644 index 00000000000..25bb4e43a56 --- /dev/null +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf @@ -0,0 +1,171 @@ +#include "..\script_component.hpp" +/* + * Author: Glowbal, johnb43 + * Detonates ammunition from an object (e.g. vehicle or crate) until no ammo is left. + * + * Arguments: + * 0: Object + * 1: Destroy when finished + * 2: Source + * 3: Instigator + * + * Return Value: + * Nothing Useful + * + * Example: + * [cursorObject, true, player, player] call ace_cookoff_fnc_detonateAmmunitionServer + * + * Public: No + */ + +if (!isServer) exitWith {}; + +params ["_object", "_destroyWhenFinished", "_source", "_instigator"]; + +if (isNull _object) exitWith {}; + +(_object getVariable QGVAR(cookoffMagazines)) params ["_magazines", "_totalAmmo"]; + +// If the cook-off has finished, clean up the effects and destroy the object +if (_magazines isEqualTo [] || {_totalAmmo <= 0}) exitWith { + [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; + + _object setVariable [QGVAR(cookoffMagazines), nil]; + + if (_destroyWhenFinished) then { + _object setDamage [1, true, _source, _instigator]; + }; +}; + +// If the cook-off is interrupted or disabled, clean up the effects +if (underwater _object || { + if (GVAR(ammoCookoffDuration) == 0) exitWith {true}; + + if (_object isKindOf "ReammoBox_F") exitWith { + !(GVAR(enableAmmobox) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) + }; + + !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) +}) exitWith { + [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; + + _object setVariable [QGVAR(cookoffMagazines), nil]; +}; + +private _magazineIndex = floor random (count _magazines); +private _magazine = _magazines select _magazineIndex; +_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile"]; + +// 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; +} else { + _magazine set [1, _ammoCount]; // 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]]; + +// Detonate the remaining ammo after a delay +[FUNC(detonateAmmunitionServer), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; + +// Get magazine info, which is used to spawn projectiles +private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; +private _ammo = getText (_configMagazine >> "ammo"); +private _configAmmo = configFile >> "CfgAmmo" >> _ammo; + +private _simType = toLower getText (_configAmmo >> "simulation"); +private _speed = linearConversion [0, 1, random 1, 1, 20, true]; +private _effect2pos = _object selectionPosition "destructionEffect2"; + +// Spawns the projectiles, making them either fly in random directions or explode +private _fnc_spawnProjectile = { + // If the magazines are inside of the cargo (inventory), don't let their projectiles escape the interior of the vehicle + if (!_spawnProjectile) exitWith {}; + + params ["_object", "_ammo", "_speed", "_flyAway"]; + + private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3]; + + if (_spawnPos select 2 < 0) then { + _spawnPos set [2, 0]; + }; + + private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"]; + + if (_flyAway) then { + private _vectorAmmo = [-1 + random 2, -1 + random 2, -0.2 + random 1]; + private _vectorVelocity = _vectorAmmo vectorMultiply _speed; + + _projectile setVectorDir _vectorVelocity; + _projectile setVelocity _vectorVelocity; + } else { + _projectile setDamage 1; + }; +}; + +switch (_simType) do { + case "shotbullet": { + [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; + + if (random 1 < 0.6) then { + [_object, _ammo, _speed, true] call _fnc_spawnProjectile; + }; + }; + case "shotshell": { + [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; + + if (random 1 < 0.15) then { + [_object, _ammo, _speed, true] call _fnc_spawnProjectile; + }; + }; + case "shotgrenade": { + if (random 1 < 0.9) then { + _speed = 0; + }; + + [_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile; + }; + case "shotrocket"; + case "shotmissile"; + case "shotsubmunitions": { + if (random 1 < 0.1) then { + [QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent; + + [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; + } else { + createVehicle ["ACE_ammoExplosionLarge", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; + }; + }; + case "shotdirectionalbomb"; + case "shotmine": { + if (random 1 < 0.5) then { + // Not all explosives detonate on destruction, some have scripted alternatives + if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then { + _ammo = getText (_configAmmo >> QEGVAR(explosives,explosive)); + }; + + // If a scripted alternative doesn't exist use generic explosion + if (_ammo != "") then { + [_object, _ammo, 0, false] call _fnc_spawnProjectile; + } else { + createVehicle ["SmallSecondary", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"]; + }; + }; + }; + case "shotilluminating": { + if (random 1 < 0.15) then { + [_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile; + }; + }; +}; From e541b337c5f41ef97a653f6b0bfb7604d25ab9ae Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:08:45 +0100 Subject: [PATCH 14/27] Fixed objects not being able to cook-off again --- addons/cookoff/XEH_postInit.sqf | 21 +++------- addons/cookoff/functions/fnc_cookOff.sqf | 5 ++- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 2 +- .../functions/fnc_detonateAmmunition.sqf | 4 +- .../fnc_detonateAmmunitionServer.sqf | 38 ++++++++++--------- addons/cookoff/functions/fnc_smoke.sqf | 2 +- .../functions/fnc_handleDetonation.sqf | 11 +++--- 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/addons/cookoff/XEH_postInit.sqf b/addons/cookoff/XEH_postInit.sqf index 673fbac963a..190232e34f8 100644 --- a/addons/cookoff/XEH_postInit.sqf +++ b/addons/cookoff/XEH_postInit.sqf @@ -16,33 +16,24 @@ if (isServer) then { ["AllVehicles", "Deleted", { { deleteVehicle _x; - } forEach ((_this select 0) getVariable [QGVAR(vehicleEffects), []]); + } forEach ((_this select 0) getVariable [QGVAR(effects), []]); }, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; ["ReammoBox_F", "Deleted", { { deleteVehicle _x; - } forEach ((_this select 0) getVariable [QGVAR(boxEffects), []]); + } forEach ((_this select 0) getVariable [QGVAR(effects), []]); }, true, [], true] call CBA_fnc_addClassEventHandler; -[QGVAR(cleanupVehicleEffects), { +// Raised when the flames have subsided or after the ammo of a box has finished cooking off +[QGVAR(cleanupEffects), { params ["_object"]; { deleteVehicle _x; - } forEach (_object getVariable [QGVAR(vehicleEffects), []]); + } forEach (_object getVariable [QGVAR(effects), []]); - _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]; + _object setVariable [QGVAR(effects), nil]; }] call CBA_fnc_addEventHandler; // Ammo box damage handling diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index cf6e5db616a..215cfd1c928 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -112,7 +112,10 @@ if (_delayBetweenSmokeAndFire) then { if (isNull _vehicle) exitWith {}; // Remove effects - [QGVAR(cleanupVehicleEffects), _vehicle] call CBA_fnc_globalEvent; + [QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent; + + // Reset variable, so it can cook-off again + _vehicle setVariable [QGVAR(isCookingOff), nil, true]; if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then { _vehicle setDamage [1, true, _source, _instigator]; // because it's running on the server, killer and instigator can be set diff --git a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf index 9b8435c0071..804efa5f8ab 100644 --- a/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf +++ b/addons/cookoff/functions/fnc_cookOffBoxLocal.sqf @@ -49,5 +49,5 @@ params ["", "", "", "_startTime", "_smokeDelay"]; [QGVAR(detonateAmmunition), [_box, true, _source, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent; }; - _box setVariable [QGVAR(boxEffects), _effects]; + _box setVariable [QGVAR(effects), _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 6bc3744f66c..e6186ccedcc 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -26,7 +26,9 @@ params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_ins if (isNull _object) exitWith {}; // Don't have an object detonate its ammo twice -if (!isNil {_object getVariable QGVAR(cookoffMagazines)}) exitWith {}; +if (_object getVariable [QGVAR(isAmmoDetonating), false]) exitWith {}; + +_object setVariable [QGVAR(isAmmoDetonating), true, true]; _object setVariable [QGVAR(cookoffMagazines), _object call FUNC(getVehicleAmmo)]; diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf index 25bb4e43a56..2e3d56bb7e2 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf @@ -10,7 +10,7 @@ * 3: Instigator * * Return Value: - * Nothing Useful + * None * * Example: * [cursorObject, true, player, player] call ace_cookoff_fnc_detonateAmmunitionServer @@ -26,19 +26,11 @@ if (isNull _object) exitWith {}; (_object getVariable QGVAR(cookoffMagazines)) params ["_magazines", "_totalAmmo"]; -// If the cook-off has finished, clean up the effects and destroy the object -if (_magazines isEqualTo [] || {_totalAmmo <= 0}) exitWith { - [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; +private _hasFinished = _totalAmmo <= 0 || {_magazines isEqualTo []}; - _object setVariable [QGVAR(cookoffMagazines), nil]; - - if (_destroyWhenFinished) then { - _object setDamage [1, true, _source, _instigator]; - }; -}; - -// If the cook-off is interrupted or disabled, clean up the effects -if (underwater _object || { +// If the cook-off has finished or been interrupted, clean up the effects for boxes (no vehicle effects) +if (_hasFinished || + {underwater _object} || { if (GVAR(ammoCookoffDuration) == 0) exitWith {true}; if (_object isKindOf "ReammoBox_F") exitWith { @@ -47,9 +39,21 @@ if (underwater _object || { !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) }) exitWith { - [QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent; + if (_object isKindOf "ReammoBox_F") then { + [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; + + // Reset variable, so the box can cook-off again + _object setVariable [QGVAR(isCookingOff), nil, true]; + }; + // Reset variables, so the object can detonate its ammo again _object setVariable [QGVAR(cookoffMagazines), nil]; + _object setVariable [QGVAR(isAmmoDetonating), nil, true]; + + // If done, destroy the object if necessary + if (_hasFinished && _destroyWhenFinished) then { + _object setDamage [1, true, _source, _instigator]; + }; }; private _magazineIndex = floor random (count _magazines); @@ -76,9 +80,6 @@ _totalAmmo = _totalAmmo - _removed; _object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]]; -// Detonate the remaining ammo after a delay -[FUNC(detonateAmmunitionServer), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; - // Get magazine info, which is used to spawn projectiles private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname; private _ammo = getText (_configMagazine >> "ammo"); @@ -169,3 +170,6 @@ switch (_simType) do { }; }; }; + +// Detonate the remaining ammo after a delay +[FUNC(detonateAmmunitionServer), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute; diff --git a/addons/cookoff/functions/fnc_smoke.sqf b/addons/cookoff/functions/fnc_smoke.sqf index f060a98f613..8d95719dc6a 100644 --- a/addons/cookoff/functions/fnc_smoke.sqf +++ b/addons/cookoff/functions/fnc_smoke.sqf @@ -41,4 +41,4 @@ private _effects = [_smokeBarrel]; _effects pushBack _smoke; } forEach _positions; -_vehicle setVariable [QGVAR(vehicleEffects), _effects]; +_vehicle setVariable [QGVAR(effects), _effects]; diff --git a/addons/vehicle_damage/functions/fnc_handleDetonation.sqf b/addons/vehicle_damage/functions/fnc_handleDetonation.sqf index 9556cea424d..8f317323fa7 100644 --- a/addons/vehicle_damage/functions/fnc_handleDetonation.sqf +++ b/addons/vehicle_damage/functions/fnc_handleDetonation.sqf @@ -21,18 +21,17 @@ */ params ["_vehicle", "_chanceOfDetonate", "_vehicleAmmo", "_explosiveAmmoCount", "_nonExplosiveAmmoCount", ["_injurer", objNull]]; -private _alreadyDetonating = _vehicle getVariable [QGVAR(detonating), false]; + private _isKnockedOut = _explosiveAmmoCount > 0; -if (!_alreadyDetonating && { _chanceOfDetonate >= random 1 }) exitWith { +// Ignore if the vehicle is already detonating ammo +if (_vehicle getVariable [QEGVAR(cookoff,isAmmoDetonating), false]) exitWith {_isKnockedOut}; + +if (_chanceOfDetonate >= random 1) exitWith { [_vehicle, _injurer, _vehicleAmmo] call FUNC(detonate); LOG_2("Detonating [%1] with a chance-to-detonate [%2]",_vehicle,_chanceOfDetonate); - _vehicle setVariable [QGVAR(detonating), true]; _isKnockedOut }; -// Avoid RPT spam -if (_alreadyDetonating) exitWith { _isKnockedOut }; - LOG_2("[%1] No Detonation - Chance of detonation [%2]",_vehicle,_chanceOfDetonate); false From 0663bd16c9ec42199d506b5ace7cf60229568231 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 11 Feb 2024 11:20:01 +0100 Subject: [PATCH 15/27] Added incendiary rounds as source of box cookoff --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 6 ++++-- addons/cookoff/script_component.hpp | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index b7ac629613b..bf52632fe11 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -29,8 +29,10 @@ if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {}; if !(_hitPoint == "" && {_damage > 0.5}) exitWith {}; // "" means structural damage -// Catch fire when hit by an explosive round -if (IS_EXPLOSIVE_AMMO(_ammo)) then { +private _ammoConfig = _ammo call CBA_fnc_getObjectConfig; + +// Catch fire when hit by an explosive or incendiary round +if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1}) then { [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; } else { // There is a small chance of cooking a box off if it's shot by tracer ammo diff --git a/addons/cookoff/script_component.hpp b/addons/cookoff/script_component.hpp index 7c812cd84b0..bf8fd62dd5c 100644 --- a/addons/cookoff/script_component.hpp +++ b/addons/cookoff/script_component.hpp @@ -16,10 +16,8 @@ #include "\z\ace\addons\main\script_macros.hpp" -#define IS_EXPLOSIVE_AMMO(ammo) (getNumber (ammo call CBA_fnc_getObjectConfig >> "explosive") > 0.5) - // Stages of cookoff in order (in seconds) -// Should be no un-synced randomness in these as the effects must be ran on each client +// Should be no un-synced randomness in these as the effects must be run on each client #define SMOKE_DELAY 10.5 #define DETONATION_DELAY 3 #define COOKOFF_TIME 14 // Cook off time should be 20s at most due to length of sound files From 2cdc40a958ae8f4899df5922621168a2d778cb62 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:34:58 +0100 Subject: [PATCH 16/27] Converted enable setting to bool --- addons/cookoff/CfgEden.hpp | 2 +- addons/cookoff/functions/fnc_cookOff.sqf | 20 +++++++++++++------ .../functions/fnc_detonateAmmunition.sqf | 9 +++++++++ .../fnc_detonateAmmunitionServer.sqf | 18 ++++++++--------- addons/cookoff/initSettings.inc.sqf | 4 ++-- addons/cookoff/stringtable.xml | 4 ++-- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/addons/cookoff/CfgEden.hpp b/addons/cookoff/CfgEden.hpp index 12117cae3b0..77c5e9e2812 100644 --- a/addons/cookoff/CfgEden.hpp +++ b/addons/cookoff/CfgEden.hpp @@ -11,7 +11,7 @@ class Cfg3DEN { expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]}); typeName = "BOOL"; condition = "objectVehicle"; - defaultValue = QUOTE((GETMVAR(QGVAR(enable),0)) in [ARR_2(1,2)]); + defaultValue = QUOTE(GETMVAR(QGVAR(enable),true)]); }; class GVAR(enableAmmoCookoff) { property = QGVAR(enableAmmoCookoff); diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 215cfd1c928..7c82e18deb7 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -27,7 +27,7 @@ */ if (!isServer) exitWith {}; -if (GVAR(enable) == 0 || {GVAR(cookoffDuration) == 0}) exitWith {}; +if (!GVAR(enable) || {GVAR(cookoffDuration) == 0}) exitWith {}; params [ "_vehicle", @@ -48,14 +48,15 @@ if !(_vehicle isKindOf "AllVehicles") exitWith {}; if (_vehicle isKindOf "CAManBase" || {_vehicle isKindOf "StaticWeapon"}) exitWith {}; +// If under water, ignore +// underwater is not very reliable, so use model center instead +if (underwater _vehicle || {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}) exitWith {}; + // Check if cook-off is disabled on vehicle specifically if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; -// Exit if cook-off enabled only for players and no players in vehicle crew found -if ((GVAR(enable) isEqualTo 1) && {(crew _vehicle) findIf {isPlayer _x} == -1}) exitWith {}; - TRACE_2("cooking off",_vehicle,_intensity); -TRACE_8("",_instigator,_delayBetweenSmokeAndFire,_ammoDetonationChance,_detonateAfterCookoff,_fireSource,_canRing,_maxIntensity,_canJet); +TRACE_9("",_source,_instigator,_delayBetweenSmokeAndFire,_ammoDetonationChance,_detonateAfterCookoff,_fireSource,_canRing,_canJet,_maxIntensity); if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {}; @@ -101,7 +102,14 @@ if (_delayBetweenSmokeAndFire) then { private _intensity = _vehicle getVariable [QGVAR(intensity), 0]; - if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith { + if ( + isNull _vehicle || + !GVAR(enable) || + {_intensity <= 1} || + {GVAR(cookoffDuration) == 0} || + {underwater _vehicle} || + {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0})} + ) exitWith { (_this select 1) call CBA_fnc_removePerFrameHandler; // Remove effects from JIP diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index e6186ccedcc..f2002b4b2e5 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -25,6 +25,15 @@ params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_ins if (isNull _object) exitWith {}; +// Check if the object can cook its ammo off +if ( + underwater _object || + {private _posASL = getPosWorld _object; surfaceIsWater _posASL && {(_posASL select 2) < 0}} || // underwater is not very reliable, so use model center instead + {GVAR(ammoCookoffDuration) == 0} || + {!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} || + {!(_object getVariable [QGVAR(enableAmmoCookoff), true])} +}) exitWith {}; + // Don't have an object detonate its ammo twice if (_object getVariable [QGVAR(isAmmoDetonating), false]) exitWith {}; diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf index 2e3d56bb7e2..7a5a55ebb5f 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf @@ -29,16 +29,14 @@ if (isNull _object) exitWith {}; private _hasFinished = _totalAmmo <= 0 || {_magazines isEqualTo []}; // If the cook-off has finished or been interrupted, clean up the effects for boxes (no vehicle effects) -if (_hasFinished || - {underwater _object} || { - if (GVAR(ammoCookoffDuration) == 0) exitWith {true}; - - if (_object isKindOf "ReammoBox_F") exitWith { - !(GVAR(enableAmmobox) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) - }; - - !(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]}) -}) exitWith { +if ( + _hasFinished || + {underwater _object} || + {private _posASL = getPosWorld _object; surfaceIsWater _posASL && {(_posASL select 2) < 0}} || // underwater is not very reliable, so use model center instead + {GVAR(ammoCookoffDuration) == 0} || + {!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} || + {!(_object getVariable [QGVAR(enableAmmoCookoff), true])} +) exitWith { if (_object isKindOf "ReammoBox_F") then { [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; diff --git a/addons/cookoff/initSettings.inc.sqf b/addons/cookoff/initSettings.inc.sqf index d06e1bdfab8..cfcad8c9864 100644 --- a/addons/cookoff/initSettings.inc.sqf +++ b/addons/cookoff/initSettings.inc.sqf @@ -1,9 +1,9 @@ [ QGVAR(enable), - "LIST", + "CHECKBOX", [LSTRING(enable_name), LSTRING(enable_tooltip)], LSTRING(category_displayName), - [[0, 1, 2], ["STR_A3_OPTIONS_DISABLED", ELSTRING(common,playerOnly), ELSTRING(common,playersAndAI)], 2], + true, 1, {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; diff --git a/addons/cookoff/stringtable.xml b/addons/cookoff/stringtable.xml index 51c67564f50..a49955ac2b0 100644 --- a/addons/cookoff/stringtable.xml +++ b/addons/cookoff/stringtable.xml @@ -17,10 +17,10 @@ ACE Vznícení munice - Enable vehicle cook-off + Enable vehicle cook-off effects - Enables vehicle cook-off effects (fire and sound). + Enables vehicle cook-off effects (fire and fire sound, but doesn't include ammunition detonations). Enable ammo box cook-off From bdb33d4dacf64c27b3f82325e619dfe02a65278c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:39:14 +0100 Subject: [PATCH 17/27] Fixed brackets --- addons/cookoff/functions/fnc_cookOff.sqf | 2 +- addons/cookoff/functions/fnc_detonateAmmunition.sqf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 7c82e18deb7..a3a9b2b4c13 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -108,7 +108,7 @@ if (_delayBetweenSmokeAndFire) then { {_intensity <= 1} || {GVAR(cookoffDuration) == 0} || {underwater _vehicle} || - {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0})} + {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}} ) exitWith { (_this select 1) call CBA_fnc_removePerFrameHandler; diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index f2002b4b2e5..1aa66b5b870 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -32,7 +32,7 @@ if ( {GVAR(ammoCookoffDuration) == 0} || {!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} || {!(_object getVariable [QGVAR(enableAmmoCookoff), true])} -}) exitWith {}; +) exitWith {}; // Don't have an object detonate its ammo twice if (_object getVariable [QGVAR(isAmmoDetonating), false]) exitWith {}; From 07b73c9a557ad847f359b12a75c1d13e2011eaac Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:41:58 +0100 Subject: [PATCH 18/27] Update fnc_cookOff.sqf --- addons/cookoff/functions/fnc_cookOff.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index a3a9b2b4c13..fdd4f2b2dbb 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -50,7 +50,7 @@ if (_vehicle isKindOf "CAManBase" || {_vehicle isKindOf "StaticWeapon"}) exitWit // If under water, ignore // underwater is not very reliable, so use model center instead -if (underwater _vehicle || {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}) exitWith {}; +if (underwater _vehicle || {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}}) exitWith {}; // Check if cook-off is disabled on vehicle specifically if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; From 9a7c293286588bc2c7dd2907d479bec4b48adbfc Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:44:23 +0100 Subject: [PATCH 19/27] Update CfgEden.hpp --- addons/cookoff/CfgEden.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/CfgEden.hpp b/addons/cookoff/CfgEden.hpp index 77c5e9e2812..1647bd7a6e7 100644 --- a/addons/cookoff/CfgEden.hpp +++ b/addons/cookoff/CfgEden.hpp @@ -11,7 +11,7 @@ class Cfg3DEN { expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]}); typeName = "BOOL"; condition = "objectVehicle"; - defaultValue = QUOTE(GETMVAR(QGVAR(enable),true)]); + defaultValue = QUOTE(GETMVAR(QGVAR(enable),true)); }; class GVAR(enableAmmoCookoff) { property = QGVAR(enableAmmoCookoff); From cc06b37f47adee85c080f55c0c2740a1da1a3e9c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:03:03 +0100 Subject: [PATCH 20/27] Removed GVAR(enable), added GVAR(enableFire) back --- addons/cookoff/ACE_Settings.hpp | 3 - addons/cookoff/CfgEden.hpp | 10 +-- addons/cookoff/functions/fnc_cookOff.sqf | 7 +- addons/cookoff/functions/fnc_cookOffBox.sqf | 2 +- .../cookoff/functions/fnc_cookOffEffect.sqf | 2 +- .../functions/fnc_detonateAmmunition.sqf | 2 +- .../fnc_detonateAmmunitionServer.sqf | 1 + addons/cookoff/functions/fnc_engineFire.sqf | 4 +- .../cookoff/functions/fnc_engineFireLocal.sqf | 7 +- .../cookoff/functions/fnc_handleDamageBox.sqf | 2 +- addons/cookoff/initSettings.inc.sqf | 6 +- addons/cookoff/stringtable.xml | 88 ++++++++----------- docs/wiki/framework/cookoff-framework.md | 6 +- 13 files changed, 64 insertions(+), 76 deletions(-) diff --git a/addons/cookoff/ACE_Settings.hpp b/addons/cookoff/ACE_Settings.hpp index f60a5276db4..37594bed51b 100644 --- a/addons/cookoff/ACE_Settings.hpp +++ b/addons/cookoff/ACE_Settings.hpp @@ -1,7 +1,4 @@ class ACE_Settings { - class GVAR(enable) { - movedToSqf = 1; - }; class GVAR(enableAmmobox) { movedToSQF = 1; }; diff --git a/addons/cookoff/CfgEden.hpp b/addons/cookoff/CfgEden.hpp index 1647bd7a6e7..f973ef40261 100644 --- a/addons/cookoff/CfgEden.hpp +++ b/addons/cookoff/CfgEden.hpp @@ -3,15 +3,15 @@ class Cfg3DEN { class AttributeCategories { class ace_attributes { class Attributes { - class GVAR(enable) { - property = QGVAR(enable); + class GVAR(enable) { // setting was previously GVAR(enable), so maintain for backwards compatiblity with missions + property = QGVAR(enable); // same as above control = "Checkbox"; - displayName = CSTRING(enable_name); - tooltip = CSTRING(enable_tooltip); + displayName = CSTRING(enableFire_name); + tooltip = CSTRING(enableFire_tooltip); expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]}); typeName = "BOOL"; condition = "objectVehicle"; - defaultValue = QUOTE(GETMVAR(QGVAR(enable),true)); + defaultValue = QUOTE(GETMVAR(QGVAR(enableFire),true)); }; class GVAR(enableAmmoCookoff) { property = QGVAR(enableAmmoCookoff); diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index fdd4f2b2dbb..26749986335 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -27,7 +27,7 @@ */ if (!isServer) exitWith {}; -if (!GVAR(enable) || {GVAR(cookoffDuration) == 0}) exitWith {}; +if (!GVAR(enableFire) || {GVAR(cookoffDuration) == 0}) exitWith {}; params [ "_vehicle", @@ -53,7 +53,7 @@ if (_vehicle isKindOf "CAManBase" || {_vehicle isKindOf "StaticWeapon"}) exitWit if (underwater _vehicle || {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}}) exitWith {}; // Check if cook-off is disabled on vehicle specifically -if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; +if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; // QGVAR(enable) is API TRACE_2("cooking off",_vehicle,_intensity); TRACE_9("",_source,_instigator,_delayBetweenSmokeAndFire,_ammoDetonationChance,_detonateAfterCookoff,_fireSource,_canRing,_canJet,_maxIntensity); @@ -104,7 +104,8 @@ if (_delayBetweenSmokeAndFire) then { if ( isNull _vehicle || - !GVAR(enable) || + !GVAR(enableFire) || + {!(_vehicle getVariable [QGVAR(enable), true])} || // QGVAR(enable) is API {_intensity <= 1} || {GVAR(cookoffDuration) == 0} || {underwater _vehicle} || diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index 4fbc6b66b5a..36613f5a7ef 100644 --- a/addons/cookoff/functions/fnc_cookOffBox.sqf +++ b/addons/cookoff/functions/fnc_cookOffBox.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: KoffeinFlummi, commy2, kymckay, johnb43 - * Start a cook-off in the given ammo box. + * Start an ammo cook-off in the given ammo box. * * Arguments: * 0: Ammo box diff --git a/addons/cookoff/functions/fnc_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index 6f8bd84e04c..0ed27dd6693 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: tcvm - * Spawn cook-off effects. + * Spawn cook-off fire effects. * * Arguments: * 0: Vehicle diff --git a/addons/cookoff/functions/fnc_detonateAmmunition.sqf b/addons/cookoff/functions/fnc_detonateAmmunition.sqf index 1aa66b5b870..ac070a79bb8 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunition.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunition.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: johnb43 - * Starts ammunition detonating from an object. + * Starts detonating ammunition from an object (e.g. vehicle or crate). * * Arguments: * 0: Object diff --git a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf index 7a5a55ebb5f..cb904a89db8 100644 --- a/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf +++ b/addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf @@ -37,6 +37,7 @@ if ( {!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} || {!(_object getVariable [QGVAR(enableAmmoCookoff), true])} ) exitWith { + // Box cook-off fire ends after the ammo has detonated (vehicle cook-off fire does not depend on the ammo detonation) if (_object isKindOf "ReammoBox_F") then { [QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent; diff --git a/addons/cookoff/functions/fnc_engineFire.sqf b/addons/cookoff/functions/fnc_engineFire.sqf index 9b7160531e6..eae6014ffd8 100644 --- a/addons/cookoff/functions/fnc_engineFire.sqf +++ b/addons/cookoff/functions/fnc_engineFire.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: KoffeinFlummi, commy2 + * Author: KoffeinFlummi, commy2, johnb43 * Start fire in engine block of a car. * * Arguments: @@ -22,7 +22,7 @@ params ["_vehicle"]; // If already smoking, stop if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {}; -_vehicle setVariable [QGVAR(isEngineSmoking), true]; +_vehicle setVariable [QGVAR(isEngineSmoking), true, true]; // Spawn engine fire effects on all connected machines private _jipID = [QGVAR(engineFireLocal), [_vehicle, CBA_missionTime + random [ENGINE_FIRE_TIME / 2, ENGINE_FIRE_TIME, ENGINE_FIRE_TIME / 2 * 3]]] call CBA_fnc_globalEventJIP; diff --git a/addons/cookoff/functions/fnc_engineFireLocal.sqf b/addons/cookoff/functions/fnc_engineFireLocal.sqf index 65d1670ed26..a6afb2f8ef2 100644 --- a/addons/cookoff/functions/fnc_engineFireLocal.sqf +++ b/addons/cookoff/functions/fnc_engineFireLocal.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: KoffeinFlummi, commy2 + * Author: KoffeinFlummi, commy2, johnb43 * Start fire in engine block of a car. * * Arguments: @@ -64,9 +64,10 @@ if (hasInterface) then { deleteVehicle _smoke; - if (isNull _vehicle || !isServer) exitWith {}; + if (!isServer || {isNull _vehicle}) exitWith {}; - _vehicle setVariable [QGVAR(isEngineSmoking), nil]; + // Reset variable, so engine can smoke again in the future + _vehicle setVariable [QGVAR(isEngineSmoking), nil, true]; private _jipID = _vehicle getVariable QGVAR(engineFireJipID); diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index bf52632fe11..7c6e0566289 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: KoffeinFlummi, commy2 + * Author: KoffeinFlummi, commy2, johnb43 * Handles all incoming damage for boxes. * * Arguments: diff --git a/addons/cookoff/initSettings.inc.sqf b/addons/cookoff/initSettings.inc.sqf index cfcad8c9864..2bb5d38e7ae 100644 --- a/addons/cookoff/initSettings.inc.sqf +++ b/addons/cookoff/initSettings.inc.sqf @@ -1,11 +1,11 @@ [ - QGVAR(enable), + QGVAR(enableFire), "CHECKBOX", - [LSTRING(enable_name), LSTRING(enable_tooltip)], + [LSTRING(enableFire_name), LSTRING(enableFire_tooltip)], LSTRING(category_displayName), true, 1, - {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)} + {[QGVAR(enableFire), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ diff --git a/addons/cookoff/stringtable.xml b/addons/cookoff/stringtable.xml index a49955ac2b0..f02ab253854 100644 --- a/addons/cookoff/stringtable.xml +++ b/addons/cookoff/stringtable.xml @@ -16,65 +16,23 @@ ACE Cook off ACE Vznícení munice - - Enable vehicle cook-off effects + + Enable vehicle cook-off fire - - Enables vehicle cook-off effects (fire and fire sound, but doesn't include ammunition detonations). - - - Enable ammo box cook-off - Habilitar detonación inducida por calor en las cajas de munición - 弾薬箱の誘爆を有効化 - Durchzündung für Munitionskisten ermöglichen - 탄약 상자 쿡오프 현상 활성화 - Aktywuj samozapłon skrzyń z amunicją - Auto-inflammation des caisses de munitions - Abilita esplosione casse munizioni - 開啟彈藥箱殉爆效果 - 开启弹药箱殉爆效果 - Разрешить детонацию ящиков с боеприпасами - Permitir cozinhar caixas de munição - Povolit vynícení munice v krabicích - - - Enables cooking off of ammo boxes. - Habilita la detonación inducida por calor en las cajas de munición - 弾薬箱が誘爆するようになります。 - Ermöglicht Durchzündung von Munitionskisten. - 탄약 상자에 쿡오프 현상을 적용합니다. - Aktywuje samozapłon skrzyń z amunicją - Permet l'auto-inflammation des caisses de munitions. - Abilita l'esplosione di casse di munizioni distrutte. - 開啟彈藥箱殉爆效果 - 开启弹药箱殉爆效果 - Активирует детонацию ящиков с боеприпасами - Permitir que caixas de munição cozinhem. - Zapíná vznícení munice v krabicích. - - - Enable vehicle ammo cook-off - - - Enables cooking off of vehicle ammunition. Fires ammunition projectiles while vehicle has ammunition remaining. + + Enables vehicle cook-off fire effects.\nThis does NOT include ammunition detonations. - Vehicle cook-off duration multiplier + Vehicle cook-off fire duration multiplier - Multiplier for how long vehicle cook-off lasts.\nSetting to 0 will disable cookoff. - - - Ammo cook-off duration multiplier - - - Multiplier for how long ammunition cook-off lasts, for both vehicles and ammo boxes.\nSetting to 0 will disable ammo cookoff. + Multiplier for how long vehicle cook-off fire lasts.\nSetting to 0 will disable vehicle cook-off fire. - Vehicle cook-off probability multiplier + Vehicle cook-off fire probability multiplier - Multiplier for vehicle cook-off probability. Higher value results in higher cook-off probability.\nSetting to 0 will disable cookoff. + Multiplier for vehicle cook-off fire probability. Higher value results in higher cook-off probability.\nSetting to 0 will disable vehicle cook-off fire. Destroy vehicles after cook-off @@ -99,6 +57,36 @@ Contrôle si les véhicules seront toujours détruits après l'auto-inflammation. Define se os veículos serão sempre destruídos após cozinhamento. + + Enable vehicle ammo cook-off + + + Enables cooking off of vehicle ammunition. Fires ammunition projectiles while vehicle has ammunition remaining.\nThis does NOT include fire effects. + + + Enable ammo box cook-off + Habilitar detonación inducida por calor en las cajas de munición + 弾薬箱の誘爆を有効化 + Durchzündung für Munitionskisten ermöglichen + 탄약 상자 쿡오프 현상 활성화 + Aktywuj samozapłon skrzyń z amunicją + Auto-inflammation des caisses de munitions + Abilita esplosione casse munizioni + 開啟彈藥箱殉爆效果 + 开启弹药箱殉爆效果 + Разрешить детонацию ящиков с боеприпасами + Permitir cozinhar caixas de munição + Povolit vynícení munice v krabicích + + + Enables cooking off of ammo boxes.\nThis does NOT include fire effects. + + + Ammo cook-off duration multiplier + + + Multiplier for how long ammunition cook-off lasts, for both vehicles and ammo boxes.\nSetting to 0 will disable ammo cook-off for both vehicles and ammo boxes. + Enable ammo removal during cook-off 誘爆中の弾薬除去を有効/無効にする diff --git a/docs/wiki/framework/cookoff-framework.md b/docs/wiki/framework/cookoff-framework.md index 6b8f26182c0..81296991540 100644 --- a/docs/wiki/framework/cookoff-framework.md +++ b/docs/wiki/framework/cookoff-framework.md @@ -12,9 +12,9 @@ version: patch: 0 --- -## 1. Disabling cook-off for individual vehicles +## 1. Disabling cook-off fire for individual vehicles -Cook-off can be disabled for a specific vehicle. "Cook-off" refers to the fire effects (visual & sounds) that happen when a vehicle is cooking off: +Cook-off fire can be disabled for a specific vehicle (does not affect ammo cook-off): ``` _vehicle setVariable ["ace_cookoff_enable", false, true]; @@ -24,7 +24,7 @@ Mission settings will always apply however, so you can't enable cook-off on a ve ## 2. Disabling ammunition cook-off for individual vehicles and boxes -Ammunition cook-off can be disabled for a specific vehicle or box. "Ammunition cook-off" refers to the ammunition exploding in a burning vehicle: +Ammunition cook-off can be disabled for a specific vehicle or box (does not affect cook-off fire): ``` _vehicleOrBox setVariable ["ace_cookoff_enableAmmoCookoff", false, true]; From 9cd62fcc7f86c28949ed4883354060391e93518c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 3 Apr 2024 00:38:46 +0200 Subject: [PATCH 21/27] Update fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 7c6e0566289..48204ea593e 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -48,13 +48,8 @@ if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig > private _configMagazine = configFile >> "CfgMagazines" >> _magazine; // Magazine could have changed during flight time (just ignore if so) - if (getText (_configMagazine >> "ammo") == _ammo) then { - // If magazine's tracer density is high enough then low chance for cook off - private _tracers = getNumber (_configMagazine >> "tracersEvery"); - - if (_tracers >= 1 && {_tracers <= 4}) then { - [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; - }; + if (_ammo getShotInfo 4 && {getText (_configMagazine >> "ammo") == _ammo)} then { // 4 = shownTracer + [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; }; From 24d49d106f3d0d8f9ccab07c978da6d18929f601 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 3 Apr 2024 00:46:12 +0200 Subject: [PATCH 22/27] Update fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 48204ea593e..3f0d0ca2f11 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -48,7 +48,7 @@ if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig > private _configMagazine = configFile >> "CfgMagazines" >> _magazine; // Magazine could have changed during flight time (just ignore if so) - if (_ammo getShotInfo 4 && {getText (_configMagazine >> "ammo") == _ammo)} then { // 4 = shownTracer + if (_ammo getShotInfo 4 && {getText (_configMagazine >> "ammo") == _ammo}) then { // 4 = shownTracer [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; }; From 51c7a0f9b84d9d2c5d2d9f077d4c0d994d862774 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Thu, 9 May 2024 10:29:00 +0200 Subject: [PATCH 23/27] Update fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 3f0d0ca2f11..43e92f62d49 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -45,10 +45,8 @@ if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig > _source currentMagazineTurret (_source unitTurret _instigator) }; - private _configMagazine = configFile >> "CfgMagazines" >> _magazine; - // Magazine could have changed during flight time (just ignore if so) - if (_ammo getShotInfo 4 && {getText (_configMagazine >> "ammo") == _ammo}) then { // 4 = shownTracer + if (_ammo getShotInfo 4 && {getText (configFile >> "CfgMagazines" >> _magazine >> "ammo") == _ammo}) then { // 4 = shownTracer [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; }; From 87c876e663973d3369b1588c59d0e1dc40e3a245 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 29 May 2024 16:51:12 +0200 Subject: [PATCH 24/27] Update fnc_handleDamageBox.sqf --- .../cookoff/functions/fnc_handleDamageBox.sqf | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 43e92f62d49..864d36ff92e 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -32,23 +32,12 @@ if !(_hitPoint == "" && {_damage > 0.5}) exitWith {}; // "" means structural dam private _ammoConfig = _ammo call CBA_fnc_getObjectConfig; // Catch fire when hit by an explosive or incendiary round -if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1}) then { +if ( + (getNumber (_ammoConfig >> "explosive") >= 0.5) || + {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1} || + {random 1 < _damage * 0.05 && {_ammo getShotInfo 4}} // there is a small chance of cooking a box off if it's shot by tracer ammo +) then { [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; -} else { - // There is a small chance of cooking a box off if it's shot by tracer ammo - if (random 1 >= _damage * 0.05) exitWith {}; - - // Need magazine to check for tracers - private _magazine = if (_source == _instigator) then { - currentMagazine _source - } else { - _source currentMagazineTurret (_source unitTurret _instigator) - }; - - // Magazine could have changed during flight time (just ignore if so) - if (_ammo getShotInfo 4 && {getText (configFile >> "CfgMagazines" >> _magazine >> "ammo") == _ammo}) then { // 4 = shownTracer - [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; - }; }; // Prevent destruction, let cook-off handle it if necessary From 389e1c71d278f93d0f467347e8ea9d00add10e93 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:04:24 +0200 Subject: [PATCH 25/27] Update fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 5dedeea9966..97525388a3a 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -37,7 +37,7 @@ if ( {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1} || {random 1 < _damage * 0.05 && {_ammo getShotInfo 4}} // there is a small chance of cooking a box off if it's shot by tracer ammo ) then { - [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent; + [QGVAR(cookOffBoxServer), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; // Prevent destruction, let cook-off handle it if necessary From ffd07a7b42833f4566f3a667ced1a6db79dff096 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:42:29 +0200 Subject: [PATCH 26/27] Update fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 97525388a3a..97ad921570b 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -35,7 +35,7 @@ private _ammoConfig = _ammo call CBA_fnc_getObjectConfig; if ( (getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1} || - {random 1 < _damage * 0.05 && {_ammo getShotInfo 4}} // there is a small chance of cooking a box off if it's shot by tracer ammo + {_damage * 0.05 > random 1 && {_ammo getShotInfo 4}} // there is a small chance of cooking a box off if it's shot by tracer ammo ) then { [QGVAR(cookOffBoxServer), [_box, _source, _instigator]] call CBA_fnc_serverEvent; }; From aac4675c68c84dec0d92606aa393f553db4ff27a Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 11 Aug 2024 08:05:01 -0700 Subject: [PATCH 27/27] Update addons/cookoff/functions/fnc_handleDamageBox.sqf --- addons/cookoff/functions/fnc_handleDamageBox.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_handleDamageBox.sqf b/addons/cookoff/functions/fnc_handleDamageBox.sqf index 97ad921570b..e78f2c94b8b 100644 --- a/addons/cookoff/functions/fnc_handleDamageBox.sqf +++ b/addons/cookoff/functions/fnc_handleDamageBox.sqf @@ -35,7 +35,7 @@ private _ammoConfig = _ammo call CBA_fnc_getObjectConfig; if ( (getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1} || - {_damage * 0.05 > random 1 && {_ammo getShotInfo 4}} // there is a small chance of cooking a box off if it's shot by tracer ammo + {_damage * 0.05 > random 1 && {_ammo getShotInfo 4}} // There is a small chance of cooking a box off if it's shot by tracer ammo ) then { [QGVAR(cookOffBoxServer), [_box, _source, _instigator]] call CBA_fnc_serverEvent; };