mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Cookoff - Mini-Rewrite (#9758)
* Cook-off improvements * More changes * Update fnc_getVehicleAmmo.sqf * Better engine fire placement * Update fnc_detonateAmmunition.sqf * Update XEH_postInit.sqf * Update fnc_getVehicleAmmo.sqf * Update events-framework.md * Various improvements * Separate effect handling * Tweaks * Update XEH_postInit.sqf * Prevent double ammo detonation * Fixed objects not being able to cook-off again * Added incendiary rounds as source of box cookoff * Converted enable setting to bool * Fixed brackets * Update fnc_cookOff.sqf * Update CfgEden.hpp * Removed GVAR(enable), added GVAR(enableFire) back * Update initSettings.inc.sqf * Update events-framework.md * Update addons/cookoff/functions/fnc_cookOffEffect.sqf * Restructured, redid API events * Fix effect for JIP, minor optimisations * Removed `cbaSettings_settingChanged` * Renamed variables, tweaked string table entries * Update fire damage #9991 * Capitalize comments again * Fix cookoff for very short durations and fix effect removal being too quick
This commit is contained in:
parent
73111fa0fd
commit
c44a1e7ea7
@ -191,6 +191,7 @@ if (isServer) then {
|
||||
[QGVAR(switchMove), {(_this select 0) switchMove (_this select 1)}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(setVectorDirAndUp), {(_this select 0) setVectorDirAndUp (_this select 1)}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(addWeaponItem), {(_this select 0) addWeaponItem [(_this select 1), (_this select 2)]}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(removeMagazinesTurret), {(_this select 0) removeMagazinesTurret [_this select 1, _this select 2]}] call CBA_fnc_addEventHandler;
|
||||
|
||||
[QGVAR(setVanillaHitPointDamage), {
|
||||
params ["_object", "_hitPointAnddamage"];
|
||||
|
@ -1,12 +1,8 @@
|
||||
|
||||
class ACE_Settings {
|
||||
class GVAR(enable) {
|
||||
movedToSqf = 1;
|
||||
};
|
||||
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) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
class CfgCloudlets {
|
||||
class GVAR(CookOff) {
|
||||
interval = 0.004;
|
||||
|
@ -1,28 +1,27 @@
|
||||
|
||||
class Cfg3DEN {
|
||||
class Object {
|
||||
class AttributeCategories {
|
||||
class ace_attributes {
|
||||
class Attributes {
|
||||
class GVAR(enable) {
|
||||
property = QGVAR(enable);
|
||||
class GVAR(enable) { // setting was previously GVAR(enable), so maintain for backwards compatiblity with missions
|
||||
property = QGVAR(enable); // same as above
|
||||
control = "Checkbox";
|
||||
displayName = CSTRING(enable_hd_name);
|
||||
tooltip = CSTRING(enable_hd_tooltip);
|
||||
expression = QUOTE(if !(_value) then {_this setVariable [ARR_3('%s',_value,true)];};);
|
||||
displayName = CSTRING(enableFire_name);
|
||||
tooltip = CSTRING(enableFire_tooltip);
|
||||
expression = QUOTE(if (!_value) then {_this setVariable [ARR_3('%s',_value,true)]});
|
||||
typeName = "BOOL";
|
||||
condition = "objectVehicle";
|
||||
defaultValue = QUOTE((GETMVAR(QGVAR(enable),0)) in [ARR_2(1,2)]);
|
||||
defaultValue = QUOTE(GETMVAR(QGVAR(enableFire),true));
|
||||
};
|
||||
class GVAR(enableAmmoCookoff) {
|
||||
property = QGVAR(enableAmmoCookoff);
|
||||
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)});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
class Extended_PreStart_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
class CfgSFX {
|
||||
class GVAR(CookOff_low) {
|
||||
name = QGVAR(cookoff_low);
|
||||
|
@ -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,14 @@ 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};
|
||||
};
|
||||
|
||||
class MRAP_02_base_F: Car_F {
|
||||
GVAR(engineSmokeOffset)[] = {0,-2,0};
|
||||
};
|
||||
|
||||
class MRAP_03_base_F: Car_F {
|
||||
GVAR(engineSmokeOffset)[] = {0,-2,0};
|
||||
};
|
||||
|
||||
class Quadbike_01_base_F: Car_F {
|
||||
GVAR(engineSmokeOffset)[] = {0,1,0};
|
||||
};
|
||||
|
||||
class Truck_F;
|
||||
class Truck_02_base_F: Truck_F {
|
||||
GVAR(engineSmokeOffset)[] = {0,-2.6,-0.1};
|
||||
};
|
||||
|
||||
class Truck_02_MRL_base_F: Truck_02_base_F {
|
||||
GVAR(engineSmokeOffset)[] = {0,0.3,-0.1};
|
||||
};
|
||||
};
|
||||
|
@ -1,10 +1,12 @@
|
||||
|
||||
PREP(handleDamageBox);
|
||||
PREP(engineFire);
|
||||
PREP(cookOff);
|
||||
PREP(smoke);
|
||||
PREP(cookOffEffect);
|
||||
PREP(cookOffBox);
|
||||
PREP(detonateAmmunition);
|
||||
PREP(cookOffBoxLocal);
|
||||
PREP(cookOffBoxServer);
|
||||
PREP(cookOffLocal);
|
||||
PREP(cookOffServer);
|
||||
PREP(detonateAmmunitionServer);
|
||||
PREP(detonateAmmunitionServerLoop);
|
||||
PREP(engineFireLocal);
|
||||
PREP(engineFireServer);
|
||||
PREP(getVehicleAmmo);
|
||||
PREP(handleDamageBox);
|
||||
PREP(isMagazineFlare);
|
||||
PREP(smoke);
|
||||
|
@ -1,63 +1,64 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
[QGVAR(engineFire), LINKFUNC(engineFire)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOff), {
|
||||
params ["_vehicle"];
|
||||
if (local _vehicle) then {
|
||||
_this call FUNC(cookOff);
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffEffect), LINKFUNC(cookOffEffect)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffBoxLocal), LINKFUNC(cookOffBoxLocal)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffLocal), LINKFUNC(cookOffLocal)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(engineFireLocal), LINKFUNC(engineFireLocal)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(smoke), LINKFUNC(smoke)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffBox), LINKFUNC(cookOffBox)] call CBA_fnc_addEventHandler;
|
||||
|
||||
// handle cleaning up effects when vehicle is deleted mid-cookoff
|
||||
[QGVAR(addCleanupHandlers), {
|
||||
params ["_vehicle"];
|
||||
if (isServer) then {
|
||||
[QGVAR(cookOffBoxServer), LINKFUNC(cookOffBoxServer)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(cookOffServer), LINKFUNC(cookOffServer)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(detonateAmmunitionServer), LINKFUNC(detonateAmmunitionServer)] call CBA_fnc_addEventHandler;
|
||||
[QGVAR(engineFireServer), LINKFUNC(engineFire)] call CBA_fnc_addEventHandler;
|
||||
};
|
||||
|
||||
// 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"];
|
||||
// Handle cleaning up effects when objects are deleted mid cook-off
|
||||
["AllVehicles", "Deleted", {
|
||||
{
|
||||
deleteVehicle _x;
|
||||
} forEach ((_this select 0) getVariable [QGVAR(effects), []]);
|
||||
}, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
[QGVAR(cleanupEffects), [_vehicle]] call CBA_fnc_localEvent;
|
||||
}];
|
||||
|
||||
_vehicle setVariable [QGVAR(deletedEH), _deletedEH];
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
["ReammoBox_F", "Deleted", {
|
||||
{
|
||||
deleteVehicle _x;
|
||||
} forEach ((_this select 0) getVariable [QGVAR(effects), []]);
|
||||
}, true, [], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// Raised when the flames have subsided or after the ammo of a box has finished cooking off
|
||||
[QGVAR(cleanupEffects), {
|
||||
params ["_vehicle", ["_effects", []]];
|
||||
params ["_object"];
|
||||
|
||||
_effects = _effects + (_vehicle getVariable [QGVAR(effects), []]);
|
||||
if (_effects isNotEqualTo []) then {
|
||||
{ deleteVehicle _x } count _effects;
|
||||
};
|
||||
{
|
||||
deleteVehicle _x;
|
||||
} forEach (_object getVariable [QGVAR(effects), []]);
|
||||
|
||||
_object setVariable [QGVAR(effects), nil];
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
// Ammo box damage handling
|
||||
["ReammoBox_F", "init", {
|
||||
(_this select 0) addEventHandler ["HandleDamage", {
|
||||
if ((_this select 0) getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmobox)]) then {
|
||||
_this call FUNC(handleDamageBox);
|
||||
};
|
||||
}];
|
||||
}, nil, nil, true] call CBA_fnc_addClassEventHandler;
|
||||
// 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)}];
|
||||
}, true, [], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// Vehicle ammo cook-off (secondary explosions)
|
||||
["AllVehicles", "Killed", {
|
||||
if (!GVAR(enableAmmoCookoff) || {GVAR(ammoCookoffDuration) == 0}) exitWith {};
|
||||
|
||||
// secondary explosions
|
||||
["AllVehicles", "killed", {
|
||||
params ["_vehicle", "", "", "_useEffects"];
|
||||
if (
|
||||
_useEffects &&
|
||||
_vehicle getVariable [QGVAR(enableAmmoCookoff), GVAR(enableAmmoCookoff)]
|
||||
) 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;
|
||||
[FUNC(detonateAmmunition), [_vehicle, _mags, _total], _delay] call CBA_fnc_waitAndExecute;
|
||||
if (_useEffects && {_vehicle getVariable [QGVAR(enableAmmoCookoff), true]}) then {
|
||||
// We don't need to pass source and instigator, as vehicle is already dead
|
||||
[QGVAR(detonateAmmunitionServer), [
|
||||
_vehicle,
|
||||
false,
|
||||
objNull,
|
||||
objNull,
|
||||
random [MIN_AMMO_DETONATION_START_DELAY, (MIN_AMMO_DETONATION_START_DELAY + MAX_AMMO_DETONATION_START_DELAY) / 2, MAX_AMMO_DETONATION_START_DELAY]
|
||||
]] call CBA_fnc_serverEvent;
|
||||
};
|
||||
}, nil, ["Man","StaticWeapon"]] call CBA_fnc_addClassEventHandler;
|
||||
}, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
if (hasInterface) then {
|
||||
// Plays a sound locally, so that different sounds can be used for various distances
|
||||
@ -68,7 +69,7 @@ if (hasInterface) then {
|
||||
|
||||
private _distance = _object distance (positionCameraToWorld [0, 0, 0]);
|
||||
|
||||
TRACE_3("",_object,_sound,_maxDistance);
|
||||
TRACE_2("",_object,_sound);
|
||||
|
||||
// 3 classes of distances: close, mid and far, each having different sound files
|
||||
private _classDistance = switch (true) do {
|
||||
@ -94,6 +95,6 @@ if (hasInterface) then {
|
||||
if (!fileExists _sound) exitWith {};
|
||||
|
||||
// Obeys speed of sound and takes doppler effects into account
|
||||
playSound3D [_sound, objNull, insideBuilding _object >= 0.5, getPosASL _object, _volume, _pitch + (random 0.2) - 0.1, _maxDistance, 0, true];
|
||||
playSound3D [_sound, objNull, false, getPosASL _object, _volume, _pitch + (random 0.2) - 0.1, _maxDistance, 0, true];
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
};
|
||||
|
@ -1,150 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Start a cook-off in the given vehicle.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <Object>
|
||||
* 1: Intensity of fire <Number>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [(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 (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 {};
|
||||
|
||||
|
||||
TRACE_2("cooking off",_vehicle,_intensity);
|
||||
TRACE_8("",_instigator,_smokeDelayEnabled,_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
|
||||
_intensity = _intensity min _maxIntensity;
|
||||
|
||||
private _config = configOf _vehicle;
|
||||
private _positions = getArray (_config >> 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;
|
||||
} forEach DEFAULT_COMMANDER_HATCHES;
|
||||
|
||||
if (_positions isEqualTo []) then {
|
||||
_positions pushBack "#noselection";
|
||||
};
|
||||
};
|
||||
|
||||
private _delay = 0;
|
||||
if (_smokeDelayEnabled) 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];
|
||||
|
||||
[{
|
||||
params ["_args", "_pfh"];
|
||||
_args params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"];
|
||||
private _intensity = _vehicle getVariable [QGVAR(intensity), 0];
|
||||
private _nextFlameTime = _vehicle getVariable [QGVAR(nextFlame), 0];
|
||||
if (isNull _vehicle || {_intensity <= 1}) exitWith {
|
||||
[_pfh] call CBA_fnc_removePerFrameHandler;
|
||||
|
||||
if (isNull _vehicle) exitWith {};
|
||||
|
||||
if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) exitWith {
|
||||
if (_fireSource isEqualTo "") then {
|
||||
_fireSource = selectRandom _positions;
|
||||
};
|
||||
|
||||
if (_nextFlameTime <= 0) then {
|
||||
_nextFlameTime = MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES;
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_vehicle", "_fireSource"];
|
||||
|
||||
if (isNull _vehicle) exitWith {};
|
||||
|
||||
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent;
|
||||
_vehicle setVariable [QGVAR(isCookingOff), false, true];
|
||||
|
||||
createVehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld (_vehicle selectionPosition _fireSource)), [], 0 , "CAN_COLLIDE"];
|
||||
|
||||
_vehicle setDamage [1, true];
|
||||
}, [_vehicle, _fireSource], _nextFlameTime] call CBA_fnc_waitAndExecute;
|
||||
};
|
||||
|
||||
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent;
|
||||
_vehicle setVariable [QGVAR(isCookingOff), false, true];
|
||||
};
|
||||
|
||||
private _lastFlameTime = _vehicle getVariable [QGVAR(lastFlame), 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 !(_canRing) then {
|
||||
_ring = false;
|
||||
};
|
||||
|
||||
private _time = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME;
|
||||
|
||||
if (_fireSource isEqualTo "") then {
|
||||
_fireSource = selectRandom _positions;
|
||||
};
|
||||
|
||||
[QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _time, _fireSource, _intensity]] call CBA_fnc_globalEvent;
|
||||
|
||||
_intensity = _intensity - (0.5 max random 1);
|
||||
_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)];
|
||||
|
||||
{
|
||||
[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];
|
||||
};
|
||||
};
|
||||
}, 0.25, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet]] call CBA_fnc_addPerFrameHandler
|
||||
}, [_vehicle, _positions, _intensity, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute;
|
@ -1,74 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, kymckay
|
||||
* Start a cook-off in the given ammo box.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Ammo box <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [_box] call ace_cookoff_fnc_cookOffBox
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_box"];
|
||||
|
||||
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
|
||||
_box setVariable [QGVAR(isCookingOff), true];
|
||||
|
||||
if (local _box) then {
|
||||
[QGVAR(cookOffBox), _box] call CBA_fnc_globalEvent;
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_box"];
|
||||
|
||||
// Box will start smoking
|
||||
private _smoke = "#particlesource" createVehicleLocal [0,0,0];
|
||||
_smoke setParticleClass "AmmoSmokeParticles2";
|
||||
_smoke attachTo [_box, [0,0,0]];
|
||||
|
||||
private _effects = [_smoke];
|
||||
|
||||
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;
|
52
addons/cookoff/functions/fnc_cookOffBoxLocal.sqf
Normal file
52
addons/cookoff/functions/fnc_cookOffBoxLocal.sqf
Normal file
@ -0,0 +1,52 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, kymckay, johnb43
|
||||
* Spawns local cook-off effects for ammo boxes.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Box <OBJECT>
|
||||
* 1: Source <OBJECT>
|
||||
* 2: Instigator <OBJECT>
|
||||
* 3: Start time of the cook-off <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, player, player, CBA_missionTime + 10] call ace_cookoff_fnc_cookOffBoxLocal
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["", "", "", "_startTime"];
|
||||
|
||||
[{
|
||||
params ["_box", "_source", "_instigator"];
|
||||
|
||||
// If box was deleted before smoke could be spawned, just exit
|
||||
if (isNull _box) exitWith {};
|
||||
|
||||
private _boxPos = ASLToAGL getPosASL _box;
|
||||
private _effects = [];
|
||||
|
||||
// Box will start smoking
|
||||
if (hasInterface) then {
|
||||
private _smoke = createVehicleLocal ["#particlesource", _boxPos, [], 0, "CAN_COLLIDE"];
|
||||
_smoke setParticleClass "AmmoSmokeParticles2";
|
||||
_smoke attachTo [_box];
|
||||
|
||||
_effects pushBack _smoke;
|
||||
};
|
||||
|
||||
if (isServer) then {
|
||||
private _sound = createSoundSource ["Sound_Fire", _boxPos, [], 0];
|
||||
_sound attachTo [_box];
|
||||
|
||||
_effects pushBack _sound;
|
||||
|
||||
// Detonate the ammunition
|
||||
[QGVAR(detonateAmmunitionServer), [_box, true, _source, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
_box setVariable [QGVAR(effects), _effects];
|
||||
}, _this, (_startTime - CBA_missionTime) max 0] call CBA_fnc_waitAndExecute; // This delay allows for synchronisation for JIP players
|
50
addons/cookoff/functions/fnc_cookOffBoxServer.sqf
Normal file
50
addons/cookoff/functions/fnc_cookOffBoxServer.sqf
Normal file
@ -0,0 +1,50 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, kymckay, johnb43
|
||||
* Start an ammo cook-off in the given ammo box.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Ammo box <OBJECT>
|
||||
* 1: Source <OBJECT> (default: objNull)
|
||||
* 2: Instigator <OBJECT> (default: objNull)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* cursorObject call ace_cookoff_fnc_cookOffBoxServer
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
if (!isServer) exitWith {};
|
||||
if (!GVAR(enableAmmobox) || {GVAR(ammoCookoffDuration) == 0}) exitWith {};
|
||||
|
||||
params ["_box", ["_source", objNull], ["_instigator", objNull]];
|
||||
|
||||
// Make sure it's a box (important, because deleted EH is assigned to ReammoBox_F only in postInit)
|
||||
if !(_box isKindOf "ReammoBox_F") exitWith {};
|
||||
|
||||
if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {};
|
||||
|
||||
// Allow only 1 cook-off per box at a time
|
||||
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
|
||||
|
||||
_box setVariable [QGVAR(isCookingOff), true, true];
|
||||
|
||||
private _delay = random [SMOKE_DELAY / 2, SMOKE_DELAY, SMOKE_DELAY / 2 * 3];
|
||||
|
||||
// Spawn cook-off effects on all connected machines and JIP
|
||||
private _jipID = [QGVAR(cookOffBoxLocal), [
|
||||
_box,
|
||||
_source,
|
||||
_instigator,
|
||||
CBA_missionTime + _delay // Generate a globally synced timestamp
|
||||
]] call CBA_fnc_globalEventJIP;
|
||||
|
||||
[_jipID, _box] call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
_box setVariable [QGVAR(cookoffBoxJipID), _jipID];
|
||||
|
||||
// API
|
||||
[QGVAR(cookOffBox), [_box, _source, _instigator, _delay]] call CBA_fnc_globalEvent;
|
@ -1,200 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Spawn cook-off effects
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <Object>
|
||||
* 1: Spawn fire jet <Boolean>
|
||||
* 2: Spawn fire ring <Boolean>
|
||||
* 3: How long effect will last (Max 20 seconds) <Number>
|
||||
* 4: What selection will fire originate from <String>
|
||||
* 5: Cookoff intensity value <Number>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [vehicle player, true, false, 15, "commander_turret"] call ace_cookoff_fnc_cookOffEffect
|
||||
*
|
||||
* 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);
|
||||
|
||||
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 {
|
||||
private _intensity = 20;
|
||||
private _radius = 1.5 * ((boundingBoxReal _obj) select 2);
|
||||
[QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, format [QGVAR(%1), hashValue _obj]]] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_args", "_pfh"];
|
||||
_args params ["_obj", "_jet", "_ring", "_time", "_startTime", "_light", "_fireSelection", "_sound", "_intensity"];
|
||||
private _elapsedTime = CBA_missionTime - _startTime;
|
||||
if (_elapsedTime >= _time) exitWith {
|
||||
deleteVehicle _light;
|
||||
deleteVehicle _sound;
|
||||
if (isServer) then {
|
||||
[QEGVAR(fire,removeFireSource), [format [QGVAR(%1), hashValue _obj]]] 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);
|
||||
|
||||
if (_jet) then {
|
||||
private _particlePosition = (_obj 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,
|
||||
_particlePosition,
|
||||
[0, 0, 15 * (_factor / 2)],
|
||||
0,
|
||||
10,
|
||||
7.9,
|
||||
0.075,
|
||||
[1.25 * _factor, 2.5 * _factor],
|
||||
[[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1],
|
||||
1,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
_obj
|
||||
];
|
||||
|
||||
// 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];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal",16,2,32],
|
||||
"", "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, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "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, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "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, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "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, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
|
||||
private _dir = 20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[1.25 * _factor, _flameSize * _factor],
|
||||
[[1, 1, 1, -2],[1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
|
||||
_dir = -20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[1.25 * _factor, _flameSize * _factor],
|
||||
[[1, 1, 1, -2],[1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
|
||||
_dir = 20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal",16,2,32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[_dir, -_dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[1.25 * _factor, _flameSize * _factor],
|
||||
[[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
|
||||
_dir = 20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[-_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[1.25 * _factor, _flameSize * _factor],
|
||||
[[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1], 1, 0, "", "", _obj
|
||||
];
|
||||
};
|
||||
|
||||
(getVehicleTIPars _obj) params ["_tiEngine", "_tiWheels", "_tiWeapon"];
|
||||
_obj setVehicleTIPars [
|
||||
// formula is designed to have the temperature ramp up quickly and then level out
|
||||
(_tiEngine + (_intensity * 0.01))/1.005,
|
||||
(_tiWheels + (_intensity * 0.004))/1.002, // wheels//tracks are further away from burning parts
|
||||
(_tiWeapon + (_intensity * 0.01))/1.005
|
||||
];
|
||||
|
||||
}, 0, [_obj, _jet, _ring, _time, CBA_missionTime, _light, _fireSelection, _sound, _intensity]] call CBA_fnc_addPerFrameHandler;
|
229
addons/cookoff/functions/fnc_cookOffLocal.sqf
Normal file
229
addons/cookoff/functions/fnc_cookOffLocal.sqf
Normal file
@ -0,0 +1,229 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm, johnb43
|
||||
* Spawn cook-off fire effects.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
* 1: Spawn fire jet <BOOL>
|
||||
* 2: Spawn fire ring <BOOL>
|
||||
* 3: What selection fire will originate from <STRING>
|
||||
* 4: Cookoff intensity value <NUMBER>
|
||||
* 5: Start time <NUMBER>
|
||||
* 6: Duration of effect (max 20 seconds) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, true, false, "commander_turret", 6, CBA_missionTime, 15] call ace_cookoff_fnc_cookOffLocal
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#define FLAME_SIZE 1.5
|
||||
#define FIRE_INTENSITY 20
|
||||
|
||||
params ["_vehicle", "_jet", "_ring", "_fireSelection", "_intensity", "_startTime", "_duration"];
|
||||
|
||||
// Check if still valid for JIP players
|
||||
if (isNull _vehicle || {CBA_missionTime - _startTime >= _duration}) exitWith {};
|
||||
|
||||
// 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 {
|
||||
// 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(cookoffFire_%1), hashValue _vehicle];
|
||||
|
||||
[QEGVAR(fire,addFireSource), [_vehicle, FLAME_SIZE * ((boundingBoxReal _vehicle) select 2), FIRE_INTENSITY, _fireKey]] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
||||
|
||||
[{
|
||||
(_this select 0) params ["_vehicle", "_jet", "_ring", "_startTime", "_duration", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"];
|
||||
|
||||
private _elapsedTime = CBA_missionTime - _startTime;
|
||||
|
||||
// Clean up effects once effects have finished or vehicle has been deleted
|
||||
if (isNull _vehicle || {_elapsedTime >= _duration}) exitWith {
|
||||
(_this select 1) call CBA_fnc_removePerFrameHandler;
|
||||
|
||||
deleteVehicle _light;
|
||||
|
||||
if (isServer) then {
|
||||
deleteVehicle _sound;
|
||||
|
||||
if (["ace_fire"] call EFUNC(common,isModLoaded)) then {
|
||||
[QEGVAR(fire,removeFireSource), _fireKey] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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} && {_vehicle getVariable [QGVAR(nextForceTime), 0] <= CBA_missionTime}) then {
|
||||
private _force = [0, 0, _factor * -(0.5 min random 1.5) * (0.3 min random 1)] vectorMultiply getMass _vehicle;
|
||||
_vehicle addForce [_force, vectorUpVisual _vehicle];
|
||||
_vehicle setVariable [QGVAR(nextForceTime), CBA_missionTime + 0.01]; // This prevents bad behaviour when setAccTime is small
|
||||
};
|
||||
|
||||
// Don't spawn visual effects on machines without interfaces
|
||||
if (!hasInterface) exitWith {};
|
||||
|
||||
_light setLightBrightness _factor;
|
||||
|
||||
if (_jet) then {
|
||||
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,
|
||||
_particlePosition,
|
||||
[0, 0, 15 * (_factor / 2)],
|
||||
0,
|
||||
10,
|
||||
7.9,
|
||||
0.075,
|
||||
[1.25 * _factor, 2.5 * _factor],
|
||||
[[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[2 + random 1],
|
||||
1,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
_vehicle
|
||||
];
|
||||
};
|
||||
|
||||
if (_ring) then {
|
||||
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,
|
||||
_ringOrigin,
|
||||
[0, 20 * (_factor / 2), 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + random 0.2) * _factor,
|
||||
_ringOrigin,
|
||||
[0, -20 * (_factor / 2), 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + random 0.2) * _factor,
|
||||
_ringOrigin,
|
||||
[20 * (_factor / 2), 0, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "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, FLAME_SIZE * _factor],
|
||||
[[1, 1, 1, -2], [1, 1, 1, -2], [1, 1, 1, -1], [1, 1, 1, -0]],
|
||||
[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,
|
||||
_ringOrigin,
|
||||
[_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
|
||||
_dir = -20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
|
||||
_dir = 20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal",16,2,32],
|
||||
"", "Billboard", 1, (0.1 + (random 0.2)) * _factor,
|
||||
_ringOrigin,
|
||||
[_dir, -_dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
|
||||
_dir = 20 * (_factor / 2);
|
||||
drop [
|
||||
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 2, 32],
|
||||
"", "Billboard", 1, (0.1 + random 0.2) * _factor,
|
||||
_ringOrigin,
|
||||
[-_dir, _dir, 0],
|
||||
0, 10, 7.9, 0.075,
|
||||
[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, "", "", _vehicle
|
||||
];
|
||||
};
|
||||
|
||||
(getVehicleTIPars _vehicle) params ["_tiEngine", "_tiWheels", "_tiWeapon"];
|
||||
|
||||
// Formula is designed to have the temperature ramp up quickly and then level out
|
||||
_vehicle setVehicleTIPars [
|
||||
(_tiEngine + _intensity * 0.01) / 1.005,
|
||||
(_tiWheels + _intensity * 0.004) / 1.002, // Wheels/tracks are further away from burning parts
|
||||
(_tiWeapon + _intensity * 0.01) / 1.005
|
||||
];
|
||||
}, 0, [_vehicle, _jet, _ring, _startTime, _duration, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler;
|
202
addons/cookoff/functions/fnc_cookOffServer.sqf
Normal file
202
addons/cookoff/functions/fnc_cookOffServer.sqf
Normal file
@ -0,0 +1,202 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm, johnb43
|
||||
* 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 <OBJECT>
|
||||
* 1: Intensity of fire <NUMBER>
|
||||
* 2: Source <OBJECT> (default: objNull)
|
||||
* 3: Instigator <OBJECT> (default: objNull)
|
||||
* 4: Delay between smoke and fire enabled <BOOL> (default: true)
|
||||
* 5: Ammo detonation chance <NUMBER> (default: 0)
|
||||
* 6: Detonate after cook-off <BOOL> (default: false)
|
||||
* 7: Selection for fire source <STRING> (default: "")
|
||||
* 8: Can spawn fire ring <BOOL> (default: true)
|
||||
* 9: Can spawn fire jet <BOOL> (default: true)
|
||||
* 10: Maximum intensity <NUMBER> (default: MAX_COOKOFF_INTENSITY)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, 3] call ace_cookoff_fnc_cookOffServer
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
if (!isServer) exitWith {};
|
||||
if (!GVAR(enableFire) || {GVAR(cookoffDuration) == 0}) exitWith {};
|
||||
|
||||
params [
|
||||
"_vehicle",
|
||||
"_intensity",
|
||||
["_source", objNull],
|
||||
["_instigator", objNull],
|
||||
["_delayBetweenSmokeAndFire", true],
|
||||
["_ammoDetonationChance", 0],
|
||||
["_detonateAfterCookoff", false],
|
||||
["_fireSelection", ""],
|
||||
["_canRing", true],
|
||||
["_canJet", true],
|
||||
["_maxIntensity", MAX_COOKOFF_INTENSITY]
|
||||
];
|
||||
|
||||
// Make sure it's a vehicle (important, because deleted EH is assigned to AllVehicles only in postInit)
|
||||
if !(_vehicle isKindOf "AllVehicles") exitWith {};
|
||||
|
||||
if (_vehicle isKindOf "CAManBase" || {_vehicle isKindOf "StaticWeapon"}) exitWith {};
|
||||
|
||||
// If under water, ignore
|
||||
// underwater is not very reliable, so use model center instead
|
||||
if (underwater _vehicle || {private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}}) exitWith {};
|
||||
|
||||
// Check if cook-off is disabled on vehicle specifically
|
||||
if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {}; // QGVAR(enable) is API
|
||||
|
||||
TRACE_3("cooking off",_vehicle,_intensity,_maxIntensity);
|
||||
TRACE_8("",_source,_instigator,_delayBetweenSmokeAndFire,_ammoDetonationChance,_detonateAfterCookoff,_fireSelection,_canRing,_canJet);
|
||||
|
||||
if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {};
|
||||
|
||||
_vehicle setVariable [QGVAR(isCookingOff), true, true];
|
||||
|
||||
// Limit maximum value of intensity to prevent very long cook-off times
|
||||
_intensity = _intensity min _maxIntensity;
|
||||
|
||||
private _selections = getArray (configOf _vehicle >> QGVAR(cookoffSelections)) select {(_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]};
|
||||
|
||||
if (_selections isEqualTo []) then {
|
||||
WARNING_1("no valid selection for cookoff found. %1",typeOf _vehicle);
|
||||
|
||||
{
|
||||
if ((_vehicle selectionPosition _x) isNotEqualTo [0, 0, 0]) then {
|
||||
_selections pushBack _x;
|
||||
};
|
||||
} forEach DEFAULT_COMMANDER_HATCHES;
|
||||
|
||||
if (_selections isEqualTo []) then {
|
||||
_selections pushBack "#noselection";
|
||||
};
|
||||
};
|
||||
|
||||
// Not guaranteed to be active/used, but reserve it nonetheless
|
||||
private _fireJipID = format [QGVAR(cookOffLocal_%1), hashValue _vehicle];
|
||||
[_fireJipID, _vehicle] call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
// Spawn smoke
|
||||
private _smokeJipID = [QGVAR(smoke), [_vehicle, _selections]] call CBA_fnc_globalEventJIP;
|
||||
[_smokeJipID, _vehicle] call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
// Save intensity for looping purposes
|
||||
_vehicle setVariable [QGVAR(intensity), _intensity];
|
||||
|
||||
private _delay = 0;
|
||||
|
||||
if (_delayBetweenSmokeAndFire) then {
|
||||
_delay = random [SMOKE_DELAY, 1.5 * SMOKE_DELAY, 2 * SMOKE_DELAY];
|
||||
};
|
||||
|
||||
[{
|
||||
[{
|
||||
(_this select 0) params ["_vehicle", "_selections", "_ammoDetonationChance", "_detonateAfterCookoff", "_source", "_instigator", "_fireSelection", "_canRing", "_canJet", "_smokeJipID", "_fireJipID"];
|
||||
|
||||
if (
|
||||
isNull _vehicle ||
|
||||
!GVAR(enableFire) ||
|
||||
{!(_vehicle getVariable [QGVAR(enable), true])} || // QGVAR(enable) is API
|
||||
{GVAR(cookoffDuration) == 0} ||
|
||||
{underwater _vehicle} ||
|
||||
{private _posASL = getPosWorld _vehicle; surfaceIsWater _posASL && {(_posASL select 2) < 0}} // Underwater is not very reliable, so use model center instead
|
||||
) exitWith {
|
||||
// Effects are deleted when vehicle is deleted
|
||||
(_this select 1) call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
|
||||
private _intensity = _vehicle getVariable [QGVAR(intensity), 0];
|
||||
|
||||
if (_intensity <= 1) exitWith {
|
||||
(_this select 1) call CBA_fnc_removePerFrameHandler;
|
||||
|
||||
// Wait until the previous flame has finished
|
||||
private _nextFlameTime = (_vehicle getVariable [QGVAR(endCurrentFlame), CBA_missionTime]) - CBA_missionTime + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES);
|
||||
|
||||
if (_fireSelection isEqualTo "") then {
|
||||
_fireSelection = selectRandom _selections;
|
||||
};
|
||||
|
||||
[{
|
||||
params ["_vehicle", "_source", "_instigator", "_detonateAfterCookoff", "_fireSelection", "_smokeJipID", "_fireJipID"];
|
||||
|
||||
// Effects are deleted when vehicle is deleted
|
||||
if (isNull _vehicle) exitWith {};
|
||||
|
||||
// Remove effects from JIP
|
||||
_smokeJipID call CBA_fnc_removeGlobalEventJIP;
|
||||
_fireJipID call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
// Remove effects
|
||||
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent;
|
||||
|
||||
// Reset variable, so it can cook-off again
|
||||
_vehicle setVariable [QGVAR(isCookingOff), nil, true];
|
||||
|
||||
if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then {
|
||||
createVehicle ["ACE_ammoExplosionLarge", _vehicle modelToWorld (_vehicle selectionPosition _fireSelection), [], 0 , "CAN_COLLIDE"];
|
||||
|
||||
_vehicle setDamage [1, true, _source, _instigator]; // Because it's running on the server, source and instigator can be set
|
||||
};
|
||||
}, [_vehicle, _source, _instigator, _detonateAfterCookoff, _fireSelection, _smokeJipID, _fireJipID], _nextFlameTime] call CBA_fnc_waitAndExecute;
|
||||
};
|
||||
|
||||
// Wait until we are ready for the next flame
|
||||
if ((_vehicle getVariable [QGVAR(nextFlame), 0]) <= CBA_missionTime) then {
|
||||
private _ring = false;
|
||||
|
||||
if (_canRing) then {
|
||||
_ring = 0.2 > random 1;
|
||||
|
||||
if (!_ring && {_intensity >= 2}) then {
|
||||
_ring = 0.7 > random 1;
|
||||
};
|
||||
};
|
||||
|
||||
private _duration = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME;
|
||||
|
||||
if (_fireSelection isEqualTo "") then {
|
||||
_fireSelection = selectRandom _selections;
|
||||
};
|
||||
|
||||
// Sync for JIP players
|
||||
[QGVAR(cookOffLocal), [_vehicle, _canJet, _ring, _fireSelection, _intensity, CBA_missionTime, _duration], _fireJipID] call CBA_fnc_globalEventJIP;
|
||||
|
||||
// If there are any crew, burn them
|
||||
if (["ace_fire"] call EFUNC(common,isModLoaded)) then {
|
||||
// Use current intensity, in case GVAR(cookoffDuration) is very large and only 1 flameout stage happens
|
||||
{
|
||||
[QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator]] call CBA_fnc_globalEvent;
|
||||
} forEach (crew _vehicle);
|
||||
};
|
||||
|
||||
_intensity = (_intensity - (0.5 max random 1) / GVAR(cookoffDuration)) max 0;
|
||||
|
||||
_vehicle setVariable [QGVAR(intensity), _intensity];
|
||||
_vehicle setVariable [QGVAR(endCurrentFlame), CBA_missionTime + _duration];
|
||||
_vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _duration + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)];
|
||||
};
|
||||
|
||||
if (_ammoDetonationChance > random 1 && {_vehicle getVariable [QGVAR(nextExplosiveDetonation), 0] <= CBA_missionTime}) then {
|
||||
if (_fireSelection isEqualTo "") then {
|
||||
_fireSelection = selectRandom _selections;
|
||||
};
|
||||
|
||||
createVehicle ["ACE_ammoExplosionLarge", _vehicle modelToWorld (_vehicle selectionPosition _fireSelection), [], 0 , "CAN_COLLIDE"];
|
||||
|
||||
_vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60];
|
||||
};
|
||||
}, 0.25, _this] call CBA_fnc_addPerFrameHandler;
|
||||
}, [_vehicle, _selections, _ammoDetonationChance, _detonateAfterCookoff, _source, _instigator, _fireSelection, _canRing, _canJet, _smokeJipID, _fireJipID], _delay] call CBA_fnc_waitAndExecute;
|
||||
|
||||
// API
|
||||
[QGVAR(cookoff), [_vehicle, _intensity, _instigator, _smokeDelayEnabled, _ammoDetonationChance, _detonateAfterCookoff, _fireSelection, _canRing, _maxIntensity, _canJet]] call CBA_fnc_globalEvent;
|
@ -1,132 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Detonates ammunition from a vehicle until no ammo left
|
||||
*
|
||||
* Arguments:
|
||||
* 0: vehicle <OBJECT>
|
||||
* 1: Ammo Array <ARRAY>
|
||||
* - 0: Magazine Classname <STRING>
|
||||
* - 1: Ammo Count <NUMBER>
|
||||
* 2: Total Ammo Count <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [_vehicle, magazinesAmmo _vehicle] call ace_cookoff_fnc_detonateAmmunition
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_magazines", "_totalAmmo"];
|
||||
|
||||
if (GVAR(enable) == 0) exitWith {};
|
||||
if !(GVAR(enableAmmoCookoff)) exitWith {};
|
||||
|
||||
if (isNull _vehicle) exitWith {}; // vehicle got deleted
|
||||
if (_magazines isEqualTo []) exitWith {}; // nothing to detonate anymore
|
||||
if (underwater _vehicle) exitWith {};
|
||||
|
||||
private _magazineIndex = floor random(count _magazines);
|
||||
private _magazine = _magazines select _magazineIndex;
|
||||
_magazine params ["_magazineClassname", "_amountOfMagazines"];
|
||||
|
||||
if (_amountOfMagazines < 0) exitWith {
|
||||
ERROR_1("mag with no ammo - %1",_magazine);
|
||||
};
|
||||
private _removed = _amountOfMagazines min floor(1 + random(6 / GVAR(ammoCookoffDuration)));
|
||||
|
||||
_amountOfMagazines = _amountOfMagazines - _removed;
|
||||
if (_amountOfMagazines <= 0) then {
|
||||
_magazines deleteAt _magazineIndex;
|
||||
} else {
|
||||
_magazine set [1, _amountOfMagazines]; // clear out the magazine
|
||||
};
|
||||
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;
|
||||
_simType = toLowerANSI _simType;
|
||||
switch (_simType) do {
|
||||
case ("shotbullet"): {
|
||||
[QGVAR(playCookoffSound), [_vehicle, _simType]] call CBA_fnc_globalEvent;
|
||||
if (random 1 < 0.6) then {
|
||||
[_vehicle, _ammo, _speed, true] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
case ("shotshell"): {
|
||||
[QGVAR(playCookoffSound), [_vehicle, _simType]] call CBA_fnc_globalEvent;
|
||||
if (random 1 < 0.15) then {
|
||||
[_vehicle, _ammo, _speed, true] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
case ("shotgrenade"): {
|
||||
if (random 1 < 0.9) then {
|
||||
_speed = 0;
|
||||
};
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.5] call _spawnProjectile;
|
||||
};
|
||||
case ("shotrocket");
|
||||
case ("shotmissile");
|
||||
case ("shotsubmunitions"): {
|
||||
if (random 1 < 0.1) then {
|
||||
[QGVAR(playCookoffSound), [_vehicle, _simType]] call CBA_fnc_globalEvent;
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile;
|
||||
} else {
|
||||
createvehicle ["ACE_ammoExplosionLarge", (_vehicle modelToWorld _effect2pos), [], 0 , "CAN_COLLIDE"];
|
||||
};
|
||||
};
|
||||
case ("shotmine");
|
||||
case ("shotdirectionalbomb"): {
|
||||
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 a scripted alternative doesn't exist use generic explosion
|
||||
if (_ammo != "") then {
|
||||
[_vehicle, _ammo, 0, false] call _spawnProjectile;
|
||||
} else {
|
||||
createvehicle ["SmallSecondary", (_vehicle modelToWorld _effect2pos), [], 0 , "CAN_COLLIDE"];
|
||||
};
|
||||
};
|
||||
};
|
||||
case ("shotilluminating"): {
|
||||
if (random 1 < 0.15) then {
|
||||
[_vehicle, _ammo, _speed, random 1 < 0.3] call _spawnProjectile;
|
||||
};
|
||||
};
|
||||
};
|
||||
[FUNC(detonateAmmunition), [_vehicle, _magazines, _totalAmmo], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
|
54
addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf
Normal file
54
addons/cookoff/functions/fnc_detonateAmmunitionServer.sqf
Normal file
@ -0,0 +1,54 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: johnb43
|
||||
* Starts detonating ammunition from an object (e.g. vehicle or crate).
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Object <OBJECT>
|
||||
* 1: Destroy when finished <BOOL> (default: false)
|
||||
* 2: Source <OBJECT> (default: objNull)
|
||||
* 3: Instigator <OBJECT> (default: objNull)
|
||||
* 4: Initial delay <NUMBER> (default: 0)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject] call ace_cookoff_fnc_detonateAmmunitionServer
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
if (!isServer) exitWith {};
|
||||
|
||||
params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_instigator", objNull], ["_initialDelay", 0]];
|
||||
|
||||
if (isNull _object) exitWith {};
|
||||
|
||||
// Check if the object can cook its ammo off
|
||||
if (
|
||||
underwater _object ||
|
||||
{private _posASL = getPosWorld _object; surfaceIsWater _posASL && {(_posASL select 2) < 0}} || // Underwater is not very reliable, so use model center instead
|
||||
{GVAR(ammoCookoffDuration) == 0} ||
|
||||
{!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} ||
|
||||
{!(_object getVariable [QGVAR(enableAmmoCookoff), true])}
|
||||
) exitWith {};
|
||||
|
||||
// Don't have an object detonate its ammo twice
|
||||
if (_object getVariable [QGVAR(isAmmoDetonating), false]) exitWith {};
|
||||
|
||||
_object setVariable [QGVAR(isAmmoDetonating), true, true];
|
||||
|
||||
_object setVariable [QGVAR(cookoffMagazines), _object call FUNC(getVehicleAmmo)];
|
||||
|
||||
// TODO: When setMagazineTurretAmmo and magazineTurretAmmo are fixed (https://feedback.bistudio.com/T79689),
|
||||
// we can add gradual ammo removal during cook-off
|
||||
if (GVAR(removeAmmoDuringCookoff)) then {
|
||||
clearMagazineCargoGlobal _object;
|
||||
|
||||
{
|
||||
[QEGVAR(common,removeMagazinesTurret), [_object, _x select 0, _x select 1], _object, _x select 1] call CBA_fnc_turretEvent;
|
||||
} forEach (magazinesAllTurrets _object);
|
||||
};
|
||||
|
||||
[LINKFUNC(detonateAmmunitionServerLoop), [_object, _destroyWhenFinished, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute;
|
181
addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf
Normal file
181
addons/cookoff/functions/fnc_detonateAmmunitionServerLoop.sqf
Normal file
@ -0,0 +1,181 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: Glowbal, johnb43
|
||||
* Detonates ammunition from an object (e.g. vehicle or crate) until no ammo is left.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Object <OBJECT>
|
||||
* 1: Destroy when finished <BOOL>
|
||||
* 2: Source <OBJECT>
|
||||
* 3: Instigator <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, true, player, player] call ace_cookoff_fnc_detonateAmmunitionServerLoop
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_object", "_destroyWhenFinished", "_source", "_instigator"];
|
||||
|
||||
if (isNull _object) exitWith {};
|
||||
|
||||
(_object getVariable QGVAR(cookoffMagazines)) params ["_magazines", "_totalAmmo"];
|
||||
|
||||
private _hasFinished = _totalAmmo <= 0 || {_magazines isEqualTo []};
|
||||
|
||||
// If the cook-off has finished or been interrupted, clean up the effects for boxes (no vehicle effects)
|
||||
if (
|
||||
_hasFinished ||
|
||||
{underwater _object} ||
|
||||
{private _posASL = getPosWorld _object; surfaceIsWater _posASL && {(_posASL select 2) < 0}} || // Underwater is not very reliable, so use model center instead
|
||||
{GVAR(ammoCookoffDuration) == 0} ||
|
||||
{!([GVAR(enableAmmoCookoff), GVAR(enableAmmobox)] select (_object isKindOf "ReammoBox_F"))} ||
|
||||
{!(_object getVariable [QGVAR(enableAmmoCookoff), true])}
|
||||
) exitWith {
|
||||
// Box cook-off fire ends after the ammo has detonated (vehicle cook-off fire does not depend on the ammo detonation)
|
||||
if (_object isKindOf "ReammoBox_F") then {
|
||||
[QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent;
|
||||
|
||||
// Reset variable, so the box can cook-off again
|
||||
_object setVariable [QGVAR(isCookingOff), nil, true];
|
||||
|
||||
// Remove cook-off effects from box
|
||||
private _jipID = _object getVariable QGVAR(cookoffBoxJipID);
|
||||
|
||||
if (isNil "_jipID") exitWith {};
|
||||
|
||||
_jipID call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
_object setVariable [QGVAR(cookoffBoxJipID), nil];
|
||||
};
|
||||
|
||||
// Reset variables, so the object can detonate its ammo again
|
||||
_object setVariable [QGVAR(cookoffMagazines), nil];
|
||||
_object setVariable [QGVAR(isAmmoDetonating), nil, true];
|
||||
|
||||
// If done, destroy the object if necessary
|
||||
if (_hasFinished && _destroyWhenFinished) then {
|
||||
_object setDamage [1, true, _source, _instigator];
|
||||
};
|
||||
};
|
||||
|
||||
private _magazineIndex = floor random (count _magazines);
|
||||
private _magazine = _magazines select _magazineIndex;
|
||||
_magazine params ["_magazineClassname", "_ammoCount", "_spawnProjectile"];
|
||||
|
||||
// Make sure ammo is at least 0
|
||||
_ammoCount = _ammoCount max 0;
|
||||
|
||||
// Remove some ammo, which will be detonated
|
||||
private _removed = _ammoCount min floor (1 + random (6 / GVAR(ammoCookoffDuration)));
|
||||
|
||||
_ammoCount = _ammoCount - _removed;
|
||||
|
||||
if (_ammoCount <= 0) then {
|
||||
_magazines deleteAt _magazineIndex;
|
||||
} else {
|
||||
_magazine set [1, _ammoCount]; // remove ammo that was detonated
|
||||
};
|
||||
|
||||
private _timeBetweenAmmoDetonation = ((random 10 / sqrt _totalAmmo) min MAX_TIME_BETWEEN_AMMO_DET) max 0.1;
|
||||
TRACE_2("",_totalAmmo,_timeBetweenAmmoDetonation);
|
||||
_totalAmmo = _totalAmmo - _removed;
|
||||
|
||||
_object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]];
|
||||
|
||||
// Get magazine info, which is used to spawn projectiles
|
||||
private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname;
|
||||
private _ammo = getText (_configMagazine >> "ammo");
|
||||
private _configAmmo = configFile >> "CfgAmmo" >> _ammo;
|
||||
|
||||
private _simType = toLower getText (_configAmmo >> "simulation");
|
||||
private _speed = linearConversion [0, 1, random 1, 1, 20, true];
|
||||
private _effect2pos = _object selectionPosition "destructionEffect2";
|
||||
|
||||
// Spawns the projectiles, making them either fly in random directions or explode
|
||||
private _fnc_spawnProjectile = {
|
||||
// If the magazines are inside of the cargo (inventory), don't let their projectiles escape the interior of the vehicle
|
||||
if (!_spawnProjectile) exitWith {};
|
||||
|
||||
params ["_object", "_ammo", "_speed", "_flyAway"];
|
||||
|
||||
private _spawnPos = _object modelToWorld [-0.2 + random 0.4, -0.2 + random 0.4, random 3];
|
||||
|
||||
if (_spawnPos select 2 < 0) then {
|
||||
_spawnPos set [2, 0];
|
||||
};
|
||||
|
||||
private _projectile = createVehicle [_ammo, _spawnPos, [], 0, "CAN_COLLIDE"];
|
||||
|
||||
if (_flyAway) then {
|
||||
private _vectorAmmo = [-1 + random 2, -1 + random 2, -0.2 + random 1];
|
||||
private _vectorVelocity = _vectorAmmo vectorMultiply _speed;
|
||||
|
||||
_projectile setVectorDir _vectorVelocity;
|
||||
_projectile setVelocity _vectorVelocity;
|
||||
} else {
|
||||
_projectile setDamage 1;
|
||||
};
|
||||
};
|
||||
|
||||
switch (_simType) do {
|
||||
case "shotbullet": {
|
||||
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
|
||||
|
||||
if (random 1 < 0.6) then {
|
||||
[_object, _ammo, _speed, true] call _fnc_spawnProjectile;
|
||||
};
|
||||
};
|
||||
case "shotshell": {
|
||||
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
|
||||
|
||||
if (random 1 < 0.15) then {
|
||||
[_object, _ammo, _speed, true] call _fnc_spawnProjectile;
|
||||
};
|
||||
};
|
||||
case "shotgrenade": {
|
||||
if (random 1 < 0.9) then {
|
||||
_speed = 0;
|
||||
};
|
||||
|
||||
[_object, _ammo, _speed, random 1 < 0.5] call _fnc_spawnProjectile;
|
||||
};
|
||||
case "shotrocket";
|
||||
case "shotmissile";
|
||||
case "shotsubmunitions": {
|
||||
if (random 1 < 0.1) then {
|
||||
[QGVAR(playCookoffSound), [_object, _simType]] call CBA_fnc_globalEvent;
|
||||
|
||||
[_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile;
|
||||
} else {
|
||||
createVehicle ["ACE_ammoExplosionLarge", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"];
|
||||
};
|
||||
};
|
||||
case "shotdirectionalbomb";
|
||||
case "shotmine": {
|
||||
if (random 1 < 0.5) then {
|
||||
// Not all explosives detonate on destruction, some have scripted alternatives
|
||||
if (getNumber (_configAmmo >> "triggerWhenDestroyed") != 1) then {
|
||||
_ammo = getText (_configAmmo >> QEGVAR(explosives,explosive));
|
||||
};
|
||||
|
||||
// If a scripted alternative doesn't exist use generic explosion
|
||||
if (_ammo != "") then {
|
||||
[_object, _ammo, 0, false] call _fnc_spawnProjectile;
|
||||
} else {
|
||||
createVehicle ["SmallSecondary", _object modelToWorld _effect2pos, [], 0 , "CAN_COLLIDE"];
|
||||
};
|
||||
};
|
||||
};
|
||||
case "shotilluminating": {
|
||||
if (random 1 < 0.15) then {
|
||||
[_object, _ammo, _speed, random 1 < 0.3] call _fnc_spawnProjectile;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Detonate the remaining ammo after a delay
|
||||
[LINKFUNC(detonateAmmunitionServerLoop), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
|
@ -1,51 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2
|
||||
* Start fire in engine block of a car.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <Object>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* (vehicle player) call ace_cookoff_fnc_engineFire
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle"];
|
||||
|
||||
if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {};
|
||||
_vehicle setVariable [QGVAR(isEngineSmoking), true];
|
||||
|
||||
if (local _vehicle) then {
|
||||
[QGVAR(engineFire), _vehicle] call CBA_fnc_globalEvent;
|
||||
};
|
||||
|
||||
private _offset = getArray (_vehicle call CBA_fnc_getObjectConfig >> QGVAR(engineSmokeOffset));
|
||||
|
||||
if (_offset isEqualTo []) then {
|
||||
_offset = [0,0,0];
|
||||
};
|
||||
|
||||
private _position = [
|
||||
0,
|
||||
(boundingBoxReal _vehicle select 1 select 1) - 2,
|
||||
(boundingBoxReal _vehicle select 0 select 2) + 2
|
||||
] vectorAdd _offset;
|
||||
|
||||
private _smoke = "#particlesource" createVehicleLocal [0,0,0];
|
||||
_smoke setParticleClass "ObjectDestructionSmoke1_2Smallx";
|
||||
_smoke attachTo [_vehicle, _position];
|
||||
|
||||
[{
|
||||
(_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;
|
81
addons/cookoff/functions/fnc_engineFireLocal.sqf
Normal file
81
addons/cookoff/functions/fnc_engineFireLocal.sqf
Normal file
@ -0,0 +1,81 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, johnb43
|
||||
* Start fire in engine block of a car.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
* 1: End time <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [cursorObject, CBA_missionTime + 10] 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 {
|
||||
private _hitPoints = getAllHitPointsDamage _vehicle;
|
||||
|
||||
// Get hitpoint for engine
|
||||
private _index = (_hitPoints select 0) findIf {_x == "hitengine"};
|
||||
|
||||
// Get corresponding selection
|
||||
private _position = if (_index != -1) then {
|
||||
_vehicle selectionPosition [(_hitPoints select 1) select _index, "HitPoints", "AveragePoint"]
|
||||
} else {
|
||||
[0, 0, 0]
|
||||
};
|
||||
|
||||
if (_position isEqualTo [0, 0, 0]) then {
|
||||
// Get offset for engine smoke if there is one
|
||||
private _offset = getArray (configOf _vehicle >> QGVAR(engineSmokeOffset));
|
||||
|
||||
if (_offset isEqualTo []) then {
|
||||
_offset = [0, 0, 0];
|
||||
};
|
||||
|
||||
_position = [
|
||||
0,
|
||||
(boundingBoxReal _vehicle select 1 select 1) - 2,
|
||||
(boundingBoxReal _vehicle select 0 select 2) + 2
|
||||
] vectorAdd _offset;
|
||||
};
|
||||
|
||||
// Spawn smoke
|
||||
_smoke = createVehicleLocal ["#particlesource", ASLToAGL getPosASL _vehicle, [], 0, "CAN_COLLIDE"];;
|
||||
_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 (!isServer || {isNull _vehicle}) exitWith {};
|
||||
|
||||
// Reset variable, so engine can smoke again in the future
|
||||
_vehicle setVariable [QGVAR(isEngineSmoking), nil, true];
|
||||
|
||||
private _jipID = _vehicle getVariable QGVAR(engineFireJipID);
|
||||
|
||||
if (isNil "_jipID") exitWith {};
|
||||
|
||||
_jipID call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
_vehicle setVariable [QGVAR(engineFireJipID), nil];
|
||||
}, 5, [_vehicle, _smoke, _endTime]] call CBA_fnc_addPerFrameHandler;
|
34
addons/cookoff/functions/fnc_engineFireServer.sqf
Normal file
34
addons/cookoff/functions/fnc_engineFireServer.sqf
Normal file
@ -0,0 +1,34 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, johnb43
|
||||
* Start fire in engine block of a car.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* cursorObject call ace_cookoff_fnc_engineFireServer
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
if (!isServer) exitWith {};
|
||||
|
||||
params ["_vehicle"];
|
||||
|
||||
// If already smoking, stop
|
||||
if (_vehicle getVariable [QGVAR(isEngineSmoking), false]) exitWith {};
|
||||
|
||||
_vehicle setVariable [QGVAR(isEngineSmoking), true, true];
|
||||
|
||||
// Spawn engine fire effects on all connected machines
|
||||
private _jipID = [QGVAR(engineFireLocal), [_vehicle, CBA_missionTime + random [ENGINE_FIRE_TIME / 2, ENGINE_FIRE_TIME, ENGINE_FIRE_TIME / 2 * 3]]] call CBA_fnc_globalEventJIP;
|
||||
[_jipID, _vehicle] call CBA_fnc_removeGlobalEventJIP;
|
||||
|
||||
_vehicle setVariable [QGVAR(engineFireJipID), _jipID];
|
||||
|
||||
// API
|
||||
[QGVAR(engineFire), [_vehicle]] call CBA_fnc_globalEvent;
|
@ -1,65 +1,76 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Gets all magazines inside of a vehicle.
|
||||
* Gets all magazines inside of an object.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <Object>
|
||||
* 0: Object <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* 0: Ammo Array <ARRAY>
|
||||
* - 0: Magazine Classname <STRING>
|
||||
* - 1: Ammo Count <NUMBER>
|
||||
* 1: Total Ammo Count <NUMBER>
|
||||
* 0: Ammo array <ARRAY>
|
||||
* - 0: Magazine classname <STRING>
|
||||
* - 1: Ammo count <NUMBER>
|
||||
* - 2: If a projectile should be spawned upon detonation <BOOL>
|
||||
* 1: Total ammo count <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [vehicle player] call ace_cookoff_fnc_getVehicleAmmo
|
||||
* cursorObject call ace_cookoff_fnc_getVehicleAmmo
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle"];
|
||||
TRACE_1("getVehicleAmmo",_vehicle);
|
||||
params ["_object"];
|
||||
TRACE_1("getVehicleAmmo",_object);
|
||||
|
||||
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, true];
|
||||
_totalAmmo = _totalAmmo + _count;
|
||||
};
|
||||
} forEach (magazinesAllTurrets [_vehicle, true]);
|
||||
} forEach (magazinesAllTurrets [_object, 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, false];
|
||||
_totalAmmo = _totalAmmo + _count;
|
||||
};
|
||||
} forEach (magazinesAmmoCargo _vehicle);
|
||||
} forEach (magazinesAmmoCargo _object);
|
||||
|
||||
// Get ammo from transportAmmo / ace_rearm
|
||||
private _vehCfg = configOf _vehicle;
|
||||
private _configVehicle = configOf _object;
|
||||
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 {
|
||||
TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _vehicle);
|
||||
if (_object getVariable [QEGVAR(rearm,isSupplyVehicle), _configSupply > 0]) then {
|
||||
TRACE_1("transportAmmo vehicle - adding virtual ammo",typeOf _object);
|
||||
|
||||
_ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000];
|
||||
_ammoToDetonate pushBack ["2000Rnd_65x39_belt", 2000, false];
|
||||
_totalAmmo = _totalAmmo + 2000;
|
||||
_ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100];
|
||||
|
||||
_ammoToDetonate pushBack ["20Rnd_105mm_HEAT_MP", 100, true];
|
||||
_totalAmmo = _totalAmmo + 100;
|
||||
_ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10];
|
||||
|
||||
_ammoToDetonate pushBack ["SatchelCharge_Remote_Mag", 10, true];
|
||||
_totalAmmo = _totalAmmo + 10;
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2
|
||||
* Handles all incoming damage for boxi
|
||||
* Author: KoffeinFlummi, commy2, johnb43
|
||||
* Handles all incoming damage for boxes.
|
||||
*
|
||||
* Arguments:
|
||||
* HandleDamage EH <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* Damage to be inflicted. <NUMBER>
|
||||
* Damage to be inflicted (can be nil) <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* _this call ace_cookoff_fnc_handleDamageBox
|
||||
@ -15,58 +15,48 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "", "_damage", "_source", "_ammo", "_hitIndex", "_shooter"];
|
||||
// If cookoff for boxes is disabled, exit
|
||||
if (!GVAR(enableAmmobox) || {GVAR(ammoCookoffDuration) == 0}) exitWith {};
|
||||
|
||||
// it's already dead, who cares?
|
||||
if (damage _vehicle >= 1) exitWith {};
|
||||
params ["_box", "", "_damage", "_source", "_ammo", "", "_instigator", "_hitPoint"];
|
||||
|
||||
// If cookoff is disabled exit
|
||||
if (_vehicle getVariable [QGVAR(enable), GVAR(enable)] in [0, false]) exitWith {};
|
||||
if (!local _box) exitWith {};
|
||||
|
||||
// get hitpoint name
|
||||
private _hitpoint = "#structural";
|
||||
// If it's already dead, ignore
|
||||
if (!alive _box) exitWith {};
|
||||
|
||||
if (_hitIndex != -1) then {
|
||||
_hitpoint = toLowerANSI ((getAllHitPointsDamage _vehicle param [0, []]) select _hitIndex);
|
||||
};
|
||||
if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {};
|
||||
|
||||
// get change in damage
|
||||
private _oldDamage = 0;
|
||||
if !(_hitPoint == "" && {_damage > 0.5}) exitWith {}; // "" means structural damage
|
||||
|
||||
if (_hitpoint isEqualTo "#structural") then {
|
||||
_oldDamage = damage _vehicle;
|
||||
private _ammoConfig = _ammo call CBA_fnc_getObjectConfig;
|
||||
|
||||
// Catch fire when hit by an explosive or incendiary round
|
||||
if ((getNumber (_ammoConfig >> "explosive") >= 0.5) || {getNumber (_ammoConfig >> QEGVAR(vehicle_damage,incendiary)) > random 1}) then {
|
||||
[QGVAR(cookOffBoxServer), [_box, _source, _instigator]] call CBA_fnc_serverEvent;
|
||||
} else {
|
||||
_oldDamage = _vehicle getHitIndex _hitIndex;
|
||||
};
|
||||
// There is a small chance of cooking a box off if it's shot by tracer ammo
|
||||
if (random 1 >= _damage * 0.05) exitWith {};
|
||||
|
||||
if (_hitpoint == "#structural" && _damage > 0.5) then {
|
||||
// Almost always catch fire when hit by an explosive
|
||||
if (IS_EXPLOSIVE_AMMO(_ammo)) then {
|
||||
_vehicle call FUNC(cookOffBox);
|
||||
// Need magazine to check for tracers
|
||||
private _magazine = if (_source == _instigator) then {
|
||||
currentMagazine _source
|
||||
} else {
|
||||
// Need magazine to check for tracers
|
||||
private _mag = "";
|
||||
if (_source == _shooter) then {
|
||||
_mag = currentMagazine _source;
|
||||
} else {
|
||||
_mag = _source currentMagazineTurret ([_shooter] call CBA_fnc_turretPath);
|
||||
};
|
||||
private _magCfg = configFile >> "CfgMagazines" >> _mag;
|
||||
|
||||
// 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);
|
||||
};
|
||||
};
|
||||
};
|
||||
_source currentMagazineTurret (_source unitTurret _instigator)
|
||||
};
|
||||
|
||||
// prevent destruction, let cook-off handle it if necessary
|
||||
_damage min 0.89
|
||||
} else {
|
||||
_damage
|
||||
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(cookOffBoxServer), [_box, _source, _instigator]] call CBA_fnc_serverEvent;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Prevent destruction, let cook-off handle it if necessary
|
||||
_damage min 0.89
|
||||
|
@ -1,24 +1,22 @@
|
||||
#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 <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* 0: If magazine is type of flare <BOOL>
|
||||
* If magazine is type of flare <BOOL>
|
||||
*
|
||||
* 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");
|
||||
|
||||
_intensity != 0 || _flare == 1
|
||||
getNumber (_configAmmo >> "intensity") != 0 || {getNumber (_configAmmo >> QEGVAR(grenades,flare)) == 1}
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
* 1. Selections for smoke to come out of <ARRAY> (default: [])
|
||||
* 1: Selections for smoke to come out of <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
@ -16,12 +16,11 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", ["_positions", []]];
|
||||
params ["_vehicle", "_selections"];
|
||||
|
||||
private _turretConfig = [_vehicle, [0]] call CBA_fnc_getTurret;
|
||||
private _positionBarrelEnd = getText (_turretConfig >> "gunBeg");
|
||||
private _positionBarrelEnd = getText ([_vehicle, [0]] call CBA_fnc_getTurret >> "gunBeg");
|
||||
|
||||
// smoke out of cannon and hatches
|
||||
// Smoke out of cannon and hatches
|
||||
private _smokeBarrel = "#particlesource" createVehicleLocal [0, 0, 0];
|
||||
_smokeBarrel setParticleClass "MediumDestructionSmoke";
|
||||
_smokeBarrel attachTo [_vehicle, [0, 0, 0], _positionBarrelEnd];
|
||||
@ -29,10 +28,10 @@ _smokeBarrel attachTo [_vehicle, [0, 0, 0], _positionBarrelEnd];
|
||||
private _effects = [_smokeBarrel];
|
||||
|
||||
{
|
||||
private _position = [0, -2, 0];
|
||||
|
||||
if (_x isNotEqualTo "#noselection") then {
|
||||
_position = _vehicle selectionPosition _x;
|
||||
private _position = if (_x != "#noselection") then {
|
||||
_vehicle selectionPosition _x
|
||||
} else {
|
||||
[0, -2, 0]
|
||||
};
|
||||
|
||||
private _smoke = "#particlesource" createVehicleLocal [0, 0, 0];
|
||||
@ -40,6 +39,6 @@ private _effects = [_smokeBarrel];
|
||||
_smoke attachTo [_vehicle, _position];
|
||||
|
||||
_effects pushBack _smoke;
|
||||
} forEach _positions;
|
||||
} forEach _selections;
|
||||
|
||||
_vehicle setVariable [QGVAR(effects), _effects];
|
||||
|
@ -1,63 +1,71 @@
|
||||
[
|
||||
QGVAR(enable), "LIST",
|
||||
[LSTRING(enable_hd_name), LSTRING(enable_hd_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
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(enableFire), "CHECKBOX",
|
||||
QGVAR(enableFire),
|
||||
"CHECKBOX",
|
||||
[LSTRING(enableFire_name), LSTRING(enableFire_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
true, // default value
|
||||
true // isGlobal
|
||||
true,
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(destroyVehicleAfterCookoff), "CHECKBOX",
|
||||
[LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)],
|
||||
QGVAR(cookoffDuration),
|
||||
"SLIDER",
|
||||
[LSTRING(cookoffDuration_name), LSTRING(cookoffDuration_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
false, // default value
|
||||
true // isGlobal
|
||||
[0, 10, 1, 2],
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(enableAmmoCookoff), "CHECKBOX",
|
||||
[LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
true, // default value
|
||||
true // isGlobal
|
||||
] 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, 10, 1, 2],
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(destroyVehicleAfterCookoff),
|
||||
"CHECKBOX",
|
||||
[LSTRING(destroyVehicleAfterCookoff_name), LSTRING(destroyVehicleAfterCookoff_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
false,
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(enableAmmoCookoff),
|
||||
"CHECKBOX",
|
||||
[LSTRING(enableAmmoCookoff_name), LSTRING(enableAmmoCookoff_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
true,
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(enableAmmobox),
|
||||
"CHECKBOX",
|
||||
[LSTRING(enableBoxCookoff_name), LSTRING(enableBoxCookoff_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
true,
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(ammoCookoffDuration),
|
||||
"SLIDER",
|
||||
[LSTRING(ammoCookoffDuration_name), LSTRING(ammoCookoffDuration_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
[0, 10, 1, 2],
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
||||
[
|
||||
QGVAR(removeAmmoDuringCookoff),
|
||||
"CHECKBOX",
|
||||
[LSTRING(removeAmmoDuringCookoff_name), LSTRING(removeAmmoDuringCookoff_tooltip)],
|
||||
LSTRING(category_displayName),
|
||||
true,
|
||||
1
|
||||
] call CBA_fnc_addSetting;
|
||||
|
@ -16,14 +16,12 @@
|
||||
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
||||
|
||||
#define IS_EXPLOSIVE_AMMO(ammo) (getNumber (ammo call CBA_fnc_getObjectConfig >> "explosive") > 0.5)
|
||||
|
||||
// Stages of cookoff in order (in seconds)
|
||||
// Should be no un-synced randomness in these as the effects must be ran on each client
|
||||
#define IGNITE_TIME 3
|
||||
#define SMOKE_TIME 10.5
|
||||
// Should be no un-synced randomness in these as the effects must be run on each client
|
||||
#define SMOKE_DELAY 10.5
|
||||
#define DETONATION_DELAY 3
|
||||
#define COOKOFF_TIME 14 // Cook off time should be 20s at most due to length of sound files
|
||||
#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
|
||||
@ -32,9 +30,6 @@
|
||||
#define MIN_AMMO_DETONATION_START_DELAY 1 // Min time to wait before a vehicle's ammo starts to cookoff
|
||||
#define MAX_AMMO_DETONATION_START_DELAY 6 // Max time to wait before a vehicle's ammo starts to cookoff
|
||||
|
||||
// Delay between flame effect for players in a cooking off vehicle
|
||||
#define FLAME_EFFECT_DELAY 0.4
|
||||
|
||||
// Common commander hatch defines for default vehicles
|
||||
#define DEFAULT_COMMANDER_HATCHES ["osa_poklop_commander", "hatch_commander_axis"]
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<Project name="ACE">
|
||||
<Package name="CookOff">
|
||||
<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>
|
||||
<Italian>ACE Detonazione Munizioni</Italian>
|
||||
<Chinese>ACE 殉爆效果</Chinese>
|
||||
@ -16,158 +16,26 @@
|
||||
<Portuguese>ACE Cook off</Portuguese>
|
||||
<Czech>ACE Vznícení munice</Czech>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enable_hd_name">
|
||||
<English>Damage handling and turret effects</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 ID="STR_ACE_CookOff_enableFire_name">
|
||||
<English>Enable vehicle cook-off fire</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enable_hd_tooltip">
|
||||
<English>Changes damage handling for cook off and turret explosion effects</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 ID="STR_ACE_CookOff_enableFire_tooltip">
|
||||
<English>Enables vehicle cook-off fire effects.\nThis doesn't include ammunition detonations.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableBoxCookoff_name">
|
||||
<English>Enable ammo box cook off</English>
|
||||
<Spanish>Habilitar detonación inducida por calor en las cajas de munición</Spanish>
|
||||
<Japanese>弾薬箱の誘爆を有効化</Japanese>
|
||||
<German>Durchzündung für Munitionskisten ermöglichen</German>
|
||||
<Korean>탄약 상자 쿡오프 현상 활성화</Korean>
|
||||
<Polish>Aktywuj samozapłon skrzyń z amunicją</Polish>
|
||||
<French>Auto-inflammation des caisses de munitions</French>
|
||||
<Italian>Abilita esplosione casse munizioni</Italian>
|
||||
<Chinese>開啟彈藥箱殉爆效果</Chinese>
|
||||
<Chinesesimp>开启弹药箱殉爆效果</Chinesesimp>
|
||||
<Russian>Разрешить детонацию ящиков с боеприпасами</Russian>
|
||||
<Portuguese>Permitir cozinhar caixas de munição</Portuguese>
|
||||
<Czech>Povolit vynícení munice v krabicích</Czech>
|
||||
<Key ID="STR_ACE_CookOff_cookoffDuration_name">
|
||||
<English>Vehicle cook-off fire duration multiplier</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableBoxCookoff_tooltip">
|
||||
<English>Enables cooking off of ammo boxes.</English>
|
||||
<Spanish>Habilita la detonación inducida por calor en las cajas de munición</Spanish>
|
||||
<Japanese>弾薬箱が誘爆するようになります。</Japanese>
|
||||
<German>Ermöglicht Durchzündung von Munitionskisten.</German>
|
||||
<Korean>탄약 상자에 쿡오프 현상을 적용합니다.</Korean>
|
||||
<Polish>Aktywuje samozapłon skrzyń z amunicją</Polish>
|
||||
<French>Permet l'auto-inflammation des caisses de munitions.</French>
|
||||
<Italian>Abilita l'esplosione di casse di munizioni distrutte.</Italian>
|
||||
<Chinese>開啟彈藥箱殉爆效果</Chinese>
|
||||
<Chinesesimp>开启弹药箱殉爆效果</Chinesesimp>
|
||||
<Russian>Активирует детонацию ящиков с боеприпасами</Russian>
|
||||
<Portuguese>Permitir que caixas de munição cozinhem.</Portuguese>
|
||||
<Czech>Zapíná vznícení munice v krabicích.</Czech>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableAmmoCookoff_name">
|
||||
<English>Enable Ammunition 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 ID="STR_ACE_CookOff_enableAmmoCookoff_tooltip">
|
||||
<English>Enables Ammunition cook off. Fires ammunition projectiles while vehicle is on fire and has ammunition.</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>
|
||||
<Japanese>弾薬が誘爆します。車両が燃えると、搭載している弾薬が激しく燃え上がります。</Japanese>
|
||||
<German>Ermöglicht Durchzündung von Munition. Feuert Projektile der Munition ab, solange das Fahrzeug brennt und Munition besitzt.</German>
|
||||
<Polish>Aktywuje samozapłon amunicji. Wystrzeliwuje pociski podczas gdy pojazd płonie i posiada amunicję.</Polish>
|
||||
<French>Permet l'auto-inflammation des munitions. Tire des projectiles tant que le véhicule est en feu et contient des munitions.</French>
|
||||
<Italian>Abilita l'esplosione di munizioni. Spara proiettili di munizioni quando il veicolo va a fuoco e contiene ancora munizioni.</Italian>
|
||||
<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 ID="STR_ACE_CookOff_ammoCookoffDuration_name">
|
||||
<English>Ammunition cook off duration</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 ID="STR_ACE_CookOff_ammoCookoffDuration_tooltip">
|
||||
<English>Multiplier for how long cook off lasts [Setting 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 ID="STR_ACE_CookOff_cookoffDuration_tooltip">
|
||||
<English>Multiplier for how long vehicle cook-off fire lasts.\nSetting to 0 will disable vehicle cook-off fire.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_probabilityCoef_name">
|
||||
<English>Cook-off probability coefficient</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>
|
||||
<English>Vehicle cook-off fire probability multiplier</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_probabilityCoef_tooltip">
|
||||
<English>Multiplier for cook-off probability. Higher value results in higher cook-off probability</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>
|
||||
<English>Multiplier for vehicle cook-off fire probability. Higher value results in higher cook-off probability.\nSetting to 0 will disable vehicle cook-off fire.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_destroyVehicleAfterCookoff_name">
|
||||
<English>Destroy Vehicles After Cook-off</English>
|
||||
<English>Destroy vehicles after cook-off</English>
|
||||
<Korean>쿡오프 후 차량 파괴</Korean>
|
||||
<Chinesesimp>殉爆发生后摧毁载具</Chinesesimp>
|
||||
<Russian>Уничтожать технику после детонации</Russian>
|
||||
@ -191,31 +59,52 @@
|
||||
<Russian>Определяет, всегда ли транспортные средства будут уничтожаться после детонации.</Russian>
|
||||
<Spanish>Controla si los vehículos siempre será destruidos despues de la detonación inducida por calor.</Spanish>
|
||||
</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 ID="STR_ACE_CookOff_enableAmmoCookoff_name">
|
||||
<English>Enable vehicle ammo cook-off</English>
|
||||
</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 ID="STR_ACE_CookOff_enableAmmoCookoff_tooltip">
|
||||
<English>Enables cooking off of vehicle ammunition. Fires ammunition projectiles while vehicle has ammunition remaining.\nThis doesn't include fire effects.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableBoxCookoff_name">
|
||||
<English>Enable ammo box cook-off</English>
|
||||
<Spanish>Habilitar detonación inducida por calor en las cajas de munición</Spanish>
|
||||
<Japanese>弾薬箱の誘爆を有効化</Japanese>
|
||||
<German>Durchzündung für Munitionskisten ermöglichen</German>
|
||||
<Korean>탄약 상자 쿡오프 현상 활성화</Korean>
|
||||
<Polish>Aktywuj samozapłon skrzyń z amunicją</Polish>
|
||||
<French>Auto-inflammation des caisses de munitions</French>
|
||||
<Italian>Abilita esplosione casse munizioni</Italian>
|
||||
<Chinese>開啟彈藥箱殉爆效果</Chinese>
|
||||
<Chinesesimp>开启弹药箱殉爆效果</Chinesesimp>
|
||||
<Russian>Разрешить детонацию ящиков с боеприпасами</Russian>
|
||||
<Portuguese>Permitir cozinhar caixas de munição</Portuguese>
|
||||
<Czech>Povolit vynícení munice v krabicích</Czech>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_enableBoxCookoff_tooltip">
|
||||
<English>Enables cooking off of ammo boxes.\nThis doesn't include fire effects.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_ammoCookoffDuration_name">
|
||||
<English>Ammo cook-off duration multiplier</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_ammoCookoffDuration_tooltip">
|
||||
<English>Multiplier for how long ammunition cook-off lasts, for both vehicles and ammo boxes.\nSetting to 0 will disable ammo cook-off for both vehicles and ammo boxes.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_removeAmmoDuringCookoff_name">
|
||||
<English>Enable ammo removal during cook-off</English>
|
||||
<Japanese>誘爆中の弾薬除去を有効/無効にする</Japanese>
|
||||
<French>Retirer les munitions durant l'auto-inflammation</French>
|
||||
<German>Aktiviert/Deaktiviert Entfernung der Munition beim Durchzünden</German>
|
||||
<Italian>Abilita rimozione munizioni dopo l'esplosione</Italian>
|
||||
<Polish>Włącz/Wyłącz usuwanie amunicji podczas samozapłonu</Polish>
|
||||
<Chinesesimp>启用/禁用殉爆过程中的弹药移除功能</Chinesesimp>
|
||||
<Korean>쿡오프시 탄약 제거 활성화/비활성화</Korean>
|
||||
<Russian>Удалять боеприпасы из-за детонации</Russian>
|
||||
<Spanish>Habilita/Deshabilita ka eliminación de munición durante la detonación inducida por calor</Spanish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_CookOff_removeAmmoDuringCookoff_tooltip">
|
||||
<English>Removes all ammo during cook-off.</English>
|
||||
<French>Retire des munitions des véhicules durant une auto-inflammation.</French>
|
||||
<German>Entfernt Munition während dem Durchzünden der Munition eines Fahrzeuges.</German>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
||||
|
@ -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,cookOffBoxServer), _box] 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,engineFireServer), _vehicle] call CBA_fnc_serverEvent;
|
||||
};
|
||||
};
|
||||
|
@ -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,engineFireServer), _vehicle] call CBA_fnc_serverEvent;
|
||||
};
|
||||
|
@ -6,7 +6,6 @@
|
||||
* Arguments:
|
||||
* 0: The vehicle <OBJECT>
|
||||
* 1: Person who caused detonation <OBJECT> (default: objNull)
|
||||
* 2: An array of vehicle ammo in vehicle <ARRAY> (default: [])
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
@ -17,16 +16,12 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", ["_injurer", objNull], ["_vehicleAmmo", []]];
|
||||
params ["_vehicle", ["_injurer", objNull]];
|
||||
|
||||
if (_vehicleAmmo isEqualTo []) then {
|
||||
_vehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo);
|
||||
};
|
||||
|
||||
([_vehicle] + _vehicleAmmo) call EFUNC(cookoff,detonateAmmunition);
|
||||
|
||||
if ((_vehicleAmmo select 1) > 0) then {
|
||||
if (((_vehicle call EFUNC(cookoff,getVehicleAmmo)) select 1) > 0) then {
|
||||
{
|
||||
[QGVAR(medicalDamage), [_x, _injurer, _injurer], _x] call CBA_fnc_targetEvent;
|
||||
} forEach (crew _vehicle);
|
||||
};
|
||||
|
||||
[QEGVAR(cookoff,detonateAmmunitionServer), [_vehicle, false, _injurer, _injurer]] call CBA_fnc_serverEvent;
|
||||
|
@ -23,9 +23,12 @@
|
||||
|
||||
params ["_vehicle", "_chanceOfFire", "_intensity", ["_injurer", objNull], ["_hitPart", ""], ["_canRing", false], ["_canJet", true]];
|
||||
|
||||
private _alreadyCookingOff = _vehicle getVariable [QGVAR(cookingOff), false];
|
||||
// Ignore if the vehicle is already cooking off
|
||||
if (_vehicle getVariable [QEGVAR(cookoff,isCookingOff), false]) exitWith {true};
|
||||
|
||||
if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith {
|
||||
_chanceOfFire = _chanceOfFire * EGVAR(cookoff,probabilityCoef);
|
||||
|
||||
if (_chanceOfFire >= random 1) exitWith {
|
||||
private _configOf = configOf _vehicle;
|
||||
private _fireDetonateChance = [_configOf >> QGVAR(detonationDuringFireProb), "number", 0] call CBA_fnc_getConfigEntry;
|
||||
if (_canRing) then {
|
||||
@ -44,28 +47,13 @@ if (!_alreadyCookingOff && { _chanceOfFire >= random 1 }) exitWith {
|
||||
_source = ["hit_engine_point", "HitPoints"];
|
||||
};
|
||||
|
||||
// sending nil for _maxIntensity (9th param) to use default value in ace_cookoff_fnc_cookOff
|
||||
[QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, nil, _canJet]] call CBA_fnc_localEvent;
|
||||
_vehicle setVariable [QGVAR(cookingOff), true];
|
||||
[QEGVAR(cookOff,cookOffServer), [_vehicle, _intensity, _injurer, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, _canJet]] call CBA_fnc_serverEvent;
|
||||
LOG_4("Cooking-off [%1] with a chance-of-fire [%2] - Delayed Smoke | Detonate after cookoff [%3 | %4]",_vehicle,_chanceOfFire,_delayWithSmoke,_detonateAfterCookoff);
|
||||
[_vehicle] spawn FUNC(abandon);
|
||||
LOG_1("[%1] is on fire is bailing",_vehicle);
|
||||
|
||||
// cant setVehicleAmmo 0 here because it removes FFV unit's ammo
|
||||
if (GVAR(removeAmmoDuringCookoff)) then {
|
||||
private _ammo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo);
|
||||
_ammo params ["_magazines"];
|
||||
TRACE_1("removing magazines",_magazines);
|
||||
{
|
||||
_x params ["_magazine"];
|
||||
_vehicle removeMagazines _magazine;
|
||||
} forEach _magazines;
|
||||
};
|
||||
true
|
||||
};
|
||||
|
||||
// Avoid RPT spam
|
||||
if (_alreadyCookingOff) exitWith { true };
|
||||
|
||||
LOG_2("[%1] No Cook-off - Chance of fire [%2]",_vehicle,_chanceOfFire);
|
||||
false
|
||||
|
@ -21,18 +21,17 @@
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_chanceOfDetonate", "_vehicleAmmo", "_explosiveAmmoCount", "_nonExplosiveAmmoCount", ["_injurer", objNull]];
|
||||
private _alreadyDetonating = _vehicle getVariable [QGVAR(detonating), false];
|
||||
|
||||
private _isKnockedOut = _explosiveAmmoCount > 0;
|
||||
|
||||
if (!_alreadyDetonating && { _chanceOfDetonate >= random 1 }) exitWith {
|
||||
// Ignore if the vehicle is already detonating ammo
|
||||
if (_vehicle getVariable [QEGVAR(cookoff,isAmmoDetonating), false]) exitWith {_isKnockedOut};
|
||||
|
||||
if (_chanceOfDetonate >= random 1) exitWith {
|
||||
[_vehicle, _injurer, _vehicleAmmo] call FUNC(detonate);
|
||||
LOG_2("Detonating [%1] with a chance-to-detonate [%2]",_vehicle,_chanceOfDetonate);
|
||||
_vehicle setVariable [QGVAR(detonating), true];
|
||||
_isKnockedOut
|
||||
};
|
||||
|
||||
// Avoid RPT spam
|
||||
if (_alreadyDetonating) exitWith { _isKnockedOut };
|
||||
|
||||
LOG_2("[%1] No Detonation - Chance of detonation [%2]",_vehicle,_chanceOfDetonate);
|
||||
false
|
||||
|
@ -117,7 +117,7 @@ if (_isCar) then {
|
||||
_ammoEffectiveness = (_ammoEffectiveness + (_ammoEffectiveness * 0.5)) min 1;
|
||||
};
|
||||
|
||||
private _currentVehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo);
|
||||
private _currentVehicleAmmo = _vehicle call EFUNC(cookoff,getVehicleAmmo);
|
||||
private _chanceOfDetonation = 0;
|
||||
private _explosiveAmmoCount = 0;
|
||||
private _nonExplosiveAmmoCount = 0;
|
||||
@ -161,7 +161,7 @@ switch (_hitArea) do {
|
||||
_chanceOfFire = 0; // no cookoff for cars
|
||||
};
|
||||
|
||||
if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
[_vehicle] call FUNC(knockOut);
|
||||
};
|
||||
|
||||
@ -189,7 +189,7 @@ switch (_hitArea) do {
|
||||
_chanceOfFire = 0; // no cookoff for cars
|
||||
};
|
||||
|
||||
if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
[_vehicle, _hitIndex, _hitpointName, 0.89 * _penChance] call FUNC(addDamage);
|
||||
[_vehicle] call FUNC(knockOut);
|
||||
};
|
||||
@ -263,7 +263,7 @@ switch (_hitArea) do {
|
||||
_chanceOfFire = 0; // no cookoff for cars
|
||||
};
|
||||
|
||||
if ([_vehicle, _chanceToDetonate, _currentVehicleAmmo, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
if ([_vehicle, _chanceToDetonate, _explosiveAmmoCount, _nonExplosiveAmmoCount, _injurer] call FUNC(handleDetonation)) exitWith {
|
||||
[_vehicle] call FUNC(knockOut);
|
||||
};
|
||||
|
||||
|
@ -8,14 +8,6 @@
|
||||
true // Needs mission restart
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
[
|
||||
QGVAR(removeAmmoDuringCookoff), "CHECKBOX",
|
||||
[LSTRING(removeAmmoAfterCookoff_setting_enable), LSTRING(removeAmmoAfterCookoff_setting_description)],
|
||||
LSTRING(category_displayName),
|
||||
true, // default value
|
||||
true // isGlobal
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
[
|
||||
QGVAR(enableCarDamage), "CHECKBOX",
|
||||
[LSTRING(carDamage_setting_enable), LSTRING(carDamage_setting_description)],
|
||||
|
@ -49,30 +49,6 @@
|
||||
<Russian>Продвинутое повреждение машин</Russian>
|
||||
<Spanish>Habilitar/Deshabilitar daño avanzado de coche (Experimental)</Spanish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Vehicle_Damage_removeAmmoAfterCookoff_setting_description">
|
||||
<English>Removes all vehicle ammo after cook-off</English>
|
||||
<Japanese>誘爆後に車両から全ての弾薬を削除</Japanese>
|
||||
<French>Retire toutes les munitions des véhicules après une auto-inflammation.</French>
|
||||
<German>Entfernt die gesamte Munition nach dem Durchzünden der Munition eines Fahrzeuges.</German>
|
||||
<Italian>Rimuove tutte le munizioni dal veicolo dopo l'esplosione delle stesse</Italian>
|
||||
<Polish>Usuwa całą amunicję z pojazdu po samozapłonie</Polish>
|
||||
<Chinesesimp>殉爆后移除所有车辆弹药</Chinesesimp>
|
||||
<Korean>쿡오프 현상 후 차량에서 모든 탄약을 제거합니다.</Korean>
|
||||
<Russian>Удалять все боеприпасы из техники после их детонации</Russian>
|
||||
<Spanish>Elimina toda la munición del vehículo despues ser inducida a detonar por calor</Spanish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Vehicle_Damage_removeAmmoAfterCookoff_setting_enable">
|
||||
<English>Enable/Disable Ammo Removal During Cook-Off</English>
|
||||
<Japanese>誘爆中の弾薬除去を有効/無効にする</Japanese>
|
||||
<French>Retirer les munitions durant l'auto-inflammation</French>
|
||||
<German>Aktiviert/Deaktiviert Entfernung der Munition beim Durchzünden</German>
|
||||
<Italian>Abilita rimozione munizioni dopo l'esplosione</Italian>
|
||||
<Polish>Włącz/Wyłącz usuwanie amunicji podczas samozapłonu</Polish>
|
||||
<Chinesesimp>启用/禁用殉爆过程中的弹药移除功能</Chinesesimp>
|
||||
<Korean>쿡오프시 탄약 제거 활성화/비활성화</Korean>
|
||||
<Russian>Удалять боеприпасы из-за детонации</Russian>
|
||||
<Spanish>Habilita/Deshabilita ka eliminación de munición durante la detonación inducida por calor</Spanish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Vehicle_Damage_generic_turret_wreck">
|
||||
<English>Wreck (Turret)</English>
|
||||
<French>Épave (tourelle)</French>
|
||||
|
@ -12,43 +12,22 @@ version:
|
||||
patch: 0
|
||||
---
|
||||
|
||||
## 1. Disabling / Enabling Cook off for individual vehicles
|
||||
## 1. Disabling cook-off fire for individual vehicles
|
||||
|
||||
You can dynamically enable and/or disable vehicle cook off for individual vehicles by using `setVariable`:
|
||||
Cook-off fire can be disabled for a specific vehicle (does not affect ammo cook-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 (does not affect cook-off fire):
|
||||
|
||||
```
|
||||
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.
|
||||
|
@ -103,18 +103,17 @@ MenuType: 0 = Interaction, 1 = Self Interaction
|
||||
|
||||
| Event Key | Parameters | Locality | Type | Description |
|
||||
|----------|---------|---------|---------|---------|
|
||||
|`ace_refuel_started` | [_source, _target] | Local | Listen | Refueling has started |
|
||||
|`ace_refuel_started` | [_source, _target] | Local | Listen | Refuelling has started |
|
||||
|`ace_refuel_tick` | [_source, _target, _amount] | Local | Listen | Amount of fuel transferred in a tick |
|
||||
|`ace_refuel_stopped` | [_source, _target] | Local | Listen | Refueling has stopped |
|
||||
|`ace_refuel_stopped` | [_source, _target] | Local | Listen | Refuelling has stopped |
|
||||
|
||||
### 2.10 Cook Off (`ace_cookoff`)
|
||||
|
||||
| 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] | Global | Listen | Vehicle cook-off has started |
|
||||
|`ace_cookoff_cookOffBox` | [_box, _source, _instigator, _delay] | Global | Listen | Ammo box cook-off has started |
|
||||
|`ace_cookoff_engineFire` | [_vehicle] | Global | Listen | Engine fire has started |
|
||||
|
||||
### 2.11 Attach (`ace_attach`)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user