Cook-off improvements

This commit is contained in:
johnb432 2024-01-27 09:14:10 +01:00
parent a5da6cc83d
commit 4f33c32ba9
29 changed files with 755 additions and 700 deletions

View File

@ -1,4 +1,3 @@
class ACE_Settings { class ACE_Settings {
class GVAR(enable) { class GVAR(enable) {
movedToSqf = 1; movedToSqf = 1;
@ -6,7 +5,7 @@ class ACE_Settings {
class GVAR(enableAmmobox) { class GVAR(enableAmmobox) {
movedToSQF = 1; movedToSQF = 1;
}; };
class GVAR(enableAmmoCookoff) { // For CBA Setting Switch: we can eliminate and just use (ammoCookoffDuration == 0) class GVAR(enableAmmoCookoff) {
movedToSQF = 1; movedToSQF = 1;
}; };
class GVAR(ammoCookoffDuration) { class GVAR(ammoCookoffDuration) {

View File

@ -1,4 +1,3 @@
class CfgCloudlets { class CfgCloudlets {
class GVAR(CookOff) { class GVAR(CookOff) {
interval = 0.004; interval = 0.004;

View File

@ -1,4 +1,3 @@
class Cfg3DEN { class Cfg3DEN {
class Object { class Object {
class AttributeCategories { class AttributeCategories {
@ -7,9 +6,9 @@ class Cfg3DEN {
class GVAR(enable) { class GVAR(enable) {
property = QGVAR(enable); property = QGVAR(enable);
control = "Checkbox"; control = "Checkbox";
displayName = CSTRING(enable_hd_name); displayName = CSTRING(enable_name);
tooltip = CSTRING(enable_hd_tooltip); tooltip = CSTRING(enable_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"; typeName = "BOOL";
condition = "objectVehicle"; condition = "objectVehicle";
defaultValue = QUOTE((GETMVAR(QGVAR(enable),0)) in [ARR_2(1,2)]); defaultValue = QUOTE((GETMVAR(QGVAR(enable),0)) in [ARR_2(1,2)]);
@ -19,10 +18,10 @@ class Cfg3DEN {
control = "Checkbox"; control = "Checkbox";
displayName = CSTRING(enableAmmoCookoff_name); displayName = CSTRING(enableAmmoCookoff_name);
tooltip = CSTRING(enableAmmoCookoff_tooltip); 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"; typeName = "BOOL";
condition = "objectHasInventoryCargo"; 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)});
}; };
}; };
}; };

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers { class Extended_PreStart_EventHandlers {
class ADDON { class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));

View File

@ -1,4 +1,3 @@
class CfgSFX { class CfgSFX {
class GVAR(CookOff_low) { class GVAR(CookOff_low) {
name = QGVAR(cookoff_low); name = QGVAR(cookoff_low);

View File

@ -1,4 +1,3 @@
class CfgVehicles { class CfgVehicles {
class Sound; class Sound;
class GVAR(Sound_low): Sound { class GVAR(Sound_low): Sound {
@ -7,7 +6,6 @@ class CfgVehicles {
scope = 1; scope = 1;
sound = QGVAR(CookOff_low); sound = QGVAR(CookOff_low);
}; };
class GVAR(Sound_mid): GVAR(Sound_low) { class GVAR(Sound_mid): GVAR(Sound_low) {
sound = QGVAR(CookOff_mid); sound = QGVAR(CookOff_mid);
}; };
@ -17,37 +15,25 @@ class CfgVehicles {
class Tank; class Tank;
class Tank_F: Tank { class Tank_F: Tank {
GVAR(ammoLocation) = "HitHull";
GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"}; GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"};
GVAR(probability) = 0.5;
};
class MBT_02_base_F: Tank_F {
GVAR(ammoLocation) = "HitTurret";
}; };
class Car_F; class Car_F;
class Wheeled_APC_F: Car_F { class Wheeled_APC_F: Car_F {
GVAR(ammoLocation) = "HitHull";
GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"}; 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"; explosionEffect = "FuelExplosionBig";
}; };
class MRAP_01_base_F: Car_F { class MRAP_01_base_F: Car_F {
GVAR(engineSmokeOffset)[] = {0, -2, 0}; GVAR(engineSmokeOffset)[] = {0, -2, 0};
}; };
class MRAP_02_base_F: Car_F { class MRAP_02_base_F: Car_F {
GVAR(engineSmokeOffset)[] = {0, -2, 0}; GVAR(engineSmokeOffset)[] = {0, -2, 0};
}; };
class MRAP_03_base_F: Car_F { class MRAP_03_base_F: Car_F {
GVAR(engineSmokeOffset)[] = {0, -2, 0}; GVAR(engineSmokeOffset)[] = {0, -2, 0};
}; };
class Quadbike_01_base_F: Car_F { class Quadbike_01_base_F: Car_F {
GVAR(engineSmokeOffset)[] = {0, 1, 0}; GVAR(engineSmokeOffset)[] = {0, 1, 0};
}; };
@ -56,7 +42,6 @@ class CfgVehicles {
class Truck_02_base_F: 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 { class Truck_02_MRL_base_F: Truck_02_base_F {
GVAR(engineSmokeOffset)[] = {0, 0.3, -0.1}; GVAR(engineSmokeOffset)[] = {0, 0.3, -0.1};
}; };

View File

@ -1,10 +1,11 @@
PREP(handleDamageBox);
PREP(engineFire);
PREP(cookOff); PREP(cookOff);
PREP(smoke);
PREP(cookOffEffect);
PREP(cookOffBox); PREP(cookOffBox);
PREP(cookOffBoxLocal);
PREP(cookOffEffect);
PREP(detonateAmmunition); PREP(detonateAmmunition);
PREP(engineFire);
PREP(engineFireLocal);
PREP(getVehicleAmmo); PREP(getVehicleAmmo);
PREP(handleDamageBox);
PREP(isMagazineFlare); PREP(isMagazineFlare);
PREP(smoke);

View File

@ -1,60 +1,81 @@
#include "script_component.hpp" #include "script_component.hpp"
[QGVAR(engineFire), FUNC(engineFire)] call CBA_fnc_addEventHandler; [QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler;
[QGVAR(cookOff), { [QGVAR(cookOffBoxLocal), LINKFUNC(cookOffBoxLocal)] call CBA_fnc_addEventHandler;
params ["_vehicle"]; [QGVAR(cookOffEffect), LINKFUNC(cookOffEffect)] call CBA_fnc_addEventHandler;
if (local _vehicle) then { [QGVAR(engineFireLocal), LINKFUNC(engineFireLocal)] call CBA_fnc_addEventHandler;
_this call FUNC(cookOff); [QGVAR(smoke), LINKFUNC(smoke)] call CBA_fnc_addEventHandler;
};
}] 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;
// 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), { [QGVAR(addCleanupHandlers), {
params ["_vehicle"]; // No effects on machines without interfaces
if (!hasInterface) exitWith {};
// Don't add a new EH if cookoff is run multiple times params ["_object"];
if ((_vehicle getVariable [QGVAR(deletedEH), -1]) == -1) then {
private _deletedEH = _vehicle addEventHandler ["Deleted", {
params ["_vehicle"];
[QGVAR(cleanupEffects), [_vehicle]] call CBA_fnc_localEvent; // Don't add a new EH if cook-off is run multiple times
}]; if (!isNil {_object getVariable QGVAR(deletedEH)}) exitWith {};
_vehicle setVariable [QGVAR(deletedEH), _deletedEH]; _object setVariable [QGVAR(deletedEH),
}; _object addEventHandler ["Deleted", {
[QGVAR(cleanupEffects), _this select 0] call CBA_fnc_localEvent;
}]
];
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
[QGVAR(cleanupEffects), { [QGVAR(cleanupEffects), {
params ["_vehicle", ["_effects", []]]; params ["_object", ["_effects", []]];
_effects = _effects + (_vehicle getVariable [QGVAR(effects), []]); if (isServer) then {
if (_effects isNotEqualTo []) then { // Reset, so that object can cook-off again
{ deleteVehicle _x } count _effects; _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; }] call CBA_fnc_addEventHandler;
["ReammoBox_F", "init", { ["ReammoBox_F", "init", {
(_this select 0) addEventHandler ["HandleDamage", { // Calling this function inside curly brackets allows the usage of "exitWith", which would be broken with "HandleDamage" otherwise
if ((_this select 0) getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmobox)]) then { (_this select 0) addEventHandler ["HandleDamage", {_this call FUNC(handleDamageBox)}];
_this call FUNC(handleDamageBox);
};
}];
}, nil, nil, true] call CBA_fnc_addClassEventHandler; }, nil, nil, true] call CBA_fnc_addClassEventHandler;
// secondary explosions // Secondary explosions
["AllVehicles", "killed", { ["AllVehicles", "Killed", {
if (!GVAR(enableAmmoCookoff) || {GVAR(ammoCookoffDuration) == 0}) exitWith {};
params ["_vehicle", "", "", "_useEffects"]; params ["_vehicle", "", "", "_useEffects"];
if (
_useEffects && if (_useEffects && {_vehicle getVariable [QGVAR(enableAmmoCookoff), true]}) then {
_vehicle getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmoCookoff)] (_vehicle call FUNC(getVehicleAmmo)) params ["_magazines", "_total"];
) then {
if (GVAR(ammoCookoffDuration) == 0) exitWith {};
([_vehicle] call FUNC(getVehicleAmmo)) params ["_mags", "_total"];
private _delay = (random MAX_AMMO_DETONATION_START_DELAY) max MIN_AMMO_DETONATION_START_DELAY; 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;

View File

@ -2,49 +2,70 @@
/* /*
* Author: tcvm * Author: tcvm
* Start a cook-off in the given vehicle. * 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: * Arguments:
* 0: Vehicle <Object> * 0: Vehicle <OBJECT>
* 1: Intensity of fire <Number> * 1: Intensity of fire <NUMBER>
* 2: Instigator <OBJECT> (default: objNull)
* 3: Delay between smoke and fire enabled <BOOL> (default: true)
* 4: Ammo detonation chance <NUMBER> (default: 0)
* 5: Detonate after cook-off <BOOL> (default: false)
* 6: Selection for fire source <STRING> (default: "")
* 7: Can spawn fire ring <BOOL> (default: true)
* 8: Maximum intensity <NUMBER> (default: MAX_COOKOFF_INTENSITY)
* 9: Can spawn fire jet <BOOL> (default: true)
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [(vehicle player), 3] call ace_cookoff_fnc_cookOff * [vehicle player, 3] call ace_cookoff_fnc_cookOff
* *
* Public: No * 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 {}; params [
if !(GVAR(enableFire)) exitWith {}; "_vehicle",
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] in [0, false]) exitWith {}; "_intensity",
// exit if cook-off enabled only for players and no players in vehicle crew found ["_instigator", objNull],
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] isEqualTo 1 && {fullCrew [_vehicle, "", false] findIf {isPlayer (_x select 0)} == -1}) exitWith {}; ["_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_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 {}; if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {};
_vehicle setVariable [QGVAR(isCookingOff), true, true]; _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; _intensity = _intensity min _maxIntensity;
private _config = _vehicle call CBA_fnc_getObjectConfig; private _positions = getArray (configOf _vehicle >> QGVAR(cookoffSelections)) select {(_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]};
private _positions = getArray (_config >> QGVAR(cookoffSelections)) select {(_vehicle selectionPosition _x) isNotEqualTo [0,0,0]};
if (_positions isEqualTo []) then { if (_positions isEqualTo []) then {
WARNING_1("no valid selection for cookoff found. %1",typeOf _vehicle); WARNING_1("no valid selection for cookoff found. %1",typeOf _vehicle);
{ {
private _pos = _vehicle selectionPosition _x; if ((_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]) then {
if (_pos isEqualTo [0, 0, 0]) exitWith {};
_positions pushBack _x; _positions pushBack _x;
};
} forEach DEFAULT_COMMANDER_HATCHES; } forEach DEFAULT_COMMANDER_HATCHES;
if (_positions isEqualTo []) then { 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; private _delay = 0;
if (_smokeDelayEnabled) then {
if (_delayBetweenSmokeAndFire) then {
_delay = SMOKE_TIME + random SMOKE_TIME; _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"]; (_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"];
_args params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_smokeEffects"];
private _intensity = _vehicle getVariable [QGVAR(intensity), 0]; private _intensity = _vehicle getVariable [QGVAR(intensity), 0];
if (isNull _vehicle || {_intensity <= 1}) exitWith {
[QGVAR(cleanupEffects), [_vehicle, _smokeEffects]] call CBA_fnc_globalEvent; if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith {
_vehicle setVariable [QGVAR(isCookingOff), false, true]; [_this select 1] call CBA_fnc_removePerFrameHandler;
[_pfh] 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 { 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 // Wait until we are ready for the next flame
// dt = Tcurrent - Tlast if (CBA_missionTime >= _vehicle getVariable [QGVAR(nextFlame), 0]) then {
// dt >= Tnext private _ring = false;
if ((CBA_missionTime - _lastFlameTime) >= _nextFlameTime) then {
private _ring = (0.2 > random 1);
if (!_ring && _intensity >= 2) then {
_ring = (0.7 > random 1);
};
if !(_canRing) then { if (_canRing) then {
_ring = false; _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; private _time = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME;
@ -99,31 +124,30 @@ if (_smokeDelayEnabled) then {
_fireSource = selectRandom _positions; _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; [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(intensity), _intensity];
_vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _time + (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 {
{ {
[QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator]] call CBA_fnc_globalEvent; [QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator]] call CBA_fnc_globalEvent;
} forEach crew _vehicle } forEach (crew _vehicle);
};
}; };
if (_ammoDetonationChance > random 1) then { if (_ammoDetonationChance > random 1 && {CBA_missionTime >= _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]}) 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 { if (_fireSource isEqualTo "") then {
_fireSource = selectRandom _positions; _fireSource = selectRandom _positions;
}; };
createVehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld (_vehicle selectionPosition _fireSource)), [], 0 , "CAN_COLLIDE"];
_vehicle setVariable [QGVAR(lastExplosiveDetonation), CBA_missionTime]; createVehicle ["ACE_ammoExplosionLarge", _vehicle modelToWorld (_vehicle selectionPosition _fireSource), [], 0 , "CAN_COLLIDE"];
_vehicle setVariable [QGVAR(nextExplosiveDetonation), random 60];
_vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60];
}; };
}; }, 0.25, _this] call CBA_fnc_addPerFrameHandler;
}, 0.25, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _smokeEffects]] call CBA_fnc_addPerFrameHandler }, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute;
}, [_vehicle, _positions, _intensity, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute;

View File

@ -1,6 +1,6 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: KoffeinFlummi, commy2, kymckay * Author: KoffeinFlummi, commy2, kymckay, johnb43
* Start a cook-off in the given ammo box. * Start a cook-off in the given ammo box.
* *
* Arguments: * Arguments:
@ -10,65 +10,29 @@
* None * None
* *
* Example: * Example:
* [_box] call ace_cookoff_fnc_cookOffBox * cursorObject call ace_cookoff_fnc_cookOffBox
* *
* Public: No * Public: No
*/ */
params ["_box"]; if (!isServer) exitWith {};
params ["_box", "_killer", "_instigator"];
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {}; if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
_box setVariable [QGVAR(isCookingOff), true];
if (local _box) then { _box setVariable [QGVAR(isCookingOff), true, true];
[QGVAR(cookOffBox), _box] call CBA_fnc_globalEvent;
};
[{ // Spawn cook-off effects on all connected machines
params ["_box"]; 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 [_jipID, _box] call CBA_fnc_removeGlobalEventJIP;
private _smoke = "#particlesource" createVehicleLocal [0,0,0];
_smoke setParticleClass "AmmoSmokeParticles2";
_smoke attachTo [_box, [0,0,0]];
private _effects = [_smoke]; _box setVariable [QGVAR(jipID), _jipID];
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;

View File

@ -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 <OBJECT>
*
* 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;
};

View File

@ -1,15 +1,15 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: tcvm * Author: tcvm
* Spawn cook-off effects * Spawn cook-off effects.
* *
* Arguments: * Arguments:
* 0: Vehicle <Object> * 0: Vehicle <OBJECT>
* 1: Spawn fire jet <Boolean> * 1: Spawn fire jet <BOOL>
* 2: Spawn fire ring <Boolean> * 2: Spawn fire ring <BOOL>
* 3: How long effect will last (Max 20 seconds) <Number> * 3: Duration of effect (max 20 seconds) <NUMBER>
* 4: What selection will fire originate from <String> * 4: What selection will fire originate from <STRING>
* 5: Cookoff intensity value <Number> * 5: Cookoff intensity value <NUMBER>
* *
* Return Value: * Return Value:
* None * None
@ -20,60 +20,89 @@
* Public: No * Public: No
*/ */
params ["_obj", "_jet", "_ring", "_time", "_fireSelection", "_intensity"]; #define FLAME_SIZE 1.5
private _light = "#lightpoint" createVehicleLocal [0,0,0]; #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 setLightBrightness 5;
_light setLightAmbient [0.8, 0.6, 0.2]; _light setLightAmbient [0.8, 0.6, 0.2];
_light setLightColor [1, 0.5, 0.2]; _light setLightColor [1, 0.5, 0.2];
_light lightAttachObject [_obj, [0,0,0]]; _light lightAttachObject [_vehicle, [0, 0, 0]];
_time = 0 max (_time min 20);
private _sound = objNull;
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!
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];
}; };
if (_ring) then { _duration = 0 max _duration min 20;
private _intensity = 6;
private _radius = 1.5 * ((boundingBoxReal _obj) select 2); private _sound = objNull;
[QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, _obj]] call CBA_fnc_localEvent; private _fireKey = "";
if (isServer) then {
// 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, ASLToAGL getPosASL _vehicle, [], 0];
_sound attachTo [_vehicle];
};
// 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"]; (_this select 0) params ["_vehicle", "_jet", "_ring", "_duration", "_startTime", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"];
_args params ["_obj", "_jet", "_ring", "_time", "_startTime", "_light", "_fireSelection", "_sound", "_intensity"];
private _elapsedTime = CBA_missionTime - _startTime; 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 _light;
deleteVehicle _sound;
if (isServer) then { if (isServer) then {
[QEGVAR(fire,removeFireSource), [_obj]] call CBA_fnc_localEvent; deleteVehicle _sound;
};
[_pfh] call CBA_fnc_removePerFrameHandler;
};
private _factor = (1 + (_elapsedTime / 2) min 2);
private _flameSize = 1.5;
if (_elapsedTime > (_time * (3 / 4))) then { if (["ace_fire"] call EFUNC(common,isModLoaded)) then {
_factor = _factor * linearConversion [_time * (3 / 4), _time, _elapsedTime, 1, 0.5]; [QEGVAR(fire,removeFireSource), _fireKey] call CBA_fnc_localEvent;
};
};
}; };
_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 { 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 [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
"", "",
"Billboard", "Billboard",
1, 1,
(0.1 + (random 0.2)) * _factor, (0.1 + random 0.2) * _factor,
_particlePosition, _particlePosition,
[0, 0, 15 * (_factor / 2)], [0, 0, 15 * (_factor / 2)],
0, 0,
@ -87,69 +116,64 @@ if (isServer) then {
0, 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 { 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 [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal",16,2,32], ["\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, _ringOrigin,
[0, 20 * (_factor / 2), 0], [0, 20 * (_factor / 2), 0],
0, 10, 7.9, 0.075, 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]], [[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 [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\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, _ringOrigin,
[0, -20 * (_factor / 2), 0], [0, -20 * (_factor / 2), 0],
0, 10, 7.9, 0.075, 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]], [[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 [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\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, _ringOrigin,
[20 * (_factor / 2), 0, 0], [20 * (_factor / 2), 0, 0],
0, 10, 7.9, 0.075, 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]], [[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 [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\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], [-0.1 + random 0.2, -0.1 + random 0.2, -1],
[-20 * (_factor / 2), 0, 0], [-20 * (_factor / 2), 0, 0],
0, 10, 7.9, 0.075, 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]], [[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); private _dir = 20 * (_factor / 2);
drop [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\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, _ringOrigin,
[_dir, _dir, 0], [_dir, _dir, 0],
0, 10, 7.9, 0.075, 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]], [[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); _dir = -20 * (_factor / 2);
@ -159,9 +183,9 @@ if (isServer) then {
_ringOrigin, _ringOrigin,
[_dir, _dir, 0], [_dir, _dir, 0],
0, 10, 7.9, 0.075, 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]], [[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); _dir = 20 * (_factor / 2);
@ -171,31 +195,30 @@ if (isServer) then {
_ringOrigin, _ringOrigin,
[_dir, -_dir, 0], [_dir, -_dir, 0],
0, 10, 7.9, 0.075, 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]], [[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); _dir = 20 * (_factor / 2);
drop [ drop [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32], ["\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, _ringOrigin,
[-_dir, _dir, 0], [-_dir, _dir, 0],
0, 10, 7.9, 0.075, 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]], [[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"]; (getVehicleTIPars _vehicle) params ["_tiEngine", "_tiWheels", "_tiWeapon"];
_obj setVehicleTIPars [
// formula is designed to have the temperature ramp up quickly and then level out // Formula is designed to have the temperature ramp up quickly and then level out
(_tiEngine + (_intensity * 0.01))/1.005, _vehicle setVehicleTIPars [
(_tiWheels + (_intensity * 0.004))/1.002, // wheels//tracks are further away from burning parts (_tiEngine + _intensity * 0.01) / 1.005,
(_tiWeapon + (_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;
}, 0, [_obj, _jet, _ring, _time, CBA_missionTime, _light, _fireSelection, _sound, _intensity]] call CBA_fnc_addPerFrameHandler;

View File

@ -1,135 +1,174 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Glowbal * 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: * Arguments:
* 0: vehicle <OBJECT> * 0: Object <OBJECT>
* 1: Ammo Array <ARRAY> * 1: Magazine array <ARRAY>
* - 0: Magazine Classname <STRING> * - 0: Magazine classname <STRING>
* - 1: Ammo Count <NUMBER> * - 1: Ammo count <NUMBER>
* 2: Total Ammo Count <NUMBER> * 2: Total ammo count <NUMBER>
* 3: Destroy when finished <BOOL> (default: false)
* 4: Killer <OBJECT> (default: objNull)
* 5: Instigator <OBJECT> (default: objNull)
* 6: Initial delay <NUMBER> (default: 0)
* *
* Return Value: * Return Value:
* None * Nothing Useful
* *
* Example: * Example:
* [_vehicle, magazinesAmmo _vehicle] call ace_cookoff_fnc_detonateAmmunition * [cursorObject, magazinesAmmo vehicle player, 1000] call ace_cookoff_fnc_detonateAmmunition
* *
* Public: No * Public: No
*/ */
params ["_vehicle", "_magazines", "_totalAmmo"]; if (!isServer) exitWith {};
if (GVAR(enable) == 0) exitWith {}; params ["_object", "_magazines", "_totalAmmo", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]];
if !(GVAR(enableAmmoCookoff)) exitWith {};
if (isNull _vehicle) exitWith {}; // vehicle got deleted if (isNull _object) exitWith {};
if (_magazines isEqualTo []) exitWith {}; // nothing to detonate anymore
if (underwater _vehicle) exitWith {}; // 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 _magazineIndex = floor random (count _magazines);
private _magazine = _magazines select _magazineIndex; private _magazine = _magazines select _magazineIndex;
_magazine params ["_magazineClassname", "_amountOfMagazines"]; _magazine params ["_magazineClassname", "_ammoCount"];
if (_amountOfMagazines > 0) exitWith { // Make sure ammo is at least 0
private _removed = _amountOfMagazines min floor(1 + random(6 / GVAR(ammoCookoffDuration))); _ammoCount = _ammoCount max 0;
_amountOfMagazines = _amountOfMagazines - _removed; // Remove some ammo, which will be detonated
if (_amountOfMagazines <= 0) then { private _removed = _ammoCount min floor (1 + random (6 / GVAR(ammoCookoffDuration)));
_ammoCount = _ammoCount - _removed;
if (_ammoCount <= 0) then {
_magazines deleteAt _magazineIndex; _magazines deleteAt _magazineIndex;
} else { } else {
_magazine set [1, _amountOfMagazines]; // clear out the magazine _magazine set [1, _ammoCount]; // remove ammo that was detonated
}; };
private _timeBetweenAmmoDetonation = (((random 10) / (sqrt _totalAmmo)) min MAX_TIME_BETWEEN_AMMO_DET) max 0.1;
private _timeBetweenAmmoDetonation = ((random 10 / sqrt _totalAmmo) min MAX_TIME_BETWEEN_AMMO_DET) max 0.1;
TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation); TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation);
_totalAmmo = _totalAmmo - _removed; _totalAmmo = _totalAmmo - _removed;
private _ammo = getText (configFile >> "CfgMagazines" >> _magazineClassname >> "ammo"); // Detonate the remaining ammo after a delay
private _ammoCfg = configFile >> "CfgAmmo" >> _ammo; [FUNC(detonateAmmunition), [_object, _magazines, _totalAmmo, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
private _speedOfAmmo = getNumber (configFile >> "CfgMagazines" >> _magazineClassname >> "initSpeed"); // Get magazine info, which is used to spawn projectiles
private _simType = getText (_ammoCfg >> "simulation"); private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname;
private _ammo = getText (_configMagazine >> "ammo");
private _configAmmo = configFile >> "CfgAmmo" >> _ammo;
private _effect2pos = _vehicle selectionPosition "destructionEffect2"; private _simType = toLower getText (_configAmmo >> "simulation");
private _speed = random (getNumber (_configMagazine >> "initSpeed") / 10) max 1;
private _spawnProjectile = { private _effect2pos = _object selectionPosition "destructionEffect2";
params ["_vehicle", "_ammo", "_speed", "_flyAway"];
// 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];
private _spawnPos = _vehicle modelToWorld [-0.2 + (random 0.4), -0.2 + (random 0.4), random 3];
if (_spawnPos select 2 < 0) then { if (_spawnPos select 2 < 0) then {
_spawnPos set [2, 0]; _spawnPos set [2, 0];
}; };
private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"]; private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"];
if (_flyAway) then { if (_flyAway) then {
private _vectorAmmo = [(-1 + (random 2)), (-1 + (random 2)), -0.2 + (random 1)]; private _vectorAmmo = [-1 + random 2, -1 + random 2, -0.2 + random 1];
private _velVec = _vectorAmmo vectorMultiply _speed; private _vectorVelocity = _vectorAmmo vectorMultiply _speed;
_projectile setVectorDir _velVec;
_projectile setVelocity _velVec; _projectile setVectorDir _vectorVelocity;
_projectile setVelocity _vectorVelocity;
} else { } else {
_projectile setDamage 1; _projectile setDamage 1;
}; };
_projectile;
}; };
private _speed = random (_speedOfAmmo / 10) max 1; switch (_simType) do {
case "shotbullet": {
if (toLower _simType == "shotbullet") then { 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)];
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 _object, 2, 1, 1250];
playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1250];
if (random 1 < 0.6) then { if (random 1 < 0.6) then {
[_vehicle, _ammo, _speed, true] call _spawnProjectile; [_object, _ammo, _speed, true] call _fnc_spawnProjectile;
}; };
}; };
if (toLower _simType == "shotshell") then { case "shotshell": {
private _sound = selectRandom [QUOTE(PATHTO_R(sounds\heavy_crack_close.wss)), QUOTE(PATHTO_R(sounds\heavy_crack_close_filtered.wss))]; private _sound = selectRandom [QPATHTO_R(sounds\heavy_crack_close.wss), QPATHTO_R(sounds\heavy_crack_close_filtered.wss)];
playSound3D [_sound, objNull, false, (getPosASL _vehicle), 2, 1, 1300]; playSound3D [_sound, objNull, false, getPosASL _object, 2, 1, 1300];
if (random 1 < 0.15) then { 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 { if (random 1 < 0.9) then {
_speed = 0; _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 { } 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 { if (random 1 < 0.5) then {
// Not all explosives detonate on destruction, some have scripted alternatives // Not all explosives detonate on destruction, some have scripted alternatives
private _scripted = getNumber (_ammoCfg >> "triggerWhenDestroyed") == 1; if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then {
if !(_scripted) then { _ammo = getText (_configAmmo >> QEGVAR(explosives,explosive));
_ammo = getText (_ammoCfg >> "ace_explosives_Explosive");
}; };
// If a scripted alternative doesn't exist use generic explosion // If a scripted alternative doesn't exist use generic explosion
if (_ammo != "") then { if (_ammo != "") then {
[_vehicle, _ammo, 0, false] call _spawnProjectile; [_object, _ammo, 0, false] call _fnc_spawnProjectile;
} else { } 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 { 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);

View File

@ -4,48 +4,28 @@
* Start fire in engine block of a car. * Start fire in engine block of a car.
* *
* Arguments: * Arguments:
* 0: Vehicle <Object> * 0: Vehicle <OBJECT>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* (vehicle player) call ace_cookoff_fnc_engineFire * cursorObject call ace_cookoff_fnc_engineFire
* *
* Public: No * Public: No
*/ */
if (!isServer) exitWith {};
params ["_vehicle"]; params ["_vehicle"];
// If already smoking, stop
if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {}; if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {};
_vehicle setVariable [QGVAR(isEngineSmoking), true]; _vehicle setVariable [QGVAR(isEngineSmoking), true];
if (local _vehicle) then { // Spawn engine fire effects on all connected machines
[QGVAR(engineFire), _vehicle] call CBA_fnc_globalEvent; 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)); _vehicle setVariable [QGVAR(engineFireJipID), _jipID];
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;

View File

@ -0,0 +1,61 @@
#include "..\script_component.hpp"
/*
* Author: KoffeinFlummi, commy2
* Start fire in engine block of a car.
*
* Arguments:
* 0: Vehicle <OBJECT>
*
* 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;

View File

@ -4,16 +4,16 @@
* Gets all magazines inside of a vehicle. * Gets all magazines inside of a vehicle.
* *
* Arguments: * Arguments:
* 0: Vehicle <Object> * 0: Vehicle <OBJECT>
* *
* Return Value: * Return Value:
* 0: Ammo Array <ARRAY> * 0: Ammo array <ARRAY>
* - 0: Magazine Classname <STRING> * - 0: Magazine classname <STRING>
* - 1: Ammo Count <NUMBER> * - 1: Ammo count <NUMBER>
* 1: Total Ammo Count <NUMBER> * 1: Total ammo count <NUMBER>
* *
* Example: * Example:
* [vehicle player] call ace_cookoff_fnc_getVehicleAmmo * cursorObject call ace_cookoff_fnc_getVehicleAmmo
* *
* Public: No * Public: No
*/ */
@ -23,42 +23,52 @@ TRACE_1("getVehicleAmmo",_vehicle);
private _ammoToDetonate = []; private _ammoToDetonate = [];
private _totalAmmo = 0; private _totalAmmo = 0;
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgAmmo = configFile >> "CfgAmmo";
private _ammo = "";
// Get ammo from turrets // Get ammo from turrets
{ {
_x params ["_mag", "_turret", "_count"]; // If the turret is an FFV seat, it takes magazines from the soldier
// if the turret is an FFV seat, it takes magazines from the soldier _x params ["_magazine", "", "_count"];
if (_count > 0) then {
if (_mag call FUNC(isMagazineFlare)) then {continue}; if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then {
private _ammo = getText (configFile >> "CfgMagazines" >> _mag >> "ammo"); _ammo = getText (_cfgMagazines >> _magazine >> "ammo");
private _model = getText (configFile >> "CfgAmmo" >> _ammo >> "model");
if (_model == "\A3\weapons_f\empty") exitWith {TRACE_3("skipping",_mag,_ammo,_model);}; if (getText (_cfgAmmo >> _ammo >> "model") == "\A3\weapons_f\empty") then {
_ammoToDetonate pushBack [_mag, _count]; TRACE_2("skipping",_magazine,_ammo);
continue;
};
_ammoToDetonate pushBack [_magazine, _count];
_totalAmmo = _totalAmmo + _count; _totalAmmo = _totalAmmo + _count;
}; };
} forEach (magazinesAllTurrets [_vehicle, true]); } forEach (magazinesAllTurrets [_vehicle, true]);
// Get ammo from cargo space // Get ammo from cargo space
{ {
_x params ["_mag", "_count"]; _x params ["_magazine", "_count"];
if (_count > 0) then {
if (_mag call FUNC(isMagazineFlare)) then {continue}; if (_count > 0 && {!(_magazine call FUNC(isMagazineFlare))}) then {
_ammoToDetonate pushBack [_mag, _count]; _ammoToDetonate pushBack [_magazine, _count];
_totalAmmo = _totalAmmo + _count; _totalAmmo = _totalAmmo + _count;
}; };
} forEach (magazinesAmmoCargo _vehicle); } forEach (magazinesAmmoCargo _vehicle);
// Get ammo from transportAmmo / ace_rearm // 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); TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _vehicle);
_ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000]; _ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000];
_totalAmmo = _totalAmmo + 2000; _totalAmmo = _totalAmmo + 2000;
_ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100]; _ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100];
_totalAmmo = _totalAmmo + 100; _totalAmmo = _totalAmmo + 100;
_ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10]; _ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10];
_totalAmmo = _totalAmmo + 10; _totalAmmo = _totalAmmo + 10;
}; };

View File

@ -1,13 +1,13 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: KoffeinFlummi, commy2 * Author: KoffeinFlummi, commy2
* Handles all incoming damage for boxi * Handles all incoming damage for boxes.
* *
* Arguments: * Arguments:
* HandleDamage EH <ARRAY> * HandleDamage EH <ARRAY>
* *
* Return Value: * Return Value:
* Damage to be inflicted. <NUMBER> * Damage to be inflicted (can be nil) <NUMBER>
* *
* Example: * Example:
* _this call ace_cookoff_fnc_handleDamageBox * _this call ace_cookoff_fnc_handleDamageBox
@ -15,58 +15,60 @@
* Public: No * Public: No
*/ */
params ["_vehicle", "", "_damage", "_source", "_ammo", "_hitIndex", "_shooter"]; params ["_box", "", "_damage", "_source", "_ammo", "_hitIndex", "_instigator"];
// it's already dead, who cares? if (!local _box) exitWith {};
if (damage _vehicle >= 1) exitWith {};
// If cookoff is disabled exit // If it's already dead, ignore
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] in [0, false]) exitWith {}; 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"; private _hitpoint = "#structural";
if (_hitIndex != -1) then { if (_hitIndex != -1) then {
_hitpoint = toLower ((getAllHitPointsDamage _vehicle param [0, []]) select _hitIndex); _hitpoint = ((getAllHitPointsDamage _box) param [0, []]) select _hitIndex;
}; };
// get change in damage if !(_hitpoint == "#structural" && {_damage > 0.5}) exitWith {};
private _oldDamage = 0;
if (_hitpoint isEqualTo "#structural") then { // Catch fire when hit by an explosive round
_oldDamage = damage _vehicle;
} 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 { if (IS_EXPLOSIVE_AMMO(_ammo)) then {
_vehicle call FUNC(cookOffBox); [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent;
} else { } else {
// Need magazine to check for tracers // Get change in damage
private _mag = ""; private _oldDamage = if (_hitpoint == "#structural") then {
if (_source == _shooter) then { damage _box
_mag = currentMagazine _source;
} else { } else {
_mag = _source currentMagazineTurret ([_shooter] call CBA_fnc_turretPath); _box getHitIndex _hitIndex
}; };
private _magCfg = configFile >> "CfgMagazines" >> _mag;
// 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) // Magazine could have changed during flight time (just ignore if so)
if (getText (_magCfg >> "ammo") == _ammo) then { if (getText (_configMagazine >> "ammo") == _ammo) then {
// If magazine's tracer density is high enough then low chance for cook off // If magazine's tracer density is high enough then low chance for cook off
private _tracers = getNumber (_magCfg >> "tracersEvery"); private _tracers = getNumber (_configMagazine >> "tracersEvery");
if (_tracers >= 1 && {_tracers <= 4}) then { if (_tracers >= 1 && {_tracers <= 4}) then {
if (random 1 < _oldDamage*0.05) then { [QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent;
_vehicle call FUNC(cookOffBox);
};
}; };
}; };
}; };
// prevent destruction, let cook-off handle it if necessary // Prevent destruction, let cook-off handle it if necessary
_damage min 0.89 _damage min 0.89
} else {
_damage
};

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Cyruz * Author: Cyruz
* Checks if the magazine has ammo which is a flare * Checks if the magazine's ammo are flares.
* *
* Arguments: * Arguments:
* 0: Magazine <STRING> * 0: Magazine <STRING>
@ -10,15 +10,15 @@
* 0: If magazine is type of flare <BOOL> * 0: If magazine is type of flare <BOOL>
* *
* Example: * Example:
* ["3Rnd_UGL_FlareWhite_F"] call ace_cookoff_fnc_isMagazineFlare * "3Rnd_UGL_FlareWhite_F" call ace_cookoff_fnc_isMagazineFlare
* *
* Public: No * Public: No
*/ */
params ["_magazine"]; params ["_magazine"];
private _ammo = getText (configFile >> "CfgMagazines" >> _magazine >> "ammo"); private _configAmmo = configFile >> "CfgAmmo" >> getText (configFile >> "CfgMagazines" >> _magazine >> "ammo");
private _intensity = getNumber (configFile >> "CfgAmmo" >> _ammo >> "intensity"); private _intensity = getNumber (_configAmmo >> "intensity");
private _flare = getNumber (configFile >> "CfgAmmo" >> _ammo >> QEGVAR(grenades,flare)); private _flare = getNumber (_configAmmo >> QEGVAR(grenades,flare));
_intensity != 0 || _flare == 1 _intensity != 0 || _flare == 1

View File

@ -5,7 +5,7 @@
* *
* Arguments: * Arguments:
* 0: Vehicle <OBJECT> * 0: Vehicle <OBJECT>
* 1. Selections for smoke to come out of <ARRAY> (default: []) * 1: Selections for smoke to come out of <ARRAY> (default: [])
* *
* Return Value: * Return Value:
* None * None
@ -18,10 +18,12 @@
params ["_vehicle", ["_positions", []]]; params ["_vehicle", ["_positions", []]];
private _turretConfig = [_vehicle, [0]] call CBA_fnc_getTurret; // Make sure effects are cleaned up if vehicle is deleted
private _positionBarrelEnd = getText (_turretConfig >> "gunBeg"); [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]; private _smokeBarrel = "#particlesource" createVehicleLocal [0, 0, 0];
_smokeBarrel setParticleClass "MediumDestructionSmoke"; _smokeBarrel setParticleClass "MediumDestructionSmoke";
_smokeBarrel attachTo [_vehicle, [0, 0, 0], _positionBarrelEnd]; _smokeBarrel attachTo [_vehicle, [0, 0, 0], _positionBarrelEnd];
@ -31,7 +33,7 @@ private _effects = [_smokeBarrel];
{ {
private _position = [0, -2, 0]; private _position = [0, -2, 0];
if (_x isNotEqualTo "#noselection") then { if (_x != "#noselection") then {
_position = _vehicle selectionPosition _x; _position = _vehicle selectionPosition _x;
}; };

View File

@ -1,69 +1,69 @@
[ [
QGVAR(enable), "LIST", QGVAR(enable),
[LSTRING(enable_hd_name), LSTRING(enable_hd_tooltip)], "LIST",
[LSTRING(enable_name), LSTRING(enable_tooltip)],
LSTRING(category_displayName), LSTRING(category_displayName),
[[0, 1, 2], ["STR_A3_OPTIONS_DISABLED", ELSTRING(common,playerOnly), ELSTRING(common,playersAndAI)], 2], [[0, 1, 2], ["STR_A3_OPTIONS_DISABLED", ELSTRING(common,playerOnly), ELSTRING(common,playersAndAI)], 2],
true, // isGlobal 1,
{[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)}, {[QGVAR(enable), _this] call EFUNC(common,cbaSettings_settingChanged)}
true // Needs mission restart
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(enableFire), "CHECKBOX", QGVAR(cookoffDuration),
[LSTRING(enableFire_name), LSTRING(enableFire_tooltip)], "SLIDER",
[LSTRING(cookoffDuration_name), LSTRING(cookoffDuration_tooltip)],
LSTRING(category_displayName), LSTRING(category_displayName),
true, // default value [0, 5, 1, 1],
true, // isGlobal 1,
{[QGVAR(enableFire), _this] call EFUNC(common,cbaSettings_settingChanged)}, {[QGVAR(cookoffDuration), _this] call EFUNC(common,cbaSettings_settingChanged)}
false // Needs mission restart
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;
[ [
QGVAR(destroyVehicleAfterCookoff), "CHECKBOX", QGVAR(probabilityCoef),
[LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)], "SLIDER",
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",
[LSTRING(probabilityCoef_name), LSTRING(probabilityCoef_tooltip)], [LSTRING(probabilityCoef_name), LSTRING(probabilityCoef_tooltip)],
LSTRING(category_displayName), LSTRING(category_displayName),
[0,5,1,1], // [min, max, default value, trailing decimals (-1 for whole numbers only)] [0, 5, 1, 1],
true, // isGlobal 1,
{[QGVAR(probabilityCoef), _this] call EFUNC(common,cbaSettings_settingChanged)}, {[QGVAR(probabilityCoef), _this] call EFUNC(common,cbaSettings_settingChanged)}
true // Needs mission restart ] 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; ] call CBA_fnc_addSetting;

View File

@ -24,6 +24,7 @@
#define SMOKE_TIME 10.5 #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 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 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 MIN_TIME_BETWEEN_FLAMES 5
#define MAX_TIME_BETWEEN_FLAMES 15 #define MAX_TIME_BETWEEN_FLAMES 15
#define MAX_TIME_BETWEEN_AMMO_DET 25 #define MAX_TIME_BETWEEN_AMMO_DET 25

View File

@ -2,7 +2,7 @@
<Project name="ACE"> <Project name="ACE">
<Package name="CookOff"> <Package name="CookOff">
<Key ID="STR_ACE_CookOff_category_displayName"> <Key ID="STR_ACE_CookOff_category_displayName">
<English>ACE Cook off</English> <English>ACE Cook-off</English>
<Spanish>ACE Detonación inducida por calor</Spanish> <Spanish>ACE Detonación inducida por calor</Spanish>
<Italian>ACE Detonazione Munizioni</Italian> <Italian>ACE Detonazione Munizioni</Italian>
<Chinese>ACE 殉爆效果</Chinese> <Chinese>ACE 殉爆效果</Chinese>
@ -16,38 +16,14 @@
<Portuguese>ACE Cook off</Portuguese> <Portuguese>ACE Cook off</Portuguese>
<Czech>ACE Vznícení munice</Czech> <Czech>ACE Vznícení munice</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enable_hd_name"> <Key ID="STR_ACE_CookOff_enable_name">
<English>Damage handling and turret effects</English> <English>Enable vehicle cook-off</English>
<Spanish>Daño y efectos de torreta</Spanish>
<German>Schadensberechnung und Geschützturmeffekte</German>
<Japanese>損傷処理と砲塔の効果</Japanese>
<Russian>Обработка урона и эффектов срыва башни</Russian>
<Portuguese>Manipulação de dano e efeitos de torre</Portuguese>
<French>Dégâts et effets de tourelle</French>
<Chinese>傷害控制及炮塔效果</Chinese>
<Chinesesimp>损坏处理和炮塔效果</Chinesesimp>
<Italian>Gestione danni ed effetti torretta</Italian>
<Czech>Poškodit ovládání a efekty věže</Czech>
<Polish>Obsługa obrażeń i efekty wieży</Polish>
<Korean>피해량 조절 및 포탑에 효과 부여</Korean>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enable_hd_tooltip"> <Key ID="STR_ACE_CookOff_enable_tooltip">
<English>Changes damage handling for cook off and turret explosion effects</English> <English>Enables vehicle cook-off effects (fire and sound).</English>
<Spanish>Cambia el daño de la detonación inducida por calor y los efectos de la explosión de la torreta</Spanish>
<German>Ändert die Schadensberechnung für die Durchzündung und die Explosionseffekte des Geschützturmes</German>
<Japanese>誘爆の損傷処理と砲塔の爆発効果を変更します。</Japanese>
<Russian>Изменяет обработку урона для возгорания и эффекта срыва башни</Russian>
<Portuguese>Modifica a manipulação de dano para o cozinhamento de munição e efeitos de explosão da torre</Portuguese>
<French>Modifie la gestion des dégâts pour l'auto-inflammation et les effets d'explosion de tourelle.</French>
<Chinese>更改殉爆以及炮塔爆炸之傷害控制</Chinese>
<Chinesesimp>改变殉爆和炮塔爆炸的损坏处理效果</Chinesesimp>
<Italian>Modifica la gestione dei danni per l'esplosione di munizioni e gli effetti di esplosione della torretta</Italian>
<Czech>Změní poškození ovládání a efekty výbuchu veže</Czech>
<Polish>Zmienia obsługę obrażeń podczas samozapłonu i eksplozji wieży</Polish>
<Korean>쿡오프로 인해 피해량의 변화와 포탑 터짐현상을 결정합니다.</Korean>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enableBoxCookoff_name"> <Key ID="STR_ACE_CookOff_enableBoxCookoff_name">
<English>Enable ammo box cook off</English> <English>Enable ammo box cook-off</English>
<Spanish>Habilitar detonación inducida por calor en las cajas de munición</Spanish> <Spanish>Habilitar detonación inducida por calor en las cajas de munición</Spanish>
<Japanese>弾薬箱の誘爆を有効化</Japanese> <Japanese>弾薬箱の誘爆を有効化</Japanese>
<German>Durchzündung für Munitionskisten ermöglichen</German> <German>Durchzündung für Munitionskisten ermöglichen</German>
@ -77,97 +53,31 @@
<Czech>Zapíná vznícení munice v krabicích.</Czech> <Czech>Zapíná vznícení munice v krabicích.</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enableAmmoCookoff_name"> <Key ID="STR_ACE_CookOff_enableAmmoCookoff_name">
<English>Enable Ammunition cook off</English> <English>Enable vehicle ammo cook-off</English>
<Spanish>Habilitar la detonación inducida por calor en la munición</Spanish>
<Japanese>弾薬の誘爆を有効化</Japanese>
<German>Durchzündung für Munition ermöglichen</German>
<Korean>탄약 쿡오프 현상 활성화</Korean>
<Polish>Aktywuj samozapłon amunicji</Polish>
<French>Auto-inflammation des munitions</French>
<Italian>Abilita Esplosione Munizioni</Italian>
<Chinese>開啟彈藥殉爆效果</Chinese>
<Chinesesimp>开启弹药殉爆效果</Chinesesimp>
<Russian>Разрешить детонацию боекомплекта</Russian>
<Portuguese>Permitir cozinhar munição</Portuguese>
<Czech>Povolit vznícení munice</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enableAmmoCookoff_tooltip"> <Key ID="STR_ACE_CookOff_enableAmmoCookoff_tooltip">
<English>Enables Ammunition cook off. Fires ammunition projectiles while vehicle is on fire and has ammunition.</English> <English>Enables cooking off of vehicle ammunition. Fires ammunition projectiles while vehicle has ammunition remaining.</English>
<Spanish>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</Spanish> </Key>
<Japanese>弾薬が誘爆します。車両が燃えると、搭載している弾薬が激しく燃え上がります。</Japanese> <Key ID="STR_ACE_CookOff_cookoffDuration_name">
<German>Ermöglicht Durchzündung von Munition. Feuert Projektile der Munition ab, solange das Fahrzeug brennt und Munition besitzt.</German> <English>Vehicle cook-off duration multiplier</English>
<Polish>Aktywuje samozapłon amunicji. Wystrzeliwuje pociski podczas gdy pojazd płonie i posiada amunicję.</Polish> </Key>
<French>Permet l'auto-inflammation des munitions. Tire des projectiles tant que le véhicule est en feu et contient des munitions.</French> <Key ID="STR_ACE_CookOff_cookoffDuration_tooltip">
<Italian>Abilita l'esplosione di munizioni. Spara proiettili di munizioni quando il veicolo va a fuoco e contiene ancora munizioni.</Italian> <English>Multiplier for how long vehicle cook-off lasts.\nSetting to 0 will disable cookoff.</English>
<Chinese>開啟彈藥殉爆效果。當一台載有彈藥的載具起火時, 將會有殉爆的效果</Chinese>
<Chinesesimp>开启弹药殉爆效果。当一台载有弹药的载具起火时,将会有殉爆的效果。</Chinesesimp>
<Korean>쿡오프 현상을 활성화 합니다. 이것은 탄약에 불이 붙어 있는 동안 주변에 발사체를 발사합니다.</Korean>
<Russian>Активирует детонацию боекомплекта в горящей технике.</Russian>
<Portuguese>Permite que a munição cozinhe. Dispara projéteis de munição enquanto o veículo está em chamas e tem munição.</Portuguese>
<Czech>Zapíná vznícení munice. Vystřeluje projektily po dobu kdy vozidlo hoří a má munici.</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_ammoCookoffDuration_name"> <Key ID="STR_ACE_CookOff_ammoCookoffDuration_name">
<English>Ammunition cook off duration</English> <English>Ammo cook-off duration multiplier</English>
<Spanish>Duración de la detonación inducida por calor de la munición</Spanish>
<German>Munitionsdurchzündungsdauer</German>
<Polish>Czas trwania samozapłonu amunicji</Polish>
<Japanese>弾薬の誘爆持続時間</Japanese>
<French>Durée d'auto-inflammation des munitions</French>
<Italian>Durata Esplosione Munizioni</Italian>
<Chinese>彈藥殉爆效果持續時間</Chinese>
<Chinesesimp>弹药殉爆效果持续时间</Chinesesimp>
<Korean>쿡오프 지속 시간</Korean>
<Russian>Длительность детонации боеприпасов</Russian>
<Portuguese>Duração do cozinhamento de munição</Portuguese>
<Czech>Doba trvání vznícení munice</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_ammoCookoffDuration_tooltip"> <Key ID="STR_ACE_CookOff_ammoCookoffDuration_tooltip">
<English>Multiplier for how long cook off lasts [Setting to 0 will disable ammo cookoff]</English> <English>Multiplier for how long ammunition cook-off lasts, for both vehicles and ammo boxes.\nSetting to 0 will disable ammo cookoff.</English>
<Spanish>Multiplicador de cuanto dura la detonación inducida por calor [Ponerlo a cero la deshabilita]</Spanish>
<German>Faktor für die Munitionsdurchzündungsdauer [0 zum Deaktivieren]</German>
<French>Multiplicateur permettant de régler la durée durant laquelle les munitions continuent d'exploser [Une valeur de 0 désactive l'auto-inflammation].</French>
<Polish>Mnożnik decydujący jak długo ma trwać samozapłon amunicji [Ustawienie na 0 spowoduje wyłącznie samozapłonu]</Polish>
<Japanese>誘爆の持続時間を乗数で設定します。[0 に設定で誘爆を無効化]</Japanese>
<Italian>Moltiplicatore della durata delle esplosioni di munizioni [Se impostato su 0 disabiliterà le esplosioni delle munizioni]</Italian>
<Chinese>設定彈藥殉爆效果會持續多久時間 [輸入0來關閉殉爆效果]</Chinese>
<Chinesesimp>设定弹药殉爆效果会持续多久时间 [输入0来关闭殉爆效果]</Chinesesimp>
<Korean>쿡오프 지속 시간의 배수 [0 이면 비활성]</Korean>
<Russian>Множитель длительности детонации [0 - отключает детонацию боеприпасов]</Russian>
<Portuguese>Multiplicação da duração do cozinhamento [0 faz com que o cozinhamento seja desativado]</Portuguese>
<Czech>Multiplikátor doby trvání vznícení munice [Nastavte 0 pro vypnutí vznícení munice]</Czech>
</Key> </Key>
<Key ID="STR_ACE_CookOff_probabilityCoef_name"> <Key ID="STR_ACE_CookOff_probabilityCoef_name">
<English>Cook-off probability coefficient</English> <English>Vehicle cook-off probability multiplier</English>
<Spanish>Coeficiente de probabilidad de detonación inducida por calor</Spanish>
<Japanese>誘爆の可能性係数</Japanese>
<Italian>Coefficiente Probabilità Esplosione</Italian>
<German>Faktor für Wahrscheinlichkeit der Durchzündung</German>
<Chinese>殉爆發生機率係數</Chinese>
<Chinesesimp>殉爆发生机率系数</Chinesesimp>
<French>Coefficient de probabilité d'auto-inflammation</French>
<Polish>Współczynnik prawdopodobieństwa samozapłonu</Polish>
<Russian>Коэф. вероятности детонации</Russian>
<Portuguese>Probabilidade de Cozinhar</Portuguese>
<Czech>Koeficient pravděpodobnosti vznícení munice</Czech>
<Korean>쿡오프 발생 확률 계수</Korean>
</Key> </Key>
<Key ID="STR_ACE_CookOff_probabilityCoef_tooltip"> <Key ID="STR_ACE_CookOff_probabilityCoef_tooltip">
<English>Multiplier for cook-off probability. Higher value results in higher cook-off probability</English> <English>Multiplier for vehicle cook-off probability. Higher value results in higher cook-off probability.\nSetting to 0 will disable cookoff.</English>
<Spanish>Multiplicador de probabilidad de detonación inducida por calor. Valores más altos producen mayor probabilidad</Spanish>
<Japanese>誘爆する可能性の乗数。高い値では誘爆する可能性が高まります。</Japanese>
<Italian>Moltiplicatore per la probabilità dell'esplosione di munizioni. Un valore più alto aumenta la probabilità.</Italian>
<German>Faktor für Wahrscheinlichkeit der Durchzündung. Ein höherer Wert führt zu höherer Durchzündungswahrscheinlichkeit.</German>
<Chinese>調整殉爆發生機率係數。值越高代表越容易發生殉爆</Chinese>
<Chinesesimp>调整殉爆发生机率系数。值越高代表越容易发生殉爆。</Chinesesimp>
<French>Multiplicateur de probabilité de l'auto-inflammation. Plus la valeur est élevée, plus la probabilité de combustion est grande.</French>
<Polish>Mnożnik prawdopodobieństwa samozapłonu. Większa wartość oznacza większe prawdopodobieństwo samozapłonu</Polish>
<Russian>Множитель коэффициента вероятности детонации. Чем выше значение, тем выше вероятность</Russian>
<Portuguese>Multiplicador para a chance de cozinhamento. Valores mais altos aumentam as chances de ocorrer.</Portuguese>
<Czech>Multiplikátor pro pravděpodobnost vznícení munice. Vyšší hodnota znamená vyšší šanci vznícení munice.</Czech>
<Korean>쿡오프가 일어날 확률에 계수를 곱합니다. 더 큰 숫자는 더 높은 확률의 쿡오프를 일으킵니다.</Korean>
</Key> </Key>
<Key ID="STR_ACE_CookOff_destroyVehicleAfterCookoff_name"> <Key ID="STR_ACE_CookOff_destroyVehicleAfterCookoff_name">
<English>Destroy Vehicles After Cook-off</English> <English>Destroy vehicles after cook-off</English>
<Korean>쿡오프 후 차량 파괴</Korean> <Korean>쿡오프 후 차량 파괴</Korean>
<Chinesesimp>殉爆发生后摧毁载具</Chinesesimp> <Chinesesimp>殉爆发生后摧毁载具</Chinesesimp>
<Russian>Уничтожать технику после детонации</Russian> <Russian>Уничтожать технику после детонации</Russian>
@ -189,31 +99,5 @@
<French>Contrôle si les véhicules seront toujours détruits après l'auto-inflammation.</French> <French>Contrôle si les véhicules seront toujours détruits après l'auto-inflammation.</French>
<Portuguese>Define se os veículos serão sempre destruídos após cozinhamento.</Portuguese> <Portuguese>Define se os veículos serão sempre destruídos após cozinhamento.</Portuguese>
</Key> </Key>
<Key ID="STR_ACE_CookOff_enableFire_name">
<English>Enable Cook-Off Vehicle Fire</English>
<Japanese>誘爆火災を有効化</Japanese>
<French>Véhicules - Feu durant l'auto-inflammation</French>
<Russian>Вкл. горение техники от детонации</Russian>
<German>Aktiviert das in Brand setzen des Fahrzeugs während des Durchzündens der Munition</German>
<Italian>Abilita incendiamento veicoli</Italian>
<Polish>Włącz pożar pojazdu podczas samozapłonu</Polish>
<Chinesesimp>启用殉爆载具火灾</Chinesesimp>
<Korean>차량 쿡오프 화재 활성화</Korean>
<Spanish>Habilitar incendio a causa de la detonación inducida por calor</Spanish>
<Portuguese>Ativar incêndio de veículo durante cozinhamento</Portuguese>
</Key>
<Key ID="STR_ACE_CookOff_enableFire_tooltip">
<English>Whether or not vehicles will catch on fire during cook-off</English>
<Japanese>誘爆により車両が炎上するかどうかを設定します。</Japanese>
<French>Définit si les véhicules prennent feu durant l'auto-inflammation de leurs munitions.</French>
<Russian>Будет ли техника гореть при детонации боеприпасов</Russian>
<German>Ob Fahrzeuge in Brand gesetzt werden, während deren Munition durchzündet.</German>
<Italian>Determina se veicoli cominceranno a bruciare se le loro munizioni esplodono.</Italian>
<Polish>Określa, czy pojazdy zapalą się podczas samozapłonu ich amunicji.</Polish>
<Chinesesimp>车辆在殉爆过程中是否会起火</Chinesesimp>
<Korean>쿡오프가 일어나면 차량에 불이 붙습니다.</Korean>
<Spanish>Define si los vehículos salen ardiendo despues de una detonación inducida por calor.</Spanish>
<Portuguese>Define se os veículos pegarão fogo durante o cozinhamento.</Portuguese>
</Key>
</Package> </Package>
</Project> </Project>

View File

@ -175,10 +175,12 @@ if (isServer) then {
}; };
if (_x isKindOf "ReammoBox_F") then { if (_x isKindOf "ReammoBox_F") then {
if ( if (
"ace_cookoff" call EFUNC(common,isModLoaded) && (["ace_cookoff"] call EFUNC(common,isModLoaded)) &&
{GETVAR(_x,EGVAR(cookoff,enableAmmoCookoff),EGVAR(cookoff,enableAmmobox))} {EGVAR(cookoff,enableAmmobox)} &&
{EGVAR(cookoff,ammoCookoffDuration) != 0} &&
{_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]}
) then { ) then {
_x call EFUNC(cookoff,cookOffBox); [QEGVAR(cookOff,cookOffBox), [_box, objNull, objNull]] call CBA_fnc_serverEvent;
} else { } else {
_x setDamage 1; _x setDamage 1;
}; };
@ -232,10 +234,7 @@ private _enginePosition = _vehicle modelToWorld (_vehicle selectionPosition _eng
if (_position distance _enginePosition < EFFECT_SIZE * 2) then { if (_position distance _enginePosition < EFFECT_SIZE * 2) then {
_vehicle setHit [_engineSelection, 1]; _vehicle setHit [_engineSelection, 1];
if ("ace_cookoff" call EFUNC(common,isModLoaded)) then { if (["ace_cookoff"] call EFUNC(common,isModLoaded)) then {
private _enabled = _vehicle getVariable [QEGVAR(cookoff,enable), EGVAR(cookoff,enable)]; [QEGVAR(cookoff,engineFire), _vehicle] call CBA_fnc_serverEvent;
if (_enabled in [2, true] || {_enabled isEqualTo 1 && {fullCrew [_vehicle, "", false] findIf {isPlayer (_x select 0)} != -1}}) then {
_vehicle call EFUNC(cookoff,engineFire);
};
}; };
}; };

View File

@ -37,6 +37,6 @@ if (_hitIndex >= 0) then {
_vehicle setHitPointDamage [_hitPoint, _damage, true]; _vehicle setHitPointDamage [_hitPoint, _damage, true];
}; };
if (_hitPoint isEqualTo "hitengine" && { _damage > 0.9 }) then { if (_hitPoint == "hitengine" && {_damage > 0.9}) then {
_vehicle call EFUNC(cookoff,engineFire); [QEGVAR(cookoff,engineFire), _vehicle] call CBA_fnc_serverEvent;
}; };

View File

@ -23,7 +23,7 @@ if (_vehicleAmmo isEqualTo []) then {
_vehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo); _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 { if ((_vehicleAmmo select 1) > 0) then {
{ {

View File

@ -23,7 +23,9 @@
params ["_vehicle", "_chanceOfFire", "_intensity", ["_injurer", objNull], ["_hitPart", ""], ["_canRing", false], ["_canJet", true]]; 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 { if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith {
private _configOf = configOf _vehicle; 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 // 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; [QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, nil, _canJet]] call CBA_fnc_serverEvent;
_vehicle setVariable [QGVAR(cookingOff), true];
LOG_4("Cooking-off [%1] with a chance-of-fire [%2] - Delayed Smoke | Detonate after cookoff [%3 | %4]",_vehicle,_chanceOfFire,_delayWithSmoke,_detonateAfterCookoff); 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); [_vehicle] spawn FUNC(abandon);
LOG_1("[%1] is on fire is bailing",_vehicle); LOG_1("[%1] is on fire is bailing",_vehicle);

View File

@ -12,43 +12,22 @@ version:
patch: 0 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 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.
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;
};
```

View File

@ -110,9 +110,10 @@ MenuType: 0 = Interaction, 1 = Self Interaction
| Event Key | Parameters | Locality | Type | Description | | Event Key | Parameters | Locality | Type | Description |
|----------|---------|---------|---------|---------|---------| |----------|---------|---------|---------|---------|---------|
|`ace_cookoff_cookOff` | _vehicle | Global | Listen | Vehicle cook off 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 | Global | Listen | Ammo box cook off has started |`ace_cookoff_cookOffBox` | [_box, _killer, _instigator] | Server | Callable | Start ammo box cook-off
|`ace_cookoff_engineFire` | _vehicle | Global | Listen | Engine fire has started |`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`) ### 2.11 Attach (`ace_attach`)

View File

@ -47,7 +47,7 @@ Default: 0.5
#### 1.1.5 `ace_vehicle_damage_turretFireProb` #### 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 Default: 0.2