Separate effect handling

This commit is contained in:
johnb432 2024-02-06 01:06:30 +01:00
parent 0ec391a3a5
commit 51aa46c81f
8 changed files with 78 additions and 92 deletions

View File

@ -12,41 +12,37 @@ if (isServer) then {
[QGVAR(detonateAmmunition), LINKFUNC(detonateAmmunition)] call CBA_fnc_addEventHandler;
};
// Handle cleaning up effects when vehicle is deleted mid cook-off
[QGVAR(addCleanupHandlers), {
params ["_object"];
// Don't add a new EH if cook-off is run multiple times
if (!isNil {_object getVariable QGVAR(deletedEH)}) exitWith {};
_object setVariable [QGVAR(deletedEH),
_object addEventHandler ["Deleted", {
[QGVAR(cleanupEffects), _this select 0] call CBA_fnc_localEvent;
}]
];
}] call CBA_fnc_addEventHandler;
[QGVAR(cleanupEffects), {
params ["_object"];
if (isServer) then {
// Reset, so that the object can cook-off again
_object setVariable [QGVAR(isCookingOff), nil, true];
// Remove effects from JIP
{
_x call CBA_fnc_removeGlobalEventJIP;
} forEach (_object getVariable [QGVAR(jipIDs), []]);
_object setVariable [QGVAR(jipIDs), nil];
};
// All effects are local (apart from sound, which is global, but is handled by server)
// Handle cleaning up effects when objects are deleted mid cook-off
["AllVehicles", "Deleted", {
{
deleteVehicle _x;
} forEach (_object getVariable [QGVAR(effects), []]);
} forEach ((_this select 0) getVariable [QGVAR(vehicleEffects), []]);
}, nil, nil, true] call CBA_fnc_addClassEventHandler;
_object setVariable [QGVAR(effects), nil];
["ReammoBox_F", "Deleted", {
{
deleteVehicle _x;
} forEach ((_this select 0) getVariable [QGVAR(boxEffects), []]);
}, nil, nil, true] call CBA_fnc_addClassEventHandler;
[QGVAR(cleanupVehicleEffects), {
params ["_object"];
{
deleteVehicle _x;
} forEach (_object getVariable [QGVAR(vehicleEffects), []]);
_object setVariable [QGVAR(vehicleEffects), nil];
}] call CBA_fnc_addEventHandler;
[QGVAR(cleanupBoxEffects), {
params ["_object"];
{
deleteVehicle _x;
} forEach (_object getVariable [QGVAR(boxEffects), []]);
_object setVariable [QGVAR(boxEffects), nil];
}] call CBA_fnc_addEventHandler;
["ReammoBox_F", "init", {

View File

@ -7,14 +7,15 @@
* Arguments:
* 0: Vehicle <OBJECT>
* 1: Intensity of fire <NUMBER>
* 2: Instigator <OBJECT> (default: objNull)
* 3: Delay between smoke and fire enabled <BOOL> (default: true)
* 4: Ammo detonation chance <NUMBER> (default: 0)
* 5: Detonate after cook-off <BOOL> (default: false)
* 6: Selection for fire source <STRING> (default: "")
* 7: Can spawn fire ring <BOOL> (default: true)
* 8: Can spawn fire jet <BOOL> (default: true)
* 9: Maximum intensity <NUMBER> (default: MAX_COOKOFF_INTENSITY)
* 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
@ -31,6 +32,7 @@ if (GVAR(enable) == 0 || {GVAR(cookoffDuration) == 0}) exitWith {};
params [
"_vehicle",
"_intensity",
["_source", objNull],
["_instigator", objNull],
["_delayBetweenSmokeAndFire", true],
["_ammoDetonationChance", 0],
@ -41,6 +43,8 @@ params [
["_maxIntensity", MAX_COOKOFF_INTENSITY]
];
if !(_vehicle isKindOf "AllVehicles") exitWith {};
// Check if cook-off is disabled on vehicle specifically
if !(_vehicle getVariable [QGVAR(enable), true]) exitWith {};
@ -54,9 +58,6 @@ if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {};
_vehicle setVariable [QGVAR(isCookingOff), true, true];
// Only required on the server, as the only effect to clean up is to remove the effects from the JIP queue
[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent;
// Limit maximum value of intensity to prevent very long cook-off times
_intensity = _intensity min _maxIntensity;
@ -81,7 +82,6 @@ private _fireJipID = format [QGVAR(cookOffEffect_%1), hashValue _vehicle];
// Spawn smoke
private _smokeJipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP;
_vehicle setVariable [QGVAR(jipIDs), [_smokeJipID, _fireJipID]];
// Save intensity for looping purposes
_vehicle setVariable [QGVAR(intensity), _intensity];
@ -94,21 +94,25 @@ if (_delayBetweenSmokeAndFire) then {
[{
[{
(_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_fireJipID"];
(_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_source", "_instigator", "_fireSource", "_canRing", "_canJet", "_smokeJipID", "_fireJipID"];
private _intensity = _vehicle getVariable [QGVAR(intensity), 0];
if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith {
(_this select 1) call CBA_fnc_removePerFrameHandler;
// Remove effects from JIP
_smokeJipID call CBA_fnc_removeGlobalEventJIP;
_fireJipID call CBA_fnc_removeGlobalEventJIP;
// Effects are deleted when vehicle is deleted
if (isNull _vehicle) exitWith {};
// Remove effects on server
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_localEvent;
// Remove effects
[QGVAR(cleanupVehicleEffects), _vehicle] call CBA_fnc_globalEvent;
if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then {
_vehicle setDamage [1, true, _instigator, _instigator]; // because it's running on the server, killer and instigator can be set
_vehicle setDamage [1, true, _source, _instigator]; // because it's running on the server, killer and instigator can be set
};
};
@ -146,7 +150,7 @@ if (_delayBetweenSmokeAndFire) then {
};
};
if (_ammoDetonationChance > random 1 && {CBA_missionTime >= _vehicle getVariable [QGVAR(nextExplosiveDetonation), 0]}) then {
if (_ammoDetonationChance > random 1 && {_vehicle getVariable [QGVAR(nextExplosiveDetonation), 0] <= CBA_missionTime}) then {
if (_fireSource isEqualTo "") then {
_fireSource = selectRandom _positions;
};
@ -156,4 +160,4 @@ if (_delayBetweenSmokeAndFire) then {
_vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60];
};
}, 0.25, _this] call CBA_fnc_addPerFrameHandler;
}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _fireJipID], _delay] call CBA_fnc_waitAndExecute;
}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _source, _instigator, _fireSource, _canRing, _canJet, _smokeJipID, _fireJipID], _delay] call CBA_fnc_waitAndExecute;

View File

@ -5,7 +5,7 @@
*
* Arguments:
* 0: Ammo box <OBJECT>
* 1: Killer <OBJECT> (default: objNull)
* 1: Source <OBJECT> (default: objNull)
* 2: Instigator <OBJECT> (default: objNull)
*
* Return Value:
@ -19,7 +19,10 @@
if (!isServer) exitWith {};
params ["_box", ["_killer", objNull], ["_instigator", objNull]];
params ["_box", ["_source", objNull], ["_instigator", objNull]];
// Make sure it's a box
if !(_box isKindOf "ReammoBox_F") exitWith {};
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
@ -28,7 +31,7 @@ _box setVariable [QGVAR(isCookingOff), true, true];
// Spawn cook-off effects on all connected machines
private _jipID = [QGVAR(cookOffBoxLocal), [
_box,
_killer,
_source,
_instigator,
CBA_missionTime,
random [SMOKE_DELAY / 2, SMOKE_DELAY, SMOKE_DELAY / 2 * 3] // generate random timer that is global synced

View File

@ -5,7 +5,7 @@
*
* Arguments:
* 0: Box <OBJECT>
* 1: Killer <OBJECT>
* 1: Source <OBJECT>
* 2: Instigator <OBJECT>
* 3: Start time of the cook-off <NUMBER>
* 4: Smoke delay <NUMBER>
@ -22,10 +22,10 @@
params ["", "", "", "_startTime", "_smokeDelay"];
[{
params ["_box", "_killer", "_instigator"];
params ["_box", "_source", "_instigator"];
// Make sure effects are cleaned up if box is deleted
[QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent;
// If box was deleted before smoke could be spawned, just exit
if (isNull _box) exitWith {};
private _boxPos = ASLToAGL getPosASL _box;
private _effects = [];
@ -46,8 +46,8 @@ params ["", "", "", "_startTime", "_smokeDelay"];
_effects pushBack _sound;
// Detonate the ammunition
[QGVAR(detonateAmmunition), [_box, true, _killer, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent;
[QGVAR(detonateAmmunition), [_box, true, _source, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent;
};
_box setVariable [QGVAR(effects), _effects];
_box setVariable [QGVAR(boxEffects), _effects];
}, _this, (_startTime - CBA_missionTime + _smokeDelay) max 0] call CBA_fnc_waitAndExecute; // this delay allows for synchronisation for JIP players

View File

@ -6,7 +6,7 @@
* Arguments:
* 0: Object <OBJECT>
* 1: Destroy when finished <BOOL> (default: false)
* 2: Killer <OBJECT> (default: objNull)
* 2: Source <OBJECT> (default: objNull)
* 3: Instigator <OBJECT> (default: objNull)
* 4: Initial delay <NUMBER> (default: 0)
*
@ -21,7 +21,7 @@
if (!isServer) exitWith {};
params ["_object", ["_destroyWhenFinished", false], ["_killer", objNull], ["_instigator", objNull], ["_initialDelay", 0]];
params ["_object", ["_destroyWhenFinished", false], ["_source", objNull], ["_instigator", objNull], ["_initialDelay", 0]];
if (isNull _object) exitWith {};
@ -47,12 +47,12 @@ _objectAmmo params ["_magazines", "_totalAmmo"];
// If the cook-off has finished, clean up the effects and destroy the object
if (_magazines isEqualTo [] || {_totalAmmo <= 0}) exitWith {
[QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent;
[QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent;
_object setVariable [QGVAR(cookoffMagazines), nil];
if (_destroyWhenFinished) then {
_object setDamage [1, true, _killer, _instigator];
_object setDamage [1, true, _source, _instigator];
};
};
@ -66,14 +66,14 @@ if (underwater _object || {
!(GVAR(enableAmmoCookoff) && {_object getVariable [QGVAR(enableAmmoCookoff), true]})
}) exitWith {
[QGVAR(cleanupEffects), _object] call CBA_fnc_globalEvent;
[QGVAR(cleanupBoxEffects), _object] call CBA_fnc_globalEvent;
_object setVariable [QGVAR(cookoffMagazines), nil];
};
// Initial delay allows for a delay for the first time this function runs in its cycle
if (_initialDelay > 0) exitWith {
[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _initialDelay] call CBA_fnc_waitAndExecute;
[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _source, _instigator], _initialDelay] call CBA_fnc_waitAndExecute;
};
private _magazineIndex = floor random (count _magazines);
@ -101,7 +101,7 @@ _totalAmmo = _totalAmmo - _removed;
_object setVariable [QGVAR(cookoffMagazines), [_magazines, _totalAmmo]];
// Detonate the remaining ammo after a delay
[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _killer, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
[FUNC(detonateAmmunition), [_object, _destroyWhenFinished, _source, _instigator], _timeBetweenAmmoDetonation] call CBA_fnc_waitAndExecute;
// Get magazine info, which is used to spawn projectiles
private _configMagazine = configFile >> "CfgMagazines" >> _magazineClassname;

View File

@ -15,46 +15,32 @@
* Public: No
*/
params ["_box", "", "_damage", "_source", "_ammo", "_hitIndex", "_instigator"];
params ["_box", "", "_damage", "_source", "_ammo", "", "_instigator", "_hitPoint"];
if (!local _box) exitWith {};
// If it's already dead, ignore
if (damage _box >= 1) exitWith {};
if (!alive _box) exitWith {};
// If cookoff for boxes is disabled, exit
if (!GVAR(enableAmmobox) || {GVAR(ammoCookoffDuration) == 0}) exitWith {};
if !(_box getVariable [QGVAR(enableAmmoCookoff), true]) exitWith {};
// Get hitpoint name
private _hitpoint = "#structural";
if (_hitIndex != -1) then {
_hitpoint = ((getAllHitPointsDamage _box) param [0, []]) select _hitIndex;
};
if !(_hitpoint == "#structural" && {_damage > 0.5}) exitWith {};
if !(_hitPoint == "" && {_damage > 0.5}) exitWith {}; // "" means structural damage
// Catch fire when hit by an explosive round
if (IS_EXPLOSIVE_AMMO(_ammo)) then {
[QGVAR(cookOffBox), [_box, _source, _instigator]] call CBA_fnc_serverEvent;
} else {
// Get change in damage
private _oldDamage = if (_hitpoint == "#structural") then {
damage _box
} else {
_box getHitIndex _hitIndex
};
// There is a small chance of cooking a box off if it's shot by tracer ammo
if !(random 1 < _oldDamage * 0.05) exitWith {};
if (random 1 >= _damage * 0.05) exitWith {};
// Need magazine to check for tracers
private _magazine = if (_source == _instigator) then {
currentMagazine _source
} else {
_source currentMagazineTurret (_box unitTurret _instigator)
_source currentMagazineTurret (_source unitTurret _instigator)
};
private _configMagazine = configFile >> "CfgMagazines" >> _magazine;

View File

@ -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,10 +16,7 @@
* Public: No
*/
params ["_vehicle", ["_positions", []]];
// Make sure effects are cleaned up if vehicle is deleted
[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent;
params ["_vehicle", "_positions"];
private _positionBarrelEnd = getText ([_vehicle, [0]] call CBA_fnc_getTurret >> "gunBeg");
@ -44,4 +41,4 @@ private _effects = [_smokeBarrel];
_effects pushBack _smoke;
} forEach _positions;
_vehicle setVariable [QGVAR(effects), _effects];
_vehicle setVariable [QGVAR(vehicleEffects), _effects];

View File

@ -47,7 +47,7 @@ if (_chanceOfFire >= random 1) exitWith {
_source = ["hit_engine_point", "HitPoints"];
};
[QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, _canJet]] call CBA_fnc_serverEvent;
[QEGVAR(cookOff,cookOff), [_vehicle, _intensity, _injurer, _injurer, _delayWithSmoke, _fireDetonateChance, _detonateAfterCookoff, _source, _canRing, _canJet]] call CBA_fnc_serverEvent;
LOG_4("Cooking-off [%1] with a chance-of-fire [%2] - Delayed Smoke | Detonate after cookoff [%3 | %4]",_vehicle,_chanceOfFire,_delayWithSmoke,_detonateAfterCookoff);
[_vehicle] spawn FUNC(abandon);
LOG_1("[%1] is on fire is bailing",_vehicle);