Various improvements

This commit is contained in:
johnb432 2024-02-05 17:31:27 +01:00
parent 0de629ec2e
commit ed4cea6c4a
9 changed files with 90 additions and 118 deletions

View File

@ -1,12 +1,12 @@
#include "script_component.hpp"
[QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler;
[QGVAR(cookOffBoxLocal), LINKFUNC(cookOffBoxLocal)] call CBA_fnc_addEventHandler;
[QGVAR(cookOffEffect), LINKFUNC(cookOffEffect)] call CBA_fnc_addEventHandler;
[QGVAR(engineFireLocal), LINKFUNC(engineFireLocal)] call CBA_fnc_addEventHandler;
[QGVAR(smoke), LINKFUNC(smoke)] call CBA_fnc_addEventHandler;
if (isServer) then {
[QGVAR(cookOff), LINKFUNC(cookOff)] call CBA_fnc_addEventHandler;
[QGVAR(cookOffBox), LINKFUNC(cookOffBox)] call CBA_fnc_addEventHandler;
[QGVAR(engineFire), LINKFUNC(engineFire)] call CBA_fnc_addEventHandler;
[QGVAR(detonateAmmunition), LINKFUNC(detonateAmmunition)] call CBA_fnc_addEventHandler;
@ -14,9 +14,6 @@ if (isServer) then {
// Handle cleaning up effects when vehicle is deleted mid cook-off
[QGVAR(addCleanupHandlers), {
// No effects on machines without interfaces
if (!hasInterface) exitWith {};
params ["_object"];
// Don't add a new EH if cook-off is run multiple times
@ -30,33 +27,24 @@ if (isServer) then {
}] call CBA_fnc_addEventHandler;
[QGVAR(cleanupEffects), {
params ["_object", ["_effects", []]];
params ["_object"];
if (isServer) then {
// Reset, so that object can cook-off again
// Reset, so that the object can cook-off again
_object setVariable [QGVAR(isCookingOff), nil, true];
// Remove effects from JIP
private _jipID = _object getVariable QGVAR(jipID);
{
_x call CBA_fnc_removeGlobalEventJIP;
} forEach (_object getVariable [QGVAR(jipIDs), []]);
if (isNil "_jipID") exitWith {};
_jipID call CBA_fnc_removeGlobalEventJIP;
_object setVariable [QGVAR(jipID), nil];
_object setVariable [QGVAR(jipIDs), nil];
};
// No effects on machines without interfaces
if (!hasInterface) exitWith {};
// All effects are local
_effects append (_object getVariable [QGVAR(effects), []]);
if (_effects isEqualTo []) exitWith {};
// All effects are local (apart from sound, which is global, but is handled by server)
{
deleteVehicle _x;
} forEach _effects;
} forEach (_object getVariable [QGVAR(effects), []]);
_object setVariable [QGVAR(effects), nil];
}] call CBA_fnc_addEventHandler;

View File

@ -13,8 +13,8 @@
* 5: Detonate after cook-off <BOOL> (default: false)
* 6: Selection for fire source <STRING> (default: "")
* 7: Can spawn fire ring <BOOL> (default: true)
* 8: Maximum intensity <NUMBER> (default: MAX_COOKOFF_INTENSITY)
* 9: Can spawn fire jet <BOOL> (default: true)
* 8: Can spawn fire jet <BOOL> (default: true)
* 9: Maximum intensity <NUMBER> (default: MAX_COOKOFF_INTENSITY)
*
* Return Value:
* None
@ -37,8 +37,8 @@ params [
["_detonateAfterCookoff", false],
["_fireSource", ""],
["_canRing", true],
["_maxIntensity", MAX_COOKOFF_INTENSITY, [0]],
["_canJet", true, [true]]
["_canJet", true],
["_maxIntensity", MAX_COOKOFF_INTENSITY]
];
// Check if cook-off is disabled on vehicle specifically
@ -54,6 +54,9 @@ if (_vehicle getVariable [QGVAR(isCookingOff), false]) exitWith {};
_vehicle setVariable [QGVAR(isCookingOff), true, true];
// Only required on the server, as the only effect to clean up is to remove the effects from the JIP queue
[QGVAR(addCleanupHandlers), _vehicle] call CBA_fnc_localEvent;
// Limit maximum value of intensity to prevent very long cook-off times
_intensity = _intensity min _maxIntensity;
@ -73,9 +76,12 @@ if (_positions isEqualTo []) then {
};
};
// Not guaranteed to be active/used, but reserve it nonetheless
private _fireJipID = format [QGVAR(cookOffEffect_%1), hashValue _vehicle];
// Spawn smoke
private _jipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP;
_vehicle setVariable [QGVAR(jipID), _jipID];
private _smokeJipID = [QGVAR(smoke), [_vehicle, _positions]] call CBA_fnc_globalEventJIP;
_vehicle setVariable [QGVAR(jipIDs), [_smokeJipID, _fireJipID]];
// Save intensity for looping purposes
_vehicle setVariable [QGVAR(intensity), _intensity];
@ -83,23 +89,23 @@ _vehicle setVariable [QGVAR(intensity), _intensity];
private _delay = 0;
if (_delayBetweenSmokeAndFire) then {
_delay = SMOKE_TIME + random SMOKE_TIME;
_delay = random [SMOKE_DELAY, 1.5 * SMOKE_DELAY, 2 * SMOKE_DELAY];
};
[{
[{
(_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet"];
(_this select 0) params ["_vehicle", "_positions", "_ammoDetonationChance", "_detonateAfterCookoff", "_instigator", "_fireSource", "_canRing", "_canJet", "_fireJipID"];
private _intensity = _vehicle getVariable [QGVAR(intensity), 0];
if (isNull _vehicle || {_intensity <= 1} || {GVAR(enable) == 0} || {GVAR(cookoffDuration) == 0}) exitWith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
(_this select 1) call CBA_fnc_removePerFrameHandler;
// Effects are deleted when vehicle is deleted
if (isNull _vehicle) exitWith {};
// Remove effects globally
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_globalEvent;
// Remove effects on server
[QGVAR(cleanupEffects), _vehicle] call CBA_fnc_localEvent;
if (GVAR(destroyVehicleAfterCookoff) || _detonateAfterCookoff) then {
_vehicle setDamage [1, true, _instigator, _instigator]; // because it's running on the server, killer and instigator can be set
@ -118,19 +124,19 @@ if (_delayBetweenSmokeAndFire) then {
};
};
private _time = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME;
private _duration = linearConversion [0, 10, _intensity, 3, 20] + random COOKOFF_TIME;
if (_fireSource isEqualTo "") then {
_fireSource = selectRandom _positions;
};
// As the cook-off effect is max 20s, this is not synced with JIP players
[QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _time, _fireSource, _intensity]] call CBA_fnc_globalEvent;
// Sync for JIP players
[QGVAR(cookOffEffect), [_vehicle, _canJet, _ring, _fireSource, _intensity, CBA_missionTime, _duration], _fireJipID] call CBA_fnc_globalEventJIP;
_intensity = _intensity - (0.5 max random 1) / GVAR(cookoffDuration);
_vehicle setVariable [QGVAR(intensity), _intensity];
_vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _time + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)];
_vehicle setVariable [QGVAR(nextFlame), CBA_missionTime + _duration + (MIN_TIME_BETWEEN_FLAMES max random MAX_TIME_BETWEEN_FLAMES)];
// If there are any crew, burn them
if (["ace_fire"] call EFUNC(common,isModLoaded)) then {
@ -150,4 +156,4 @@ if (_delayBetweenSmokeAndFire) then {
_vehicle setVariable [QGVAR(nextExplosiveDetonation), CBA_missionTime + random 60];
};
}, 0.25, _this] call CBA_fnc_addPerFrameHandler;
}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet], _delay] call CBA_fnc_waitAndExecute;
}, [_vehicle, _positions, _ammoDetonationChance, _detonateAfterCookoff, _instigator, _fireSource, _canRing, _canJet, _fireJipID], _delay] call CBA_fnc_waitAndExecute;

View File

@ -5,6 +5,8 @@
*
* Arguments:
* 0: Ammo box <OBJECT>
* 1: Killer <OBJECT> (default: objNull)
* 2: Instigator <OBJECT> (default: objNull)
*
* Return Value:
* None
@ -17,7 +19,7 @@
if (!isServer) exitWith {};
params ["_box", "_killer", "_instigator"];
params ["_box", ["_killer", objNull], ["_instigator", objNull]];
if (_box getVariable [QGVAR(isCookingOff), false]) exitWith {};
@ -29,10 +31,9 @@ private _jipID = [QGVAR(cookOffBoxLocal), [
_killer,
_instigator,
CBA_missionTime,
random [IGNITE_TIME / 2, IGNITE_TIME, IGNITE_TIME / 2 * 3], // generate random timers that are global
random [SMOKE_TIME / 2, SMOKE_TIME, SMOKE_TIME / 2 * 3]
random [SMOKE_DELAY / 2, SMOKE_DELAY, SMOKE_DELAY / 2 * 3] // generate random timer that is global synced
]] call CBA_fnc_globalEventJIP;
[_jipID, _box] call CBA_fnc_removeGlobalEventJIP;
_box setVariable [QGVAR(jipID), _jipID];
_box setVariable [QGVAR(jipIDs), [_jipID]];

View File

@ -1,78 +1,53 @@
#include "..\script_component.hpp"
/*
* Author: KoffeinFlummi, commy2, kymckay, johnb43
* Start a cook-off in the given ammo box.
* Spawns local cook-off effects for ammo boxes.
*
* Arguments:
* 0: Ammo box <OBJECT>
* 0: Box <OBJECT>
* 1: Killer <OBJECT>
* 2: Instigator <OBJECT>
* 3: Start time of the cook-off <NUMBER>
* 4: Smoke delay <NUMBER>
*
* Return Value:
* None
*
* Example:
* cursorObject call ace_cookoff_fnc_cookOffBox
* [cursorObject, player, player, CBA_missionTime, 10, 60] call ace_cookoff_fnc_cookOffBoxLocal
*
* Public: No
*/
params ["_box", "_killer", "_instigator", "_startTime", "_igniteTime", "_smokeTime"];
params ["", "", "", "_startTime", "_smokeDelay"];
// Make sure effects are cleaned up if box is deleted
[QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent;
[{
params ["_box", "_killer", "_instigator"];
// These time checks are for JIP players
private _delay = _startTime - CBA_missionTime + _igniteTime;
// Make sure effects are cleaned up if box is deleted
[QGVAR(addCleanupHandlers), _box] call CBA_fnc_localEvent;
if (_delay >= 0) then {
[{
params ["_box"];
private _boxPos = ASLToAGL getPosASL _box;
private _effects = [];
private _effects = [];
// Box will start smoking
if (hasInterface) then {
private _smoke = createVehicleLocal ["#particlesource", _boxPos, [], 0, "CAN_COLLIDE"];
_smoke setParticleClass "AmmoSmokeParticles2";
_smoke attachTo [_box];
// Box will start smoking
if (hasInterface) then {
private _smoke = "#particlesource" createVehicleLocal [0, 0, 0];
_smoke setParticleClass "AmmoSmokeParticles2";
_smoke attachTo [_box, [0, 0, 0]];
_effects pushBack _smoke;
};
_effects pushBack _smoke;
};
if (isServer) then {
private _sound = createSoundSource ["Sound_Fire", _boxPos, [], 0];
_sound attachTo [_box];
if (isServer) then {
private _sound = createSoundSource ["Sound_Fire", ASLToAGL getPosASL _box, [], 0];
_smoke attachTo [_sound];
_effects pushBack _sound;
};
_box setVariable [QGVAR(effects), _effects];
}, _box, _delay] call CBA_fnc_waitAndExecute;
};
// Smoke happens later
_delay = _delay + _smokeTime;
if (_delay >= 0) then {
// Light the fire (also handles lighting)
[{
params ["_box", "_killer", "_instigator"];
if (hasInterface) then {
private _fire = "#particlesource" createVehicleLocal [0, 0, 0];
_fire setParticleClass "AmmoBulletCore";
_fire attachTo [_box, [0, 0, 0]];
private _effects = _box getVariable [QGVAR(effects), []];
_effects pushBack _fire;
_box setVariable [QGVAR(effects), _effects];
};
_effects pushBack _sound;
// Detonate the ammunition
if (isServer) then {
[QGVAR(detonateAmmunition), [_box, true, _killer, _instigator]] call CBA_fnc_localEvent;
};
}, _this, _delay] call CBA_fnc_waitAndExecute;
};
[QGVAR(detonateAmmunition), [_box, true, _killer, _instigator, random [DETONATION_DELAY / 2, DETONATION_DELAY, DETONATION_DELAY / 2 * 3]]] call CBA_fnc_localEvent;
};
_box setVariable [QGVAR(effects), _effects];
}, _this, (_startTime - CBA_missionTime + _smokeDelay) max 0] call CBA_fnc_waitAndExecute; // this delay allows for synchronisation for JIP players

View File

@ -7,15 +7,16 @@
* 0: Vehicle <OBJECT>
* 1: Spawn fire jet <BOOL>
* 2: Spawn fire ring <BOOL>
* 3: Duration of effect (max 20 seconds) <NUMBER>
* 4: What selection will fire originate from <STRING>
* 5: Cookoff intensity value <NUMBER>
* 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:
* [vehicle player, true, false, 15, "commander_turret"] call ace_cookoff_fnc_cookOffEffect
* [vehicle player, true, false, "commander_turret", 6, CBA_missionTime, 15] call ace_cookoff_fnc_cookOffEffect
*
* Public: No
*/
@ -23,7 +24,7 @@
#define FLAME_SIZE 1.5
#define FIRE_INTENSITY 6
params ["_vehicle", "_jet", "_ring", "_duration", "_fireSelection", "_intensity"];
params ["_vehicle", "_jet", "_ring", "_fireSelection", "_intensity", "_startTime", "_duration"];
// Spawn light
private _light = objNull;
@ -51,20 +52,20 @@ if (isServer) then {
// Make the ring a source of fire
if (_ring && {["ace_fire"] call EFUNC(common,isModLoaded)}) then {
_fireKey = format [QGVAR(%1), hashValue _vehicle];
_fireKey = format [QGVAR(cookoffFire_%1), hashValue _vehicle];
[QEGVAR(fire,addFireSource), [_vehicle, FLAME_SIZE * ((boundingBoxReal _vehicle) select 2), FIRE_INTENSITY, _fireKey]] call CBA_fnc_localEvent;
};
};
[{
(_this select 0) params ["_vehicle", "_jet", "_ring", "_duration", "_startTime", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"];
(_this select 0) params ["_vehicle", "_jet", "_ring", "_startTime", "_duration", "_light", "_fireSelection", "_sound", "_intensity", "_fireKey"];
private _elapsedTime = CBA_missionTime - _startTime;
// Clean up effects once effects have finished or vehicle has been deleted
if (isNull _vehicle || {_elapsedTime >= _duration}) exitWith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
(_this select 1) call CBA_fnc_removePerFrameHandler;
deleteVehicle _light;
@ -222,4 +223,4 @@ if (isServer) then {
(_tiWheels + _intensity * 0.004) / 1.002, // wheels//tracks are further away from burning parts
(_tiWeapon + _intensity * 0.01) / 1.005
];
}, 0, [_vehicle, _jet, _ring, _duration, CBA_missionTime, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler;
}, 0, [_vehicle, _jet, _ring, _startTime, _duration, _light, _fireSelection, _sound, _intensity, _fireKey]] call CBA_fnc_addPerFrameHandler;

View File

@ -51,7 +51,7 @@ if (hasInterface) then {
};
// Spawn smoke
_smoke = "#particlesource" createVehicleLocal [0, 0, 0];
_smoke = createVehicleLocal ["#particlesource", ASLToAGL getPosASL _vehicle, [], 0, "CAN_COLLIDE"];;
_smoke setParticleClass "ObjectDestructionSmoke1_2Smallx";
_smoke attachTo [_vehicle, _position];
};
@ -60,14 +60,20 @@ if (hasInterface) then {
(_this select 0) params ["_vehicle", "_smoke", "_endTime"];
if (!alive _vehicle || {_vehicle getHitPointDamage "HitEngine" < 0.9} || {CBA_missionTime >= _endTime}) exitWith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
(_this select 1) call CBA_fnc_removePerFrameHandler;
deleteVehicle _smoke;
if (isNull _vehicle || !isServer) exitWith {};
(_vehicle getVariable [QGVAR(engineFireJipID), ""]) call CBA_fnc_removeGlobalEventJIP;
_vehicle setVariable [QGVAR(isEngineSmoking), nil];
_vehicle setVariable [QGVAR(isEngineSmoking), false];
private _jipID = _vehicle getVariable QGVAR(engineFireJipID);
if (isNil "_jipID") exitWith {};
_jipID call CBA_fnc_removeGlobalEventJIP;
_vehicle setVariable [QGVAR(engineFireJipID), nil];
};
}, 5, [_vehicle, _smoke, _endTime]] call CBA_fnc_addPerFrameHandler;

View File

@ -20,10 +20,9 @@
// Stages of cookoff in order (in seconds)
// Should be no un-synced randomness in these as the effects must be ran on each client
#define IGNITE_TIME 3
#define SMOKE_TIME 10.5
#define SMOKE_DELAY 10.5
#define DETONATION_DELAY 3
#define COOKOFF_TIME 14 // Cook off time should be 20s at most due to length of sound files
#define COOKOFF_TIME_BOX 82.5 // Cook off time for boxes should be significant to allow time for ammo to burn
#define ENGINE_FIRE_TIME 240
#define MIN_TIME_BETWEEN_FLAMES 5
#define MAX_TIME_BETWEEN_FLAMES 15
@ -33,9 +32,6 @@
#define MIN_AMMO_DETONATION_START_DELAY 1 // Min time to wait before a vehicle's ammo starts to cookoff
#define MAX_AMMO_DETONATION_START_DELAY 6 // Max time to wait before a vehicle's ammo starts to cookoff
// Delay between flame effect for players in a cooking off vehicle
#define FLAME_EFFECT_DELAY 0.4
// Common commander hatch defines for default vehicles
#define DEFAULT_COMMANDER_HATCHES ["osa_poklop_commander", "hatch_commander_axis"]

View File

@ -180,7 +180,7 @@ if (isServer) then {
{EGVAR(cookoff,ammoCookoffDuration) != 0} &&
{_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]}
) then {
[QEGVAR(cookOff,cookOffBox), [_box, objNull, objNull]] call CBA_fnc_serverEvent;
[QEGVAR(cookOff,cookOffBox), _box] call CBA_fnc_serverEvent;
} else {
_x setDamage 1;
};

View File

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