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] 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 | 154 +++++++------ addons/cookoff/functions/fnc_cookOffBox.sqf | 70 ++---- .../cookoff/functions/fnc_cookOffBoxLocal.sqf | 83 +++++++ .../cookoff/functions/fnc_cookOffEffect.sqf | 173 ++++++++------- .../functions/fnc_detonateAmmunition.sqf | 207 +++++++++++------- addons/cookoff/functions/fnc_engineFire.sqf | 40 +--- .../cookoff/functions/fnc_engineFireLocal.sqf | 61 ++++++ .../cookoff/functions/fnc_getVehicleAmmo.sqf | 52 +++-- .../cookoff/functions/fnc_handleDamageBox.sqf | 88 ++++---- .../cookoff/functions/fnc_isMagazineFlare.sqf | 10 +- addons/cookoff/functions/fnc_smoke.sqf | 12 +- addons/cookoff/initSettings.inc.sqf | 112 +++++----- 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 | 39 +--- docs/wiki/framework/events-framework.md | 7 +- .../wiki/framework/vehicledamage-framework.md | 2 +- 29 files changed, 755 insertions(+), 700 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 ba4447dba9..f60a5276db 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 c167177705..a328451a7b 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 2b58daa304..12117cae3b 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 6c29240403..f6503c2479 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 0d670ead86..24329862fc 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 78cbd0c623..86e0df8386 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 2cd87efaa7..3dc602be70 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 b9c8101595..400569afd6 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; -// handle cleaning up effects when vehicle is deleted mid-cookoff +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 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", []]]; - _effects = _effects + (_vehicle getVariable [QGVAR(effects), []]); - if (_effects isNotEqualTo []) then { - { deleteVehicle _x } count _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); + + 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 1d598cdb96..048b82beb2 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; - -// 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 (_ammoDetonationChance > random 1) then { - private _lastExplosiveDetonationTime = _vehicle getVariable [QGVAR(lastExplosiveDetonation), 0]; - private _nextExplosiveDetonation = _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]; - - if ((CBA_missionTime - _lastExplosiveDetonationTime) > _nextExplosiveDetonation) then { - if (_fireSource isEqualTo "") then { - _fireSource = selectRandom _positions; - }; - createVehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld (_vehicle selectionPosition _fireSource)), [], 0 , "CAN_COLLIDE"]; - - _vehicle setVariable [QGVAR(lastExplosiveDetonation), CBA_missionTime]; - _vehicle setVariable [QGVAR(nextExplosiveDetonation), random 60]; + // 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); }; }; - }, 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; + + if (_ammoDetonationChance > random 1 && {CBA_missionTime >= _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]}) then { + if (_fireSource isEqualTo "") then { + _fireSource = selectRandom _positions; + }; + + createVehicle ["ACE_ammoExplosionLarge", _vehicle modelToWorld (_vehicle selectionPosition _fireSource), [], 0 , "CAN_COLLIDE"]; + + _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; diff --git a/addons/cookoff/functions/fnc_cookOffBox.sqf b/addons/cookoff/functions/fnc_cookOffBox.sqf index 8b8e60891c..0a1d92944f 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 {}; + +params ["_box", "_killer", "_instigator"]; if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; -_box setVariable [QGVAR(isCookingOff), true]; -if (local _box) then { - [QGVAR(cookOffBox), _box] call CBA_fnc_globalEvent; -}; +_box setVariable [QGVAR(isCookingOff), true, true]; -[{ - params ["_box"]; +// 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; - // Box will start smoking - private _smoke = "#particlesource" createVehicleLocal [0,0,0]; - _smoke setParticleClass "AmmoSmokeParticles2"; - _smoke attachTo [_box, [0,0,0]]; +[_jipID, _box] call CBA_fnc_removeGlobalEventJIP; - private _effects = [_smoke]; - - 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]]; - - _effects pushBack _fire; - - [{ - params ["_box", "_effects"]; - - { - deleteVehicle _x; - } forEach _effects; - - 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 0000000000..2e0dd031a1 --- /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 a907f67606..1cf1e3f853 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]; }; - _light setLightBrightness 5 * (_factor / 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]; + }; + + // 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 + (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, [_obj, _jet, _ring, _time, CBA_missionTime, _light, _fireSelection, _sound, _intensity]] call CBA_fnc_addPerFrameHandler; - +}, 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 b4d48f3120..145bb99987 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); +// 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 (_destroyWhenFinished) then { + _object setDamage [1, true, _killer, _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(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 _magazineIndex = floor random (count _magazines); private _magazine = _magazines select _magazineIndex; -_magazine params ["_magazineClassname", "_amountOfMagazines"]; +_magazine params ["_magazineClassname", "_ammoCount"]; -if (_amountOfMagazines > 0) exitWith { - private _removed = _amountOfMagazines min floor(1 + random(6 / GVAR(ammoCookoffDuration))); +// Make sure ammo is at least 0 +_ammoCount = _ammoCount max 0; - _amountOfMagazines = _amountOfMagazines - _removed; - if (_amountOfMagazines <= 0) then { - _magazines deleteAt _magazineIndex; +// 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; + +// 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 _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 { - _magazine set [1, _amountOfMagazines]; // clear out the magazine + _projectile setDamage 1; }; - 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; - - private _speedOfAmmo = getNumber (configFile >> "CfgMagazines" >> _magazineClassname >> "initSpeed"); - private _simType = getText (_ammoCfg >> "simulation"); - - private _effect2pos = _vehicle selectionPosition "destructionEffect2"; - - private _spawnProjectile = { - params ["_vehicle", "_ammo", "_speed", "_flyAway"]; - - 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]; - }; - - 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; - }; - - _projectile; - }; - - private _speed = random (_speedOfAmmo / 10) max 1; - - 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]; +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; - }; - if (toLower _simType in ["shotrocket", "shotmissile", "shotsubmunitions"]) then { - 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]; - [_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile; + [_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile; + }; + case "shotrocket"; + case "shotmissile"; + case "shotsubmunitions": { + if (random 1 < 0.1) then { + 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]; + + [_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 118537b30a..9b7160531e 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; -}; +// 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; -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]; - -[{ - (_this select 0) params ["_vehicle", "_smoke", "_time"]; - - 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 0000000000..845ced8bd8 --- /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 f6be84c1f9..5f6603c453 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 dfc5cb7267..2f76ef9c77 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; -}; - -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); + // Get change in damage + private _oldDamage = if (_hitpoint == "#structural") then { + damage _box } 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; - - // 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); - }; - }; - }; + _box getHitIndex _hitIndex }; - // prevent destruction, let cook-off handle it if necessary - _damage min 0.89 -} else { - _damage + // There is a small chance of cooking a box off if it's shot by tracer ammo + if !(random 1 < _oldDamage * 0.05) exitWith {}; + + // Need magazine to check for tracers + private _magazine = if (_source == _instigator) then { + currentMagazine _source + } else { + _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"); + + 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 diff --git a/addons/cookoff/functions/fnc_isMagazineFlare.sqf b/addons/cookoff/functions/fnc_isMagazineFlare.sqf index b6c8a604be..fd6ea99641 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 ce50043413..6ff2726fa1 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 8912636fd6..afaaabc1b0 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)], - LSTRING(category_displayName), - false, // default value - true, // isGlobal - {[QGVAR(destroyVehicleAfterCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart -] call CBA_fnc_addSetting; - -[ - QGVAR(enableAmmoCookoff), "CHECKBOX", - [LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)], - LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(enableAmmoCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)}, - false // Needs mission restart -] call CBA_fnc_addSetting; - -[ - QGVAR(enableAmmobox), "CHECKBOX", - [LSTRING(enableBoxCookoff_name), LSTRING(enableBoxCookoff_tooltip)], - LSTRING(category_displayName), - true, // default value - true, // isGlobal - {[QGVAR(enableAmmobox), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart -] call CBA_fnc_addSetting; - -[ - 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(ammoCookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart -] call CBA_fnc_addSetting; - -[ - QGVAR(probabilityCoef), "SLIDER", + QGVAR(probabilityCoef), + "SLIDER", [LSTRING(probabilityCoef_name), LSTRING(probabilityCoef_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(probabilityCoef), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(destroyVehicleAfterCookoff), + "CHECKBOX", + [LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)], + LSTRING(category_displayName), + false, + 1, + {[QGVAR(destroyVehicleAfterCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(enableAmmoCookoff), + "CHECKBOX", + [LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)], + LSTRING(category_displayName), + true, + 1, + {[QGVAR(enableAmmoCookoff), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(enableAmmobox), + "CHECKBOX", + [LSTRING(enableBoxCookoff_name), LSTRING(enableBoxCookoff_tooltip)], + LSTRING(category_displayName), + true, + 1, + {[QGVAR(enableAmmobox), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(ammoCookoffDuration), + "SLIDER", + [LSTRING(ammoCookoffDuration_name), LSTRING(ammoCookoffDuration_tooltip)], + LSTRING(category_displayName), + [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 03b3e5c5f5..9e00ea970e 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 76aebcad60..5959a23782 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 11d89d4ca5..e1e2732576 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 75d72da340..017feffceb 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 67d64da442..437570292d 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 a6e7335542..453454d08c 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 b53fea2049..6b8f26182c 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 + +Ammunition cook-off can be disabled for a specific vehicle or box. "Ammunition cook-off" refers to the ammunition exploding in a burning vehicle: ``` -VEHICLE setVariable ["ace_cookoff_enable", false, true]; +_vehicleOrBox setVariable ["ace_cookoff_enableAmmoCookoff", 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: - -``` -class MyVehicle { - ace_cookoff_probability = 0.6; -}; -``` - -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 c29f271719..f4edcbad4c 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 7e22bccf5d..60d60e9676 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