From 13e3ba30994e8d60bc6e9319b9d81cc43727192a Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Fri, 26 Jan 2024 18:38:26 +0100 Subject: [PATCH 01/27] Reworked fire module --- addons/cookoff/functions/fnc_cookOff.sqf | 2 +- addons/fire/XEH_PREP.hpp | 6 +- addons/fire/XEH_postInit.sqf | 42 ++- addons/fire/XEH_preInit.sqf | 2 - addons/fire/functions/fnc_burn.sqf | 336 ++---------------- addons/fire/functions/fnc_burnEffects.sqf | 191 ++++++++++ addons/fire/functions/fnc_burnIndicator.sqf | 31 +- addons/fire/functions/fnc_burnReaction.sqf | 7 +- addons/fire/functions/fnc_burnSimulation.sqf | 156 ++++++++ addons/fire/functions/fnc_fireManagerPFH.sqf | 44 +-- addons/fire/functions/fnc_isBurning.sqf | 9 +- addons/fire/functions/fnc_isPlant.sqf | 20 -- .../fire/functions/fnc_medical_canPatDown.sqf | 2 +- .../fire/functions/fnc_medical_progress.sqf | 8 +- addons/fire/functions/fnc_medical_success.sqf | 3 + addons/fire/initSettings.inc.sqf | 22 +- addons/fire/script_component.hpp | 7 +- addons/zeus/functions/fnc_moduleBurn.sqf | 3 +- 18 files changed, 474 insertions(+), 417 deletions(-) create mode 100644 addons/fire/functions/fnc_burnEffects.sqf create mode 100644 addons/fire/functions/fnc_burnSimulation.sqf delete mode 100644 addons/fire/functions/fnc_isPlant.sqf diff --git a/addons/cookoff/functions/fnc_cookOff.sqf b/addons/cookoff/functions/fnc_cookOff.sqf index 57cde71682d..8efa58bdf2a 100644 --- a/addons/cookoff/functions/fnc_cookOff.sqf +++ b/addons/cookoff/functions/fnc_cookOff.sqf @@ -107,7 +107,7 @@ if (_smokeDelayEnabled) then { _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; + [QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator], _x] call CBA_fnc_targetEvent; } forEach crew _vehicle }; diff --git a/addons/fire/XEH_PREP.hpp b/addons/fire/XEH_PREP.hpp index d9eacfdee00..efc48a1f23a 100644 --- a/addons/fire/XEH_PREP.hpp +++ b/addons/fire/XEH_PREP.hpp @@ -1,10 +1,10 @@ PREP(burn); -PREP(isBurning); -PREP(isPlant); +PREP(burnEffects); PREP(burnIndicator); PREP(burnReaction); +PREP(burnSimulation); PREP(fireManagerPFH); - +PREP(isBurning); PREP(medical_progress); PREP(medical_success); PREP(medical_canPatDown); diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 125cb59140d..6da3b4b6e52 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -1,38 +1,46 @@ #include "script_component.hpp" -[QGVAR(burn), FUNC(burn)] call CBA_fnc_addEventHandler; +[QGVAR(burn), LINKFUNC(burn)] call CBA_fnc_addEventHandler; +[QGVAR(burnEffects), LINKFUNC(burnEffects)] call CBA_fnc_addEventHandler; +[QGVAR(burnSimulation), LINKFUNC(burnSimulation)] call CBA_fnc_addEventHandler; + +// Only play sound if enabled in settings [QGVAR(playScream), { + if (!GVAR(enableScreams)) exitWith {}; + params ["_scream", "_source"]; - // only play sound if enabled in settings - if (GVAR(enableScreams)) then { - _source say3D _scream; - }; + + _source say3D _scream; }] call CBA_fnc_addEventHandler; -["ace_settingsInitialized", { - TRACE_1("settingsInit", GVAR(enabled)); - if (!GVAR(enabled)) exitWith {}; +if (isServer) then { + ["CBA_settingsInitialized", { + TRACE_1("settingsInit", GVAR(enabled)); + + if (!GVAR(enabled)) exitWith {}; + + GVAR(fireSources) = createHashMap; - if (isServer) then { [QGVAR(addFireSource), { - params ["_source", "_radius", "_intensity", "_key", ["_condition", { true }], ["_conditionArgs", []]]; + params ["_source", "_radius", "_intensity", "_key", ["_condition", {true}], ["_conditionArgs", []]]; + private _fireLogic = createVehicle ["ACE_LogicDummy", [0, 0, 0], [], 0, "NONE"]; + if (_source isEqualType objNull) then { _fireLogic attachTo [_source]; } else { _fireLogic setPosASL _source; }; - [GVAR(fireSources), _key, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]] call CBA_fnc_hashSet; + GVAR(fireSources) set [_key, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; }] call CBA_fnc_addEventHandler; [QGVAR(removeFireSource), { params ["_key"]; - [GVAR(fireSources), _key] call CBA_fnc_hashRem; - }] call CBA_fnc_addEventHandler; - [{ _this call FUNC(fireManagerPFH) }, FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; - GVAR(fireSources) = [[], nil] call CBA_fnc_hashCreate; - }; -}] call CBA_fnc_addEventHandler; + GVAR(fireSources) deleteAt _key; + }] call CBA_fnc_addEventHandler; + [LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; + }] call CBA_fnc_addEventHandler; +}; diff --git a/addons/fire/XEH_preInit.sqf b/addons/fire/XEH_preInit.sqf index 2fc794454d3..894773534a4 100644 --- a/addons/fire/XEH_preInit.sqf +++ b/addons/fire/XEH_preInit.sqf @@ -8,6 +8,4 @@ PREP_RECOMPILE_END; #include "initSettings.inc.sqf" -GVAR(burningPlants) = []; - ADDON = true; diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index 08d52bd05c0..ea5c0a7f4dc 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -1,8 +1,7 @@ #include "..\script_component.hpp" /* - * Author: tcvm - * Makes object catch fire. Only call from events. Local effects only. - * Arbitrary values to ignite people. Assumed maximum is "10". + * Author: tcvm, johnb43 + * Makes object catch fire. Only call from targeted events, is applied globally. * * Arguments: * 0: Vehicle @@ -18,322 +17,39 @@ * Public: No */ -#define INTENSITY_LOSS 0.03 -#define INTENSITY_UPDATE 3 -#define BURN_PROPOGATE_UPDATE 1 -#define BURN_PROPOGATE_DISTANCE 2 -#define BURN_PROPOGATE_COUNTER_MAX 5 - -params ["_unit", "_intensity", ["_instigator", objNull]]; +if !(EGVAR(common,settingsInitFinished)) exitWith { + EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(burn), _this]; +}; if (!GVAR(enabled)) exitWith {}; -private _isBurning = [_unit] call FUNC(isBurning); -if (_isBurning) exitWith {}; - -[{ - // looped function - (_this getVariable "params") params ["_unit", "", "_instigator"]; - private _unitPos = getPosASL _unit; - - _intensity = _unit getVariable [QGVAR(intensity), 0]; - - if (surfaceIsWater _unitPos && {(_unitPos#2) < 1}) then { - _intensity = 0; - }; - - _fireParticle setDropInterval (0.01 max linearConversion [BURN_MAX_INTENSITY, BURN_MIN_INTENSITY, _intensity, 0.03, 0.1, false]); - _fireParticle setParticleParams [ - ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 10, 32], // sprite sheet values - "", // animation name - "Billboard", // particle type - 1, // timer period - 0.7, // lifetime - "destructionEffect2", // position - [0, 0, 1], // move velocity - 0, // rotation velocity - 10, // weight - 7.9, // volume - 1, // rubbing - [0.3, 0.3], // size - [ - [1, 1, 1, -0], - [1, 1, 1, -1], - [1, 1, 1, -1], - [1, 1, 1, -1], - [1, 1, 1, -0] - ], // colour - [0.5, 1], // animation speed - 1, // random dir period - 0, // random dir intensity - "", // on timer script - "", // before destroy script - _unit, // particle source - 0, - false, - 0, - [[0.8, 0.6, 0.2, 1]] // emissive color - ]; - _fireParticle setParticleRandom [ - 0.04 * _intensity, // life time - [0.05, 0.05, 2], // position - [0.05 * _intensity, 0.05 * _intensity, 0.05 * _intensity], // move velocity - 0, // rotation velocity - 0.06 * _intensity, // size - [0, 0, 0, 0], // color - 0, // random direction period - 0 // random direction intensity - ]; - - _smokeParticle setParticleCircle [0, [0, 0, 0]]; - _smokeParticle setParticleRandom [ - 0, // life time - [0.25, 0.25, 0], // position - [0.2, 0.2, 0], // move velocity - 0, // rotation velocity - 0.25, // size - [0, 0, 0, 0.1], // color - 0, // random direction period - 0 // random direction intensity - ]; - _smokeParticle setParticleParams [ - ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 7, 48], // sprite sheet values - "", // animation name - "Billboard", // particle type - 1, // timer period - 8, // lifetime - [0, 0, 1.1], // position - [0, 0, 1], // move velocity - 0, // rotation velocity - 10, // weight - 7.9, // volume - 0.066, // rubbing - [1, 3, 6], // size - [ - [0.5, 0.5, 0.5, 0.15], - [0.75, 0.75, 0.75, 0.075], - [1, 1, 1, 0] - ], // colour - [0.125], // animation speed - 1, // random dir period - 0, // random dir intensity - "", // on timer script - "", // before destroy script - _unit // particle source - ]; - _smokeParticle setDropInterval 0.15; - - _fireLight setLightBrightness ((_intensity * 3) / 10); - _lightFlare setLightBrightness (_intensity / 30); - - private _distanceToUnit = (_unit distance ace_player); - _fireLight setLightAttenuation [1, 10 max (5 min (10 - _intensity)), 0, 15]; - _lightFlare setLightFlareSize (_intensity * (3 / 4)) * FLARE_SIZE_MODIFIER; - - if (!GVAR(enableFlare)) then { - _lightFlare setLightFlareSize 0; - }; - - // always keep flare visible to perceiving unit as long as it isnt the player - if (_unit isNotEqualTo ace_player) then { - private _relativeAttachPoint = [0, 0, 0.3]; - if (_distanceToUnit > 1.5) then { - _relativeAttachPoint = (vectorNormalized (_unit worldToModelVisual (getPos ace_player))) vectorMultiply linearConversion [5, 30, _distanceToUnit, 0.5, 1.5]; - _relativeAttachPoint set [2, 0.3 + ((_unit selectionPosition "pelvis") select 2)]; - }; - _lightFlare attachTo [_unit, _relativeAttachPoint]; - }; - - if (!isGamePaused) then { - // If the unit goes to spectator alive _unit == true and they will be on fire and still take damage - // Only workaround I could think of, kinda clunky - if (_isThisUnitAlive) then { - _isThisUnitAlive = (alive _unit) && { getNumber ((configOf _unit) >> "isPlayableLogic") != 1 }; - }; - - // propagate fire - if ((CBA_missionTime - _lastPropogateUpdate) >= BURN_PROPOGATE_UPDATE) then { - _lastPropogateUpdate = CBA_missionTime; - if !([ace_player] call FUNC(isBurning)) then { - if ((vehicle _unit) isEqualTo (vehicle ace_player)) then { - if (0.5 > random 1) then { - [QGVAR(burn), [ace_player, _intensity * (7 / 8), _instigator]] call CBA_fnc_globalEvent; - }; - } else { - if ((ace_player isKindOf "Man") && {_unit isNotEqualTo ace_player} && {isDamageAllowed ace_player && {ace_player getVariable [QEGVAR(medical,allowDamage), true]}}) then { - private _burnCounter = _unit getVariable [QGVAR(burnCounter), 0]; - if (_distanceToUnit < BURN_PROPOGATE_DISTANCE) then { - if (_burnCounter < BURN_PROPOGATE_COUNTER_MAX) then { - _burnCounter = _burnCounter + 1; - } else { - [QGVAR(burn), [ace_player, _intensity * (3 / 4), _instigator]] call CBA_fnc_globalEvent; - }; - } else { - _burnCounter = 0; - }; - _unit setVariable [QGVAR(burnCounter), _burnCounter]; - }; - }; - }; - }; - - // update intensity/fire reactions - if ((CBA_missionTime - _lastIntensityUpdate) >= INTENSITY_UPDATE) then { - _lastIntensityUpdate = CBA_missionTime; - _intensity = _intensity - INTENSITY_LOSS - (rain / 10); - if (local _unit) then { - if (_isThisUnitAlive) then { - if !(IS_UNCONSCIOUS(_unit)) then { - if !(isPlayer _unit) then { - private _sdr = _unit getVariable [QGVAR(stopDropRoll), false]; - if ((_unit isEqualTo vehicle _unit) && (_sdr || ({ 0.05 > random 1 }))) then { - _unit setVariable [QGVAR(stopDropRoll), true]; - if !(_sdr) then { - TRACE_1("stop, drop, roll!", _unit); - _unit setUnitPos "DOWN"; - doStop _unit; - }; - // queue up a bunch of animations - for "_i" from 0 to 2 do { - [_unit, selectRandom ["amovppnemstpsnonwnondnon_amovppnemevasnonwnondl", "amovppnemstpsnonwnondnon_amovppnemevasnonwnondr"], 0] call EFUNC(common,doAnimation); - }; - _intensity = _intensity - (1 / _intensity); - } else { - private _group = (group _unit); - private _vehicle = vehicle _unit; - - if (_vehicle != _unit) then { - TRACE_1("Ejecting", _unit); - _unit leaveVehicle _vehicle; - unassignVehicle _unit; - _unit action ["eject",_vehicle]; - }; - _unit disableAI "TARGET"; - _unit disableAI "AUTOTARGET"; - - // Run away - if (leader _group != _unit) then { - [_unit] join grpNull; - }; - _unit doMove ((getPosATL _unit) getPos [20 + random 35, floor (random 360)]); - _unit setSpeedMode "FULL"; - _unit setSuppression 1; - }; - } else { - if ((animationState _unit) in PRONE_ROLLING_ANIMS) then { - // decrease intensity of burn - _intensity = _intensity * INTENSITY_DECREASE_MULT_ROLLING; - }; - }; - - [_unit] call FUNC(burnReaction); - }; - - // Common burn areas are the hands and face https://www.ncbi.nlm.nih.gov/pubmed/16899341/ - private _woundSelection = ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] selectRandomWeighted [0.77, 0.5, 0.8, 0.8, 0.3, 0.3]; - if (GET_PAIN_PERCEIVED(_unit) < (PAIN_UNCONSCIOUS + random 0.2)) then { - // keep pain around unconciousness limit to allow for more fun interactions - [_unit, _intensity / BURN_MAX_INTENSITY, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); - } else { - [_unit, 0.15, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); - }; - }; - _unit setVariable [QGVAR(intensity), _intensity, true]; // globally sync intensity across all clients to make sure simulation is deterministic - }; - }; - - private _burnIndicatorPFH = _unit getVariable [QGVAR(burnUIPFH), -1]; - if (_unit isEqualTo ace_player && { _isThisUnitAlive } && { _burnIndicatorPFH < 0 }) then { - _burnIndicatorPFH = [FUNC(burnIndicator), 1, _unit] call CBA_fnc_addPerFrameHandler; - _unit setVariable [QGVAR(burnUIPFH), _burnIndicatorPFH]; - }; - }; -}, 0, [_unit, _intensity, _instigator], { - TRACE_1("burn init",GVAR(enableFlare)); - // init function - private _params = _this getVariable "params"; - _params params ["_unit", "_startingIntensity"]; - - _intensity = _startingIntensity; - private _unitPos = getPos _unit; - - _fireParticle = "#particlesource" createVehicleLocal _unitPos; - _fireParticle attachTo [_unit, [0, 0, 0]]; - _fireParticle setDropInterval 0.03; - - _smokeParticle = "#particlesource" createVehicleLocal _unitPos; - - _fireLight = "#lightpoint" createVehicleLocal _unitPos; - _fireLight setLightIntensity 0; - _fireLight setLightAmbient [0.8, 0.6, 0.2]; - _fireLight setLightColor [1, 0.5, 0.4]; - _fireLight attachTo [_unit, [0, 0, 0]]; - _fireLight setLightDayLight false; - - _lightFlare = "#lightpoint" createVehicleLocal _unitPos; - _lightFlare setLightIntensity 0; - _lightFlare setLightColor [1, 0.8, 0.8]; - _lightFlare setLightUseFlare true; - _lightFlare setLightFlareMaxDistance 100; - _lightFlare setLightFlareSize 0; - - if (_unit isNotEqualTo ace_player) then { - private _relativeAttachPoint = (vectorNormalized (_unit worldToModelVisual (getPos ace_player))) vectorMultiply 1; - _relativeAttachPoint set [2, 0.5]; - _lightFlare attachTo [_unit, _relativeAttachPoint]; - } else { - _lightFlare attachTo [_unit, [0, 0, 0.3]]; - }; - - if (isServer) then { - _fireSound = createSoundSource ["Sound_Fire", _unitPos, [], 0]; - _fireSound attachTo [_unit, [0, 0, 0], "Head"]; - }; +params ["_unit", "_intensity", ["_instigator", objNull]]; - _unit setVariable [QGVAR(burning), true]; - _unit setVariable [QGVAR(intensity), _intensity]; - _unit setVariable [QGVAR(burnUIPFH), -1]; +// Check if unit is remote (objNull is remote) +if (!local _unit) exitWith {}; - if (local _unit) then { - if (_unit isEqualTo ace_player) then { - private _burnIndicatorPFH = [FUNC(burnIndicator), 1, _unit] call CBA_fnc_addPerFrameHandler; - _unit setVariable [QGVAR(burnUIPFH), _burnIndicatorPFH]; - }; +// Check if the unit can burn (takes care of spectators and curators) +if (getNumber (configOf _unit >> "isPlayableLogic") == 1) exitWith {}; - [_unit, false] call FUNC(burnReaction); - }; +// If unit is invulnerable, don't burn unit +if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith {}; - _lastIntensityUpdate = 0; - _lastPropogateUpdate = 0; +// If unit is already burning, don't burn more +if (_unit call FUNC(isBurning)) exitWith {}; - _isThisUnitAlive = true; -}, { - (_this getVariable "params") params ["_unit"]; +_unit setVariable [QGVAR(intensity), _intensity, true]; - // deinit function - deleteVehicle _fireParticle; - deleteVehicle _smokeParticle; - deleteVehicle _fireLight; - deleteVehicle _lightFlare; - deleteVehicle _fireSound; +// Fire simulation +private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator], format [QGVAR(burnSimulation_%1), hashValue _unit]] call CBA_fnc_globalEventJIP; +[_burnSimulationJipID, _unit] call CBA_fnc_removeGlobalEventJIP; - if (local _unit) then { - if (!isPlayer _unit) then { - _unit setUnitPos "AUTO"; - _unit setVariable [QGVAR(stopDropRoll), false]; - }; - }; - _unit setVariable [QGVAR(burning), false]; - _unit setVariable [QGVAR(burnCounter), 0]; -}, { - // run condition - true -}, { - // exit condition - (_this getVariable "params") params ["_unit"]; +// Spawn effects for unit +private _burnEffectsJipID = [QGVAR(burnEffects), _unit, format [QGVAR(burnEffects_%1), hashValue _unit]] call CBA_fnc_globalEventJIP; +[_burnEffectsJipID, _unit] call CBA_fnc_removeGlobalEventJIP; - private _unitAlive = (alive _unit) && { getNumber ((configOf _unit) >> "isPlayableLogic") != 1 }; - private _unitIsUnit = { (_unit != vehicle _unit) && { isNull vehicle _unit } }; +_unit setVariable [QGVAR(jipIDs), [_burnSimulationJipID, _burnEffectsJipID], true]; - !_unitAlive || _unitIsUnit || { _intensity <= BURN_MIN_INTENSITY } || { !([_unit] call FUNC(isBurning)) } -}, ["_intensity", "_fireParticle", "_smokeParticle", "_fireLight", "_fireSound", "_lightFlare", "_lastIntensityUpdate", "_lastPropogateUpdate", "_isThisUnitAlive"]] call CBA_fnc_createPerFrameHandlerObject; +// Play screams and optional weapon dropping +if (_unit call EFUNC(common,isAwake)) then { + [_unit, false] call FUNC(burnReaction); +}; diff --git a/addons/fire/functions/fnc_burnEffects.sqf b/addons/fire/functions/fnc_burnEffects.sqf new file mode 100644 index 00000000000..eabf29c0531 --- /dev/null +++ b/addons/fire/functions/fnc_burnEffects.sqf @@ -0,0 +1,191 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm, johnb43 + * Spawns particle effects for a burning unit. + * + * Arguments: + * 0: Unit + * + * Return Value: + * None + * + * Example: + * player call ace_fire_fnc_burnEffects + * + * Public: No + */ + +params ["_unit"]; + +// Spawn particles +private _unitPos = getPos _unit; +private _fireParticle = objNull; +private _smokeParticle = objNull; +private _fireLight = objNull; +private _lightFlare = objNull; + +if (hasInterface) then { + _fireParticle = "#particlesource" createVehicleLocal _unitPos; + _fireParticle attachTo [_unit, [0, 0, 0]]; + _fireParticle setDropInterval 0.03; + + _smokeParticle = "#particlesource" createVehicleLocal _unitPos; + + _fireLight = "#lightpoint" createVehicleLocal _unitPos; + _fireLight setLightIntensity 0; + _fireLight setLightAmbient [0.8, 0.6, 0.2]; + _fireLight setLightColor [1, 0.5, 0.4]; + _fireLight attachTo [_unit, [0, 0, 0]]; + _fireLight setLightDayLight false; + + _lightFlare = "#lightpoint" createVehicleLocal _unitPos; + _lightFlare setLightIntensity 0; + _lightFlare setLightColor [1, 0.8, 0.8]; + _lightFlare setLightUseFlare true; + _lightFlare setLightFlareMaxDistance 100; + _lightFlare setLightFlareSize 0; + + if (_unit != ACE_player) then { + private _relativeAttachPoint = vectorNormalized (_unit worldToModelVisual (getPos ACE_player)); + _relativeAttachPoint set [2, 0.5]; + _lightFlare attachTo [_unit, _relativeAttachPoint]; + } else { + _lightFlare attachTo [_unit, [0, 0, 0.3]]; + }; +}; + +private _fireSound = objNull; + +if (isServer) then { + _fireSound = createSoundSource ["Sound_Fire", _unitPos, [], 0]; + _fireSound attachTo [_unit, [0, 0, 0], "Head"]; +}; + +[{ + params ["_args", "_pfhID"]; + _args params ["_unit", "_fireParticle", "_smokeParticle", "_fireLight", "_lightFlare", "_fireSound"]; + + if (isNull _unit || {!(_unit call FUNC(isBurning))}) exitWith { + _pfhID call CBA_fnc_removePerFrameHandler; + + deleteVehicle _fireParticle; + deleteVehicle _smokeParticle; + deleteVehicle _fireLight; + deleteVehicle _lightFlare; + deleteVehicle _fireSound; + }; + + // Display burn indicators + if (_unit == ACE_player && {alive _unit} && {isNil {_unit getVariable QGVAR(burnUIPFH)}}) then { // this accounts for player remote controlled a new unit + private _burnIndicatorPFH = [LINKFUNC(burnIndicator), 1, _unit] call CBA_fnc_addPerFrameHandler; + _unit setVariable [QGVAR(burnUIPFH), _burnIndicatorPFH]; + }; + + if (!hasInterface) exitWith {}; + + private _intensity = _unit getVariable [QGVAR(intensity), 0]; + + _fireParticle setDropInterval (0.01 max linearConversion [BURN_MAX_INTENSITY, BURN_MIN_INTENSITY, _intensity, 0.03, 0.1, false]); + _fireParticle setParticleParams [ + ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 10, 32], // sprite sheet values + "", // animation name + "Billboard", // particle type + 1, // timer period + 0.7, // lifetime + "destructionEffect2", // position + [0, 0, 1], // move velocity + 0, // rotation velocity + 10, // weight + 7.9, // volume + 1, // rubbing + [0.3, 0.3], // size + [ + [1, 1, 1, -0], + [1, 1, 1, -1], + [1, 1, 1, -1], + [1, 1, 1, -1], + [1, 1, 1, -0] + ], // colour + [0.5, 1], // animation speed + 1, // random dir period + 0, // random dir intensity + "", // on timer script + "", // before destroy script + _unit, // particle source + 0, + false, + 0, + [[0.8, 0.6, 0.2, 1]] // emissive color + ]; + _fireParticle setParticleRandom [ + 0.04 * _intensity, // life time + [0.05, 0.05, 2], // position + [0.05 * _intensity, 0.05 * _intensity, 0.05 * _intensity], // move velocity + 0, // rotation velocity + 0.06 * _intensity, // size + [0, 0, 0, 0], // color + 0, // random direction period + 0 // random direction intensity + ]; + + _smokeParticle setParticleCircle [0, [0, 0, 0]]; + _smokeParticle setParticleRandom [ + 0, // life time + [0.25, 0.25, 0], // position + [0.2, 0.2, 0], // move velocity + 0, // rotation velocity + 0.25, // size + [0, 0, 0, 0.1], // color + 0, // random direction period + 0 // random direction intensity + ]; + _smokeParticle setParticleParams [ + ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 7, 48], // sprite sheet values + "", // animation name + "Billboard", // particle type + 1, // timer period + 8, // lifetime + [0, 0, 1.1], // position + [0, 0, 1], // move velocity + 0, // rotation velocity + 10, // weight + 7.9, // volume + 0.066, // rubbing + [1, 3, 6], // size + [ + [0.5, 0.5, 0.5, 0.15], + [0.75, 0.75, 0.75, 0.075], + [1, 1, 1, 0] + ], // colour + [0.125], // animation speed + 1, // random dir period + 0, // random dir intensity + "", // on timer script + "", // before destroy script + _unit // particle source + ]; + _smokeParticle setDropInterval 0.15; + + _fireLight setLightBrightness ((_intensity * 3) / 10); + _lightFlare setLightBrightness (_intensity / 30); + + private _distanceToUnit = _unit distance ACE_player; + _fireLight setLightAttenuation [1, 10 max (5 min (10 - _intensity)), 0, 15]; + _lightFlare setLightFlareSize (_intensity * (3 / 4)) * FLARE_SIZE_MODIFIER; + + if (!GVAR(enableFlare)) then { + _lightFlare setLightFlareSize 0; + }; + + // Always keep flare visible to perceiving unit as long as it isn't the player + if (_unit != ACE_player) then { + private _relativeAttachPoint = [0, 0, 0.3]; + + if (_distanceToUnit > 1.5) then { + _relativeAttachPoint = (vectorNormalized (_unit worldToModelVisual (getPos ACE_player))) vectorMultiply linearConversion [5, 30, _distanceToUnit, 0.5, 1.5]; + _relativeAttachPoint set [2, 0.3 + ((_unit selectionPosition "pelvis") select 2)]; + }; + + _lightFlare attachTo [_unit, _relativeAttachPoint]; + }; +}, 0, [_unit, _fireParticle, _smokeParticle, _fireLight, _lightFlare, _fireSound]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/fire/functions/fnc_burnIndicator.sqf b/addons/fire/functions/fnc_burnIndicator.sqf index 13db8862c9f..2874b69d115 100644 --- a/addons/fire/functions/fnc_burnIndicator.sqf +++ b/addons/fire/functions/fnc_burnIndicator.sqf @@ -11,26 +11,29 @@ * None * * Example: - * [player, 4] call ace_fire_fnc_burnIndicator + * [player, _pfhID] call ace_fire_fnc_burnIndicator * * Public: No */ params ["_unit", "_pfhHandle"]; -if !(IS_UNCONSCIOUS(_unit)) then { - private _iteration = _unit getVariable [QGVAR(indicatorIteration), 0]; - if (_iteration == 0) then { - QGVAR(indicatorLayer) cutRsc [QGVAR(onFire1), "PLAIN"]; - _iteration = 1; - } else { - QGVAR(indicatorLayer) cutRsc [QGVAR(onFire2), "PLAIN"]; - _iteration = 0; - }; - _unit setVariable [QGVAR(indicatorIteration), _iteration]; +if (!alive _unit || {!(_unit call FUNC(isBurning))}) exitWith { + _pfhHandle call CBA_fnc_removePerFrameHandler; + + _unit setVariable [QGVAR(burnUIPFH), nil]; }; -if (!([_unit] call FUNC(isBurning)) || { !alive _unit }) then { - [_pfhHandle] call CBA_fnc_removePerFrameHandler; - _unit setVariable [QGVAR(burnUIPFH), -1]; +if !(_unit call EFUNC(common,isAwake)) exitWith {}; + +private _iteration = _unit getVariable [QGVAR(indicatorIteration), 0]; + +if (_iteration == 0) then { + QGVAR(indicatorLayer) cutRsc [QGVAR(onFire1), "PLAIN"]; + _iteration = 1; +} else { + QGVAR(indicatorLayer) cutRsc [QGVAR(onFire2), "PLAIN"]; + _iteration = 0; }; + +_unit setVariable [QGVAR(indicatorIteration), _iteration]; diff --git a/addons/fire/functions/fnc_burnReaction.sqf b/addons/fire/functions/fnc_burnReaction.sqf index 748fbbd60ee..42bd64b43ce 100644 --- a/addons/fire/functions/fnc_burnReaction.sqf +++ b/addons/fire/functions/fnc_burnReaction.sqf @@ -5,7 +5,7 @@ * * Arguments: * 0: Unit - * 1: Should unit throw its current weapon + * 1: Should unit throw its current weapon (default: true) * * Return Value: * None @@ -18,14 +18,15 @@ params ["_unit", ["_throwWeapon", true]]; if ( _throwWeapon && {GVAR(dropWeapon) > 0} - && {_unit in _unit && {(currentWeapon _unit) isNotEqualTo ""}} + && {isNull objectParent _unit && {(currentWeapon _unit) != ""}} && {!isPlayer _unit || GVAR(dropWeapon) >= 2} ) then { - [_unit] call EFUNC(common,throwWeapon); + _unit call EFUNC(common,throwWeapon); }; if (_unit isKindOf "CAManBase") then { private _soundID = floor (1 + random 15); private _sound = format [QGVAR(scream_%1), _soundID]; + [QGVAR(playScream), [_sound, _unit]] call CBA_fnc_globalEvent; }; diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf new file mode 100644 index 00000000000..ed5a338ea58 --- /dev/null +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -0,0 +1,156 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm, johnb43 + * Makes object catch fire. Simulates fire intensity over time. + * Arbitrary values to ignite people. Assumed maximum is "10". + * + * Arguments: + * 0: Unit + * 1: Instigator + * + * Return Value: + * None + * + * Example: + * player call ace_fire_fnc_burnSimulation + * + * Public: No + */ + +params ["_unit", "_instigator"]; + +// Reset variables +_unit setVariable [QGVAR(stopDropRoll), nil]; +_unit setVariable [QGVAR(burnCounter), nil]; + +[{ + params ["_args", "_pfhID"]; + _args params ["_unit", "_instigator"]; + + private _remote = !local _unit; + + // If unit is local and the fire has died now, the effects need to be cleaned up -> do not stop PFH here + if (isNull _unit || {_remote && {!(_unit call FUNC(isBurning))}}) exitWith { + _pfhID call CBA_fnc_removePerFrameHandler; + }; + + if (_remote) exitWith {}; + + private _unitPos = getPosASL _unit; + + // If unit is invulnerable or in water or if the fire has died out, stop burning unit + if ( + !(_unit call FUNC(isBurning)) || + {surfaceIsWater _unitPos && {(_unitPos select 2) < 1}} || + {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} + ) exitWith { + // Remove global effects and simulation + { + _x call CBA_fnc_removeGlobalEventJIP; + } forEach (_unit getVariable [QGVAR(jipIDs), []]); + + // Update globally that the unit isn't burning anymore + _unit setVariable [QGVAR(intensity), nil, true]; + + _pfhID call CBA_fnc_removePerFrameHandler; + + _unit setVariable [QGVAR(stopDropRoll), nil]; + _unit setVariable [QGVAR(burnCounter), nil]; + + if (!isPlayer _unit) then { + _unit setUnitPos "AUTO"; + }; + }; + + if (isGamePaused) exitWith {}; + + private _intensity = _unit getVariable [QGVAR(intensity), 0]; + + // Propagate fire to other units if it's intense + if (_intensity >= BURN_THRESHOLD_INTENSE) then { + _unitPos = ASLToAGL _unitPos; + + { + if !(_x call FUNC(isBurning)) then { + _distancePercent = 1 - ((_unitPos distance _x) / BURN_PROPAGATE_DISTANCE); + + [QGVAR(burn), [_x, _intensity * _distancePercent, _instigator], _x] call CBA_fnc_targetEvent; + }; + } forEach (_unitPos nearEntities ["CAManBase", BURN_PROPAGATE_DISTANCE]); + }; + + // Update intensity/fire reactions + if (CBA_missionTime >= _unit getVariable [QGVAR(intensityUpdate), 0]) then { + _unit setVariable [QGVAR(intensityUpdate), CBA_missionTime + INTENSITY_UPDATE]; + + _intensity = _intensity - INTENSITY_LOSS - (rain / 10); + + if (_unit call EFUNC(common,isAwake)) then { + if (!isPlayer _unit) then { + private _sdr = _unit getVariable [QGVAR(stopDropRoll), false]; + + private _vehicle = objectParent _unit; + + if (isNull _vehicle && {_sdr || {0.05 > random 1}}) then { + _unit setVariable [QGVAR(stopDropRoll), true]; + + if (!_sdr) then { + TRACE_1("stop, drop, roll!", _unit); + + _unit setUnitPos "DOWN"; + doStop _unit; + }; + + // Queue up a bunch of animations + for "_i" from 0 to 2 do { + [_unit, selectRandom ["amovppnemstpsnonwnondnon_amovppnemevasnonwnondl", "amovppnemstpsnonwnondnon_amovppnemevasnonwnondr"], 0] call EFUNC(common,doAnimation); + }; + + _intensity = _intensity - (1 / _intensity); + } else { + // Make the unit leave the vehicle + if (_vehicle != _unit) then { + TRACE_1("Ejecting", _unit); + + _unit leaveVehicle _vehicle; + unassignVehicle _unit; + + _unit action ["Eject", _vehicle]; + }; + + _unit disableAI "TARGET"; + _unit disableAI "AUTOTARGET"; + + // Run away, erraticly + if (leader group _unit != _unit) then { + [_unit] join grpNull; + }; + + _unit doMove ((getPosATL _unit) getPos [20 + random 35, floor (random 360)]); + _unit setSpeedMode "FULL"; + _unit setSuppression 1; + }; + } else { + // Decrease intensity of burn if rolling around + if ((animationState _unit) in PRONE_ROLLING_ANIMS) then { + _intensity = _intensity * INTENSITY_DECREASE_MULT_ROLLING; + }; + }; + + // Play screams and throw weapon (if enabled) + _unit call FUNC(burnReaction); + }; + + // Common burn areas are the hands and face https://www.ncbi.nlm.nih.gov/pubmed/16899341/ + private _woundSelection = ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] selectRandomWeighted [0.77, 0.5, 0.8, 0.8, 0.3, 0.3]; + + if (GET_PAIN_PERCEIVED(_unit) < (PAIN_UNCONSCIOUS + random 0.2)) then { + // Keep pain around unconciousness limit to allow for more fun interactions + [_unit, _intensity / BURN_MAX_INTENSITY, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); + } else { + [_unit, 0.15, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); + }; + + _unit setVariable [QGVAR(intensity), _intensity, true]; // globally sync intensity across all clients to make sure simulation is deterministic + }; +}, BURN_PROPAGATE_UPDATE, [_unit, _instigator]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf index fa8e7fb7893..0fce278fe6c 100644 --- a/addons/fire/functions/fnc_fireManagerPFH.sqf +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -5,39 +5,41 @@ * Used to handle external burning objects, not used internally because internal methods are more performant. * * Arguments: - * 0: Unit on fire - * 1: PFH Handle + * 0: Args (not used) + * 1: PFH Handle (not used) * * Return Value: * None * * Example: - * [ace_fire_fnc_fireManagerPFH, 0.25, [_unit]] call CBA_fnc_addPerFrameHandler + * [ace_fire_fnc_fireManagerPFH, 0.25] call CBA_fnc_addPerFrameHandler * * Public: No */ -params ["_args", "_handle"]; +private _attachedObject = objNull; +private _sourcePos = []; +private _distancePercent = 0; -[GVAR(fireSources), { - _value params ["", "", "", "_condition", "_conditionArgs"]; - _conditionArgs call _condition; -}] call CBA_fnc_hashFilter; +{ + _y params ["_source", "_radius", "_intensity", "_condition", "_conditionArgs"]; -[GVAR(fireSources), { - _value params ["_source", "_radius", "_intensity"]; - private _attachedObject = attachedTo _source; - private _sourcePos = getPosATL _source; - if (_attachedObject isNotEqualTo objNull) then { - _sourcePos = getPosATL _attachedObject; + // Remove when condition is no longer valid + if !(_conditionArgs call _condition) then { + GVAR(fireSources) deleteAt _x; + + continue; }; - private _nearEntities = _sourcePos nearEntities ["Man", _radius]; + _attachedObject = attachedTo _source; + _sourcePos = ASLtoAGL getPosASL ([_source, _attachedObject] select (!isNull _attachedObject)); + + // Burn units close to the fire { - private _burning = [_x] call FUNC(isBurning); - if !(_burning) then { - private _distancePercent = 1 - ((_sourcePos distance _x) / _radius); - [QGVAR(burn), [_x, _intensity * _distancePercent]] call CBA_fnc_globalEvent; + if !(_x call FUNC(isBurning)) then { + _distancePercent = 1 - ((_sourcePos distance _x) / _radius); + + [QGVAR(burn), [_x, _intensity * _distancePercent], _x] call CBA_fnc_targetEvent; }; - } forEach _nearEntities; -}] call CBA_fnc_hashEachPair; + } forEach (_sourcePos nearEntities ["CAManBase", _radius]); +} forEach GVAR(fireSources); diff --git a/addons/fire/functions/fnc_isBurning.sqf b/addons/fire/functions/fnc_isBurning.sqf index 3bdbe560be0..ba0dd9e13fe 100644 --- a/addons/fire/functions/fnc_isBurning.sqf +++ b/addons/fire/functions/fnc_isBurning.sqf @@ -1,10 +1,10 @@ #include "..\script_component.hpp" /* * Author: commy2 - * Check if object is burning. + * Check if unit is burning. * * Arguments: - * 0: Vehicle + * 0: Unit * * Return Value: * None @@ -17,7 +17,4 @@ params [["_unit", objNull, [objNull]]]; -_unit getVariable [QGVAR(burning), false] || { - GVAR(burningPlants) = GVAR(burningPlants) select {!isNull _x}; - _unit in GVAR(burningPlants) -} +(_unit getVariable [QGVAR(intensity), 0]) > BURN_MIN_INTENSITY diff --git a/addons/fire/functions/fnc_isPlant.sqf b/addons/fire/functions/fnc_isPlant.sqf deleted file mode 100644 index f132fc72be5..00000000000 --- a/addons/fire/functions/fnc_isPlant.sqf +++ /dev/null @@ -1,20 +0,0 @@ -#include "..\script_component.hpp" -/* - * Author: commy2 - * Check if object is a map placed bush or tree. - * - * Arguments: - * 0: Object - * - * Return Value: - * Is bush or tree? - * - * Example: - * cursorObject call ace_fire_fnc_isPlant - * - * Public: No - */ - -params [["_object", objNull, [objNull]]]; - -_object in nearestTerrainObjects [_object, ["TREE", "SMALL TREE", "BUSH"], 0.1] diff --git a/addons/fire/functions/fnc_medical_canPatDown.sqf b/addons/fire/functions/fnc_medical_canPatDown.sqf index b7efc262b27..758b83b9227 100644 --- a/addons/fire/functions/fnc_medical_canPatDown.sqf +++ b/addons/fire/functions/fnc_medical_canPatDown.sqf @@ -18,4 +18,4 @@ params ["", "_patient"]; -[_patient] call FUNC(isBurning) +_patient call FUNC(isBurning) diff --git a/addons/fire/functions/fnc_medical_progress.sqf b/addons/fire/functions/fnc_medical_progress.sqf index 07d99958d66..fd64b5c27da 100644 --- a/addons/fire/functions/fnc_medical_progress.sqf +++ b/addons/fire/functions/fnc_medical_progress.sqf @@ -5,8 +5,8 @@ * * Arguments: * 0: Arguments - * 0: Medic - * 1: Patient + * - 0: Medic (not used) + * - 1: Patient * * Return Value: * Continue pat down @@ -18,6 +18,6 @@ */ params ["_args"]; -_args params ["_medic", "_patient"]; +_args params ["", "_patient"]; -[_patient] call FUNC(isBurning) +_patient call FUNC(isBurning) diff --git a/addons/fire/functions/fnc_medical_success.sqf b/addons/fire/functions/fnc_medical_success.sqf index 78e119a8fa5..5538d7d4db0 100644 --- a/addons/fire/functions/fnc_medical_success.sqf +++ b/addons/fire/functions/fnc_medical_success.sqf @@ -6,6 +6,8 @@ * Arguments: * 0: Medic * 1: Patient + * 2: Body Part + * 3: Treatment * * Return Value: * None @@ -20,6 +22,7 @@ params ["_medic", "_patient", "_bodyPart", "_classname"]; private _intensity = _patient getVariable [QGVAR(intensity), 0]; _intensity = _intensity * INTENSITY_DECREASE_MULT_PAT_DOWN; + _patient setVariable [QGVAR(intensity), _intensity, true]; if (_intensity > BURN_MIN_INTENSITY) then { diff --git a/addons/fire/initSettings.inc.sqf b/addons/fire/initSettings.inc.sqf index 97963f3e322..ceacc410ff2 100644 --- a/addons/fire/initSettings.inc.sqf +++ b/addons/fire/initSettings.inc.sqf @@ -2,20 +2,20 @@ QGVAR(enabled), "CHECKBOX", [ELSTRING(common,Enabled), LSTRING(Setting_Description)], LSTRING(Category_DisplayName), - true, // default value - true, // isGlobal + true, + 1, {[QGVAR(fireEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + true // needs mission restart ] call CBA_fnc_addSetting; [ QGVAR(enableFlare), "CHECKBOX", [LSTRING(Setting_FlareEnable), LSTRING(Setting_FlareDescription)], LSTRING(Category_DisplayName), - false, // default value - true, // isGlobal + false, + 1, {[QGVAR(flareEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // Needs mission restart + true ] call CBA_fnc_addSetting; [ @@ -23,18 +23,16 @@ [LSTRING(Setting_DropWeapon), LSTRING(Setting_DropWeapon_Description)], LSTRING(Category_DisplayName), [ - [0,1,2], - [localize "STR_A3_OPTIONS_DISABLED", ELSTRING(common,aiOnly), ELSTRING(common,playersAndAI)], + [0, 1, 2], + ["STR_A3_OPTIONS_DISABLED", ELSTRING(common,aiOnly), ELSTRING(common,playersAndAI)], 1 ], - true // isGlobal + 1 ] call CBA_fnc_addSetting; [ QGVAR(enableScreams), "CHECKBOX", [LSTRING(Setting_EnableScreams), LSTRING(Setting_EnableScreams_Description)], LSTRING(Category_DisplayName), - true, - false // isGlobal + true ] call CBA_fnc_addSetting; - diff --git a/addons/fire/script_component.hpp b/addons/fire/script_component.hpp index 86ef159aaea..cf7b42a2b44 100644 --- a/addons/fire/script_component.hpp +++ b/addons/fire/script_component.hpp @@ -31,9 +31,14 @@ "amovppnemstpsoptwbindnon_amovppnemevasoptwbindr"\ ] - #define BURN_MAX_INTENSITY 10 #define BURN_MIN_INTENSITY 1 #define INTENSITY_DECREASE_MULT_PAT_DOWN 0.8 #define INTENSITY_DECREASE_MULT_ROLLING INTENSITY_DECREASE_MULT_PAT_DOWN + +#define INTENSITY_LOSS 0.03 +#define INTENSITY_UPDATE 3 +#define BURN_PROPAGATE_UPDATE 1 +#define BURN_PROPAGATE_DISTANCE 2 +#define BURN_THRESHOLD_INTENSE 3 diff --git a/addons/zeus/functions/fnc_moduleBurn.sqf b/addons/zeus/functions/fnc_moduleBurn.sqf index 4cf2017b670..e3e78a5f7b4 100644 --- a/addons/zeus/functions/fnc_moduleBurn.sqf +++ b/addons/zeus/functions/fnc_moduleBurn.sqf @@ -36,7 +36,6 @@ switch (false) do { [LSTRING(RequiresAddon)] call FUNC(showMessage); }; default { - [QEGVAR(fire,burn), [_unit, 5]] call CBA_fnc_globalEvent; + [QEGVAR(fire,burn), [_unit, 5], _unit] call CBA_fnc_targetEvent; }; }; - From ccb09e60d73da7096839f91a19ab7018a46436d6 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 3 Feb 2024 22:25:15 +0100 Subject: [PATCH 02/27] Update fnc_burn.sqf --- addons/fire/functions/fnc_burn.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index ea5c0a7f4dc..407ee8035fc 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -17,7 +17,7 @@ * Public: No */ -if !(EGVAR(common,settingsInitFinished)) exitWith { +if (!EGVAR(common,settingsInitFinished)) exitWith { EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(burn), _this]; }; From 41bd5bf5c3963642875f896cc89a643c96054917 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 5 Feb 2024 13:17:33 +0100 Subject: [PATCH 03/27] Fire deals more damage --- .../cookoff/functions/fnc_cookOffEffect.sqf | 2 +- addons/fire/CfgVehicles.hpp | 7 +++ addons/fire/XEH_postInit.sqf | 59 ++++++++++++++++--- addons/fire/config.cpp | 1 + addons/fire/functions/fnc_burn.sqf | 34 ++++++----- addons/fire/functions/fnc_burnEffects.sqf | 32 +++++----- addons/fire/functions/fnc_burnSimulation.sqf | 26 ++++---- addons/fire/functions/fnc_fireManagerPFH.sqf | 32 +++++----- addons/fire/functions/fnc_isBurning.sqf | 8 +-- addons/fire/script_component.hpp | 4 +- addons/grenades/CfgAmmo.hpp | 2 +- docs/wiki/framework/attach-framework.md | 2 +- docs/wiki/framework/fire-framework.md | 6 +- 13 files changed, 138 insertions(+), 77 deletions(-) create mode 100644 addons/fire/CfgVehicles.hpp diff --git a/addons/cookoff/functions/fnc_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index 44282f2f6b8..c755fc6fbb6 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -38,7 +38,7 @@ if (isServer) then { }; if (_ring) then { - private _intensity = 6; + 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; }; diff --git a/addons/fire/CfgVehicles.hpp b/addons/fire/CfgVehicles.hpp new file mode 100644 index 00000000000..0ed16faff7c --- /dev/null +++ b/addons/fire/CfgVehicles.hpp @@ -0,0 +1,7 @@ +class CfgVehicles { + class Static; + class GVAR(logic): Static { + scope = 1; + displayName = ""; + }; +}; diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 6da3b4b6e52..518af00c7b3 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -2,6 +2,7 @@ [QGVAR(burn), LINKFUNC(burn)] call CBA_fnc_addEventHandler; [QGVAR(burnEffects), LINKFUNC(burnEffects)] call CBA_fnc_addEventHandler; +[QGVAR(burnObjectEffects), LINKFUNC(burnObjectEffects)] call CBA_fnc_addEventHandler; [QGVAR(burnSimulation), LINKFUNC(burnSimulation)] call CBA_fnc_addEventHandler; // Only play sound if enabled in settings @@ -22,23 +23,67 @@ if (isServer) then { GVAR(fireSources) = createHashMap; [QGVAR(addFireSource), { - params ["_source", "_radius", "_intensity", "_key", ["_condition", {true}], ["_conditionArgs", []]]; + params [ + ["_source", objNull, [objNull, []]], + ["_radius", 0, [0]], + ["_intensity", 0, [0]], + ["_key", ""], + ["_condition", {true}], + ["_conditionArgs", []] + ]; - private _fireLogic = createVehicle ["ACE_LogicDummy", [0, 0, 0], [], 0, "NONE"]; + private _isObject = _source isEqualType objNull; - if (_source isEqualType objNull) then { - _fireLogic attachTo [_source]; + // Check if the source is valid + if !(_isObject || {_source isEqualTypeParams [0, 0, 0]}) exitWith {}; + + if (_isObject && {isNull _source}) exitWith {}; + if (_radius == 0 || _intensity == 0) exitWith {}; + if (_key isEqualTo "") exitWith {}; // key can be many types + + // If a position is passed, create a static object at said position + private _sourcePos = if (_isObject) then { + getPosATL _source } else { - _fireLogic setPosASL _source; + ASLToATL _source + }; + + private _fireLogic = createVehicle [QGVAR(logic), _sourcePos, [], 0, "CAN_COLLIDE"]; + + // If an object was passed, attach logic to the object + if (_isObject) then { + _fireLogic attachTo [_source]; + }; + + // hashValue supports more types than hashmaps do by default, but not all (e.g. locations) + private _hashedKey = hashValue _key; + + if (isNil "_hashedKey") exitWith { + ERROR_1("Unsupported key type used: %1",_key) + }; + + // To avoid issues, remove existing entries first before overwriting + if (_hashedKey in GVAR(fireSources)) then { + [QGVAR(removeFireSource), _key] call CBA_fnc_localEvent; }; - GVAR(fireSources) set [_key, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; + GVAR(fireSources) set [_hashedKey, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; }] call CBA_fnc_addEventHandler; [QGVAR(removeFireSource), { params ["_key"]; - GVAR(fireSources) deleteAt _key; + private _hashedKey = hashValue _key; + + if (isNil "_hashedKey") exitWith { + ERROR_1("Unsupported key type used: %1",_key) + }; + + (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; + + // Deleting the object will automatically remove any particles (if there are any) + detach _fireLogic; + deleteVehicle _fireLogic; }] call CBA_fnc_addEventHandler; [LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/fire/config.cpp b/addons/fire/config.cpp index da8cd0091c2..df2eb5cb79c 100644 --- a/addons/fire/config.cpp +++ b/addons/fire/config.cpp @@ -24,6 +24,7 @@ class CfgPatches { #include "CfgEventHandlers.hpp" #include "CfgSounds.hpp" +#include "CfgVehicles.hpp" #include "ACE_Medical_Treatment_Actions.hpp" #include "RscTitles.hpp" diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index 407ee8035fc..ed9883cf8ff 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -1,10 +1,10 @@ #include "..\script_component.hpp" /* - * Author: tcvm, johnb43 - * Makes object catch fire. Only call from targeted events, is applied globally. + * Author: johnb43 + * Makes a unit catch fire. Only call from targeted events, is applied globally. * * Arguments: - * 0: Vehicle + * 0: Unit * 1: Intensity of fire * 2: Instigator of fire (default: objNull) * @@ -25,31 +25,35 @@ if (!GVAR(enabled)) exitWith {}; params ["_unit", "_intensity", ["_instigator", objNull]]; +if (BURN_MIN_INTENSITY > _intensity) exitWith {}; + // Check if unit is remote (objNull is remote) if (!local _unit) exitWith {}; // Check if the unit can burn (takes care of spectators and curators) -if (getNumber (configOf _unit >> "isPlayableLogic") == 1) exitWith {}; +if (getNumber (configOf _unit >> "isPlayableLogic") == 1 || {!(_unit isKindOf "CAManBase")}) exitWith {}; -// If unit is invulnerable, don't burn unit +// If unit is invulnerable, don't burn the unit if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith {}; -// If unit is already burning, don't burn more -if (_unit call FUNC(isBurning)) exitWith {}; +private _unitPos = getPosASL _unit; + +// Check if unit is in water +if (surfaceIsWater _unitPos && {(_unitPos select 2) < 1}) exitWith {}; + +// If unit is already burning, update intensity, but don't add another PFH +if (_unit call FUNC(isBurning)) exitWith { + _unit setVariable [QGVAR(intensity), _intensity, true]; +}; _unit setVariable [QGVAR(intensity), _intensity, true]; -// Fire simulation -private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator], format [QGVAR(burnSimulation_%1), hashValue _unit]] call CBA_fnc_globalEventJIP; +// Fire simulation (objects are handled differently) +private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator]] call CBA_fnc_globalEventJIP; [_burnSimulationJipID, _unit] call CBA_fnc_removeGlobalEventJIP; // Spawn effects for unit -private _burnEffectsJipID = [QGVAR(burnEffects), _unit, format [QGVAR(burnEffects_%1), hashValue _unit]] call CBA_fnc_globalEventJIP; +private _burnEffectsJipID = [QGVAR(burnEffects), _unit] call CBA_fnc_globalEventJIP; [_burnEffectsJipID, _unit] call CBA_fnc_removeGlobalEventJIP; _unit setVariable [QGVAR(jipIDs), [_burnSimulationJipID, _burnEffectsJipID], true]; - -// Play screams and optional weapon dropping -if (_unit call EFUNC(common,isAwake)) then { - [_unit, false] call FUNC(burnReaction); -}; diff --git a/addons/fire/functions/fnc_burnEffects.sqf b/addons/fire/functions/fnc_burnEffects.sqf index eabf29c0531..469fa4eceac 100644 --- a/addons/fire/functions/fnc_burnEffects.sqf +++ b/addons/fire/functions/fnc_burnEffects.sqf @@ -26,7 +26,7 @@ private _lightFlare = objNull; if (hasInterface) then { _fireParticle = "#particlesource" createVehicleLocal _unitPos; - _fireParticle attachTo [_unit, [0, 0, 0]]; + _fireParticle attachTo [_unit]; _fireParticle setDropInterval 0.03; _smokeParticle = "#particlesource" createVehicleLocal _unitPos; @@ -35,7 +35,7 @@ if (hasInterface) then { _fireLight setLightIntensity 0; _fireLight setLightAmbient [0.8, 0.6, 0.2]; _fireLight setLightColor [1, 0.5, 0.4]; - _fireLight attachTo [_unit, [0, 0, 0]]; + _fireLight attachTo [_unit]; _fireLight setLightDayLight false; _lightFlare = "#lightpoint" createVehicleLocal _unitPos; @@ -128,17 +128,8 @@ if (isServer) then { 0 // random direction intensity ]; + _smokeParticle setDropInterval 0.15; _smokeParticle setParticleCircle [0, [0, 0, 0]]; - _smokeParticle setParticleRandom [ - 0, // life time - [0.25, 0.25, 0], // position - [0.2, 0.2, 0], // move velocity - 0, // rotation velocity - 0.25, // size - [0, 0, 0, 0.1], // color - 0, // random direction period - 0 // random direction intensity - ]; _smokeParticle setParticleParams [ ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 7, 48], // sprite sheet values "", // animation name @@ -164,13 +155,21 @@ if (isServer) then { "", // before destroy script _unit // particle source ]; - _smokeParticle setDropInterval 0.15; + _smokeParticle setParticleRandom [ + 0, // life time + [0.25, 0.25, 0], // position + [0.2, 0.2, 0], // move velocity + 0, // rotation velocity + 0.25, // size + [0, 0, 0, 0.1], // color + 0, // random direction period + 0 // random direction intensity + ]; _fireLight setLightBrightness ((_intensity * 3) / 10); - _lightFlare setLightBrightness (_intensity / 30); - - private _distanceToUnit = _unit distance ACE_player; _fireLight setLightAttenuation [1, 10 max (5 min (10 - _intensity)), 0, 15]; + + _lightFlare setLightBrightness (_intensity / 30); _lightFlare setLightFlareSize (_intensity * (3 / 4)) * FLARE_SIZE_MODIFIER; if (!GVAR(enableFlare)) then { @@ -179,6 +178,7 @@ if (isServer) then { // Always keep flare visible to perceiving unit as long as it isn't the player if (_unit != ACE_player) then { + private _distanceToUnit = _unit distance ACE_player; private _relativeAttachPoint = [0, 0, 0.3]; if (_distanceToUnit > 1.5) then { diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index ed5a338ea58..e077286b12a 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: tcvm, johnb43 - * Makes object catch fire. Simulates fire intensity over time. + * Simulates fire intensity over time on burning units. * Arbitrary values to ignite people. Assumed maximum is "10". * * Arguments: @@ -29,20 +29,18 @@ _unit setVariable [QGVAR(burnCounter), nil]; private _remote = !local _unit; - // If unit is local and the fire has died now, the effects need to be cleaned up -> do not stop PFH here + // If unit is local and the fire has died out, the effects need to be cleaned up -> do not stop PFH here if (isNull _unit || {_remote && {!(_unit call FUNC(isBurning))}}) exitWith { _pfhID call CBA_fnc_removePerFrameHandler; }; if (_remote) exitWith {}; - private _unitPos = getPosASL _unit; - // If unit is invulnerable or in water or if the fire has died out, stop burning unit if ( !(_unit call FUNC(isBurning)) || - {surfaceIsWater _unitPos && {(_unitPos select 2) < 1}} || - {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} + {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} || + {private _unitPos = getPosASL _unit; surfaceIsWater _unitPos && {(_unitPos select 2) < 1}} ) exitWith { // Remove global effects and simulation { @@ -66,17 +64,21 @@ _unit setVariable [QGVAR(burnCounter), nil]; private _intensity = _unit getVariable [QGVAR(intensity), 0]; - // Propagate fire to other units if it's intense + // Propagate fire to other units (alive or dead) if it's intense if (_intensity >= BURN_THRESHOLD_INTENSE) then { - _unitPos = ASLToAGL _unitPos; + private _adjustedIntensity = 0; { - if !(_x call FUNC(isBurning)) then { - _distancePercent = 1 - ((_unitPos distance _x) / BURN_PROPAGATE_DISTANCE); + _distancePercent = 1 - ((_unit distance _x) / BURN_PROPAGATE_DISTANCE); + _adjustedIntensity = _intensity * _distancePercent; - [QGVAR(burn), [_x, _intensity * _distancePercent, _instigator], _x] call CBA_fnc_targetEvent; + // Don't burn if intensity is too low + if (BURN_MIN_INTENSITY > _adjustedIntensity) then { + continue; }; - } forEach (_unitPos nearEntities ["CAManBase", BURN_PROPAGATE_DISTANCE]); + + [QGVAR(burn), [_x, _adjustedIntensity, _instigator], _x] call CBA_fnc_targetEvent; + } forEach nearestObjects [_unit, ["CAManBase"], BURN_PROPAGATE_DISTANCE]; }; // Update intensity/fire reactions diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf index 0fce278fe6c..74f744cc35f 100644 --- a/addons/fire/functions/fnc_fireManagerPFH.sqf +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -1,8 +1,7 @@ #include "..\script_component.hpp" /* * Author: tcvm - * Handles various fire objects and determines if local units deserves to get burned. - * Used to handle external burning objects, not used internally because internal methods are more performant. + * Handles various objects on fire and determines if units close to objects deserve to get burned. * * Arguments: * 0: Args (not used) @@ -12,34 +11,37 @@ * None * * Example: - * [ace_fire_fnc_fireManagerPFH, 0.25] call CBA_fnc_addPerFrameHandler + * [[], -1] call CBA_fnc_addPerFrameHandler * * Public: No */ -private _attachedObject = objNull; -private _sourcePos = []; private _distancePercent = 0; +private _adjustedIntensity = 0; { - _y params ["_source", "_radius", "_intensity", "_condition", "_conditionArgs"]; + _y params ["_fireLogic", "_radius", "_intensity", "_condition", "_conditionArgs"]; // Remove when condition is no longer valid if !(_conditionArgs call _condition) then { - GVAR(fireSources) deleteAt _x; + (GVAR(fireSources) deleteAt _x) params [["_fireLogic", objNull]]; + + detach _fireLogic; + deleteVehicle _fireLogic; continue; }; - _attachedObject = attachedTo _source; - _sourcePos = ASLtoAGL getPosASL ([_source, _attachedObject] select (!isNull _attachedObject)); - - // Burn units close to the fire + // Burn units (alive or dead) close to the fire { - if !(_x call FUNC(isBurning)) then { - _distancePercent = 1 - ((_sourcePos distance _x) / _radius); + _distancePercent = 1 - ((_fireLogic distance _x) / _radius); + _adjustedIntensity = _intensity * _distancePercent; - [QGVAR(burn), [_x, _intensity * _distancePercent], _x] call CBA_fnc_targetEvent; + // Don't burn if intensity is too low + if (BURN_MIN_INTENSITY > _adjustedIntensity) then { + continue; }; - } forEach (_sourcePos nearEntities ["CAManBase", _radius]); + + [QGVAR(burn), [_x, _adjustedIntensity], _x] call CBA_fnc_targetEvent; + } forEach nearestObjects [_fireLogic, ["CAManBase"], _radius]; } forEach GVAR(fireSources); diff --git a/addons/fire/functions/fnc_isBurning.sqf b/addons/fire/functions/fnc_isBurning.sqf index ba0dd9e13fe..04a57c29e6b 100644 --- a/addons/fire/functions/fnc_isBurning.sqf +++ b/addons/fire/functions/fnc_isBurning.sqf @@ -1,10 +1,10 @@ #include "..\script_component.hpp" /* * Author: commy2 - * Check if unit is burning. + * Check if an object is burning. * * Arguments: - * 0: Unit + * 0: Object * * Return Value: * None @@ -15,6 +15,6 @@ * Public: Yes */ -params [["_unit", objNull, [objNull]]]; +params [["_object", objNull, [objNull]]]; -(_unit getVariable [QGVAR(intensity), 0]) > BURN_MIN_INTENSITY +(_object getVariable [QGVAR(intensity), 0]) > BURN_MIN_INTENSITY diff --git a/addons/fire/script_component.hpp b/addons/fire/script_component.hpp index cf7b42a2b44..ebb0002ff6f 100644 --- a/addons/fire/script_component.hpp +++ b/addons/fire/script_component.hpp @@ -37,8 +37,8 @@ #define INTENSITY_DECREASE_MULT_PAT_DOWN 0.8 #define INTENSITY_DECREASE_MULT_ROLLING INTENSITY_DECREASE_MULT_PAT_DOWN -#define INTENSITY_LOSS 0.03 -#define INTENSITY_UPDATE 3 +#define INTENSITY_LOSS 0.02 +#define INTENSITY_UPDATE 2 #define BURN_PROPAGATE_UPDATE 1 #define BURN_PROPAGATE_DISTANCE 2 #define BURN_THRESHOLD_INTENSE 3 diff --git a/addons/grenades/CfgAmmo.hpp b/addons/grenades/CfgAmmo.hpp index 5082dd432d9..e911e237474 100644 --- a/addons/grenades/CfgAmmo.hpp +++ b/addons/grenades/CfgAmmo.hpp @@ -153,7 +153,7 @@ class CfgAmmo { class ACE_G_M14: SmokeShell { GVAR(incendiary) = 1; model = QPATHTOF(models\ace_anm14th3_armed.p3d); - hit = 5; + hit = 10; indirectHit = 4; indirectHitRange = 1.1; dangerRadiusHit = 50; diff --git a/docs/wiki/framework/attach-framework.md b/docs/wiki/framework/attach-framework.md index 2ed5f745614..2d00ff8d210 100644 --- a/docs/wiki/framework/attach-framework.md +++ b/docs/wiki/framework/attach-framework.md @@ -29,7 +29,7 @@ class CfgVehicles { scope = 1; // Should be 1 (private) or 2 (public), scope 0 will cause errors on object creation displayName = "New ACE attachable item"; model = "\path\to\my\model.p3d"; - vehicleClass = ""; + vehicleClass = ""; }; }; ``` diff --git a/docs/wiki/framework/fire-framework.md b/docs/wiki/framework/fire-framework.md index 2236c5a1c86..eec9baf3e58 100644 --- a/docs/wiki/framework/fire-framework.md +++ b/docs/wiki/framework/fire-framework.md @@ -26,8 +26,8 @@ Use `CBA_fnc_serverEvent` to use the following features. Events are defined only 0 | Source of flame | Object/Position ASL | Required 1 | Radius of fire | Number | Required 2 | Intensity of fire (1, 10] | Number | Required -3 | Fire source ID | Any | Required -4 | Condition to stop fire | Code | Optional (default: `{ true }`) +3 | Fire source ID | Array/Boolean/Code/Config/Group/Namespace/NaN/Number/Object/Side/String | Required +4 | Condition to stop fire | Code | Optional (default: `{true}`) 5 | Arguments to pass to condition | Any | Optional (default: `[]`) ### 1.2 Removing fire source @@ -36,4 +36,4 @@ Use `CBA_fnc_serverEvent` to use the following features. Events are defined only | Arguments | Type | Optional (default value) ---| --------- | ---- | ------------------------ -0 | Fire source ID | Any | Required +0 | Fire source ID | Array/Boolean/Code/Config/Group/Namespace/NaN/Number/Object/Side/String | Required From 8f3a1e9dc50258979dd4578e71079c974524a5b2 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:30:50 +0100 Subject: [PATCH 04/27] Update fnc_burnEffects.sqf --- addons/fire/functions/fnc_burnEffects.sqf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/fire/functions/fnc_burnEffects.sqf b/addons/fire/functions/fnc_burnEffects.sqf index 469fa4eceac..da690207216 100644 --- a/addons/fire/functions/fnc_burnEffects.sqf +++ b/addons/fire/functions/fnc_burnEffects.sqf @@ -25,20 +25,20 @@ private _fireLight = objNull; private _lightFlare = objNull; if (hasInterface) then { - _fireParticle = "#particlesource" createVehicleLocal _unitPos; + _fireParticle = createVehicleLocal ["#particlesource", _unitPos, [], 0, "CAN_COLLIDE"]; _fireParticle attachTo [_unit]; _fireParticle setDropInterval 0.03; - _smokeParticle = "#particlesource" createVehicleLocal _unitPos; + _smokeParticle = createVehicleLocal ["#particlesource", _unitPos, [], 0, "CAN_COLLIDE"]; - _fireLight = "#lightpoint" createVehicleLocal _unitPos; + _fireLight = createVehicleLocal ["#lightpoint", _unitPos, [], 0, "CAN_COLLIDE"]; _fireLight setLightIntensity 0; _fireLight setLightAmbient [0.8, 0.6, 0.2]; _fireLight setLightColor [1, 0.5, 0.4]; _fireLight attachTo [_unit]; _fireLight setLightDayLight false; - _lightFlare = "#lightpoint" createVehicleLocal _unitPos; + _lightFlare = createVehicleLocal ["#lightpoint", _unitPos, [], 0, "CAN_COLLIDE"]; _lightFlare setLightIntensity 0; _lightFlare setLightColor [1, 0.8, 0.8]; _lightFlare setLightUseFlare true; From a35864c6156c50bece069ccf8d4eebed4aaa978f Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:43:25 +0100 Subject: [PATCH 05/27] Minor tweaks --- addons/fire/CfgSounds.hpp | 8 ++++---- addons/fire/XEH_postInit.sqf | 4 ++-- addons/fire/functions/fnc_burnReaction.sqf | 17 +++++------------ addons/fire/functions/fnc_medical_success.sqf | 2 +- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/addons/fire/CfgSounds.hpp b/addons/fire/CfgSounds.hpp index b83ce9b91a4..76fb0e64f74 100644 --- a/addons/fire/CfgSounds.hpp +++ b/addons/fire/CfgSounds.hpp @@ -1,10 +1,10 @@ // weird ass concatenation syntax. PBO Project complains otherwise... #define CONCAT(a,b) a####b #define CREATE_SCREAM(no)\ -class GVAR(DOUBLES(scream,no)) { \ - name = QUOTE(GVAR(CONCAT(scream,no)));\ - sound[] = {QUOTE(PATHTOF(CONCAT(sounds\scream,no).ogg)), QUOTE(db+8), 1};\ - titles[] = {}; \ +class GVAR(DOUBLES(scream,no)) {\ + name = QGVAR(CONCAT(scream,no));\ + sound[] = {QPATHTOF(CONCAT(sounds\scream,no).ogg), QUOTE(db+8), 1};\ + titles[] = {};\ } class CfgSounds { diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index dfbe531b107..b093b1cdc59 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -59,7 +59,7 @@ if (isServer) then { private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_1("Unsupported key type used: %1",_key) + ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); }; // To avoid issues, remove existing entries first before overwriting @@ -76,7 +76,7 @@ if (isServer) then { private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_1("Unsupported key type used: %1",_key) + ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); }; (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; diff --git a/addons/fire/functions/fnc_burnReaction.sqf b/addons/fire/functions/fnc_burnReaction.sqf index 42bd64b43ce..3138a31cc23 100644 --- a/addons/fire/functions/fnc_burnReaction.sqf +++ b/addons/fire/functions/fnc_burnReaction.sqf @@ -5,7 +5,6 @@ * * Arguments: * 0: Unit - * 1: Should unit throw its current weapon (default: true) * * Return Value: * None @@ -13,20 +12,14 @@ * Public: No */ -params ["_unit", ["_throwWeapon", true]]; +params ["_unit"]; if ( - _throwWeapon - && {GVAR(dropWeapon) > 0} - && {isNull objectParent _unit && {(currentWeapon _unit) != ""}} - && {!isPlayer _unit || GVAR(dropWeapon) >= 2} + GVAR(dropWeapon) > 0 && + {isNull objectParent _unit && {(currentWeapon _unit) != ""}} && + {!isPlayer _unit || GVAR(dropWeapon) >= 2} ) then { _unit call EFUNC(common,throwWeapon); }; -if (_unit isKindOf "CAManBase") then { - private _soundID = floor (1 + random 15); - private _sound = format [QGVAR(scream_%1), _soundID]; - - [QGVAR(playScream), [_sound, _unit]] call CBA_fnc_globalEvent; -}; +[QGVAR(playScream), [format [QGVAR(scream_%1), floor (1 + random 15)], _unit]] call CBA_fnc_globalEvent; diff --git a/addons/fire/functions/fnc_medical_success.sqf b/addons/fire/functions/fnc_medical_success.sqf index 5538d7d4db0..a84aab56444 100644 --- a/addons/fire/functions/fnc_medical_success.sqf +++ b/addons/fire/functions/fnc_medical_success.sqf @@ -29,7 +29,7 @@ if (_intensity > BURN_MIN_INTENSITY) then { TRACE_1("patient still burning, looping",_this); if (EGVAR(medical_gui,pendingReopen)) then { - LOG("temporarily blocking medical menu reopen"); + TRACE_1("temporarily blocking medical menu reopen",_this); EGVAR(medical_gui,pendingReopen) = false; [{EGVAR(medical_gui,pendingReopen) = true}] call CBA_fnc_execNextFrame; From b5dfe0a3469a91ea80ad70c7f2d7a90d35b22c98 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:51:41 +0100 Subject: [PATCH 06/27] Removed outdated comment --- addons/fire/XEH_postInit.sqf | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index b093b1cdc59..d0869d3b71a 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -81,7 +81,6 @@ if (isServer) then { (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; - // Deleting the object will automatically remove any particles (if there are any) detach _fireLogic; deleteVehicle _fireLogic; }] call CBA_fnc_addEventHandler; From 70b21f6cecffd82cab7cb3f25deaa5f84b50bcd0 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:59:59 +0100 Subject: [PATCH 07/27] Minor cleanup --- addons/fire/XEH_postInit.sqf | 108 +++++++++++++++---------------- addons/fire/initSettings.inc.sqf | 15 +++-- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index d0869d3b71a..96373548036 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -14,77 +14,77 @@ _source say3D _scream; }] call CBA_fnc_addEventHandler; -if (isServer) then { - ["CBA_settingsInitialized", { - TRACE_1("settingsInit",GVAR(enabled)); +if (!isServer) exitWith {}; - if (!GVAR(enabled)) exitWith {}; +["CBA_settingsInitialized", { + TRACE_1("settingsInit",GVAR(enabled)); - GVAR(fireSources) = createHashMap; + if (!GVAR(enabled)) exitWith {}; - [QGVAR(addFireSource), { - params [ - ["_source", objNull, [objNull, []]], - ["_radius", 0, [0]], - ["_intensity", 0, [0]], - ["_key", ""], - ["_condition", {true}], - ["_conditionArgs", []] - ]; + GVAR(fireSources) = createHashMap; - private _isObject = _source isEqualType objNull; + [QGVAR(addFireSource), { + params [ + ["_source", objNull, [objNull, []]], + ["_radius", 0, [0]], + ["_intensity", 0, [0]], + ["_key", ""], + ["_condition", {true}], + ["_conditionArgs", []] + ]; - // Check if the source is valid - if !(_isObject || {_source isEqualTypeParams [0, 0, 0]}) exitWith {}; + private _isObject = _source isEqualType objNull; - if (_isObject && {isNull _source}) exitWith {}; - if (_radius == 0 || _intensity == 0) exitWith {}; - if (_key isEqualTo "") exitWith {}; // key can be many types + // Check if the source is valid + if !(_isObject || {_source isEqualTypeParams [0, 0, 0]}) exitWith {}; - // If a position is passed, create a static object at said position - private _sourcePos = if (_isObject) then { - getPosATL _source - } else { - ASLToATL _source - }; + if (_isObject && {isNull _source}) exitWith {}; + if (_radius == 0 || _intensity == 0) exitWith {}; + if (_key isEqualTo "") exitWith {}; // key can be many types - private _fireLogic = createVehicle [QGVAR(logic), _sourcePos, [], 0, "CAN_COLLIDE"]; + // If a position is passed, create a static object at said position + private _sourcePos = if (_isObject) then { + getPosATL _source + } else { + ASLToATL _source + }; - // If an object was passed, attach logic to the object - if (_isObject) then { - _fireLogic attachTo [_source]; - }; + private _fireLogic = createVehicle [QGVAR(logic), _sourcePos, [], 0, "CAN_COLLIDE"]; - // hashValue supports more types than hashmaps do by default, but not all (e.g. locations) - private _hashedKey = hashValue _key; + // If an object was passed, attach logic to the object + if (_isObject) then { + _fireLogic attachTo [_source]; + }; - if (isNil "_hashedKey") exitWith { - ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); - }; + // hashValue supports more types than hashmaps do by default, but not all (e.g. locations) + private _hashedKey = hashValue _key; - // To avoid issues, remove existing entries first before overwriting - if (_hashedKey in GVAR(fireSources)) then { - [QGVAR(removeFireSource), _key] call CBA_fnc_localEvent; - }; + if (isNil "_hashedKey") exitWith { + ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); + }; - GVAR(fireSources) set [_hashedKey, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; - }] call CBA_fnc_addEventHandler; + // To avoid issues, remove existing entries first before overwriting + if (_hashedKey in GVAR(fireSources)) then { + [QGVAR(removeFireSource), _key] call CBA_fnc_localEvent; + }; - [QGVAR(removeFireSource), { - params ["_key"]; + GVAR(fireSources) set [_hashedKey, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; + }] call CBA_fnc_addEventHandler; - private _hashedKey = hashValue _key; + [QGVAR(removeFireSource), { + params ["_key"]; - if (isNil "_hashedKey") exitWith { - ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); - }; + private _hashedKey = hashValue _key; - (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; + if (isNil "_hashedKey") exitWith { + ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); + }; - detach _fireLogic; - deleteVehicle _fireLogic; - }] call CBA_fnc_addEventHandler; + (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; - [LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; + detach _fireLogic; + deleteVehicle _fireLogic; }] call CBA_fnc_addEventHandler; -}; + + [LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; +}] call CBA_fnc_addEventHandler; diff --git a/addons/fire/initSettings.inc.sqf b/addons/fire/initSettings.inc.sqf index ceacc410ff2..431998ffd95 100644 --- a/addons/fire/initSettings.inc.sqf +++ b/addons/fire/initSettings.inc.sqf @@ -1,5 +1,6 @@ [ - QGVAR(enabled), "CHECKBOX", + QGVAR(enabled), + "CHECKBOX", [ELSTRING(common,Enabled), LSTRING(Setting_Description)], LSTRING(Category_DisplayName), true, @@ -9,17 +10,18 @@ ] call CBA_fnc_addSetting; [ - QGVAR(enableFlare), "CHECKBOX", + QGVAR(enableFlare), + "CHECKBOX", [LSTRING(Setting_FlareEnable), LSTRING(Setting_FlareDescription)], LSTRING(Category_DisplayName), false, 1, - {[QGVAR(flareEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true + {[QGVAR(flareEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)} ] call CBA_fnc_addSetting; [ - QGVAR(dropWeapon), "LIST", + QGVAR(dropWeapon), + "LIST", [LSTRING(Setting_DropWeapon), LSTRING(Setting_DropWeapon_Description)], LSTRING(Category_DisplayName), [ @@ -31,7 +33,8 @@ ] call CBA_fnc_addSetting; [ - QGVAR(enableScreams), "CHECKBOX", + QGVAR(enableScreams), + "CHECKBOX", [LSTRING(Setting_EnableScreams), LSTRING(Setting_EnableScreams_Description)], LSTRING(Category_DisplayName), true From eb02fd7a109c7f3a65346ac2dda6357584669b4c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:13:45 +0100 Subject: [PATCH 08/27] Use eyePos for better position --- addons/fire/functions/fnc_burn.sqf | 6 +++--- addons/fire/functions/fnc_burnSimulation.sqf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index ed9883cf8ff..511133bfd04 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -36,10 +36,10 @@ if (getNumber (configOf _unit >> "isPlayableLogic") == 1 || {!(_unit isKindOf "C // If unit is invulnerable, don't burn the unit if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith {}; -private _unitPos = getPosASL _unit; +private _eyePos = eyePos _unit; -// Check if unit is in water -if (surfaceIsWater _unitPos && {(_unitPos select 2) < 1}) exitWith {}; +// Check if unit is mostly submerged in water +if (surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}) exitWith {}; // If unit is already burning, update intensity, but don't add another PFH if (_unit call FUNC(isBurning)) exitWith { diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index e077286b12a..27f9957ad73 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -40,7 +40,7 @@ _unit setVariable [QGVAR(burnCounter), nil]; if ( !(_unit call FUNC(isBurning)) || {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} || - {private _unitPos = getPosASL _unit; surfaceIsWater _unitPos && {(_unitPos select 2) < 1}} + {private _eyePos = eyePos _unit; surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}} ) exitWith { // Remove global effects and simulation { From 1aaaa37930d8b28476fa794c5c3ceec6ba3a0ba7 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Tue, 26 Mar 2024 22:18:49 +0100 Subject: [PATCH 09/27] Update fnc_burnSimulation.sqf --- addons/fire/functions/fnc_burnSimulation.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index 27f9957ad73..764d6383f87 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -97,7 +97,7 @@ _unit setVariable [QGVAR(burnCounter), nil]; _unit setVariable [QGVAR(stopDropRoll), true]; if (!_sdr) then { - TRACE_1("stop, drop, roll!", _unit); + TRACE_1("stop, drop, roll!",_unit); _unit setUnitPos "DOWN"; doStop _unit; @@ -112,7 +112,7 @@ _unit setVariable [QGVAR(burnCounter), nil]; } else { // Make the unit leave the vehicle if (_vehicle != _unit) then { - TRACE_1("Ejecting", _unit); + TRACE_1("Ejecting",_unit); _unit leaveVehicle _vehicle; unassignVehicle _unit; From 2af0da4853facca2fb3a7f258dbc6fadb160c8aa Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:59:11 +0200 Subject: [PATCH 10/27] Fixed headers, made fire simulation local --- addons/fire/XEH_postInit.sqf | 4 +-- addons/fire/functions/fnc_burn.sqf | 7 ++--- addons/fire/functions/fnc_burnIndicator.sqf | 5 +-- addons/fire/functions/fnc_burnSimulation.sqf | 33 +++++++++----------- addons/fire/functions/fnc_fireManagerPFH.sqf | 9 +++--- addons/zeus/functions/fnc_moduleBurn.sqf | 9 ++---- 6 files changed, 29 insertions(+), 38 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 9becb56b712..bfcecf80bf8 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -60,7 +60,7 @@ if (!isServer) exitWith {}; private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); + ERROR_2("Unsupported key type used: %1 - %2 - %3",_key,typeName _key); }; // To avoid issues, remove existing entries first before overwriting @@ -77,7 +77,7 @@ if (!isServer) exitWith {}; private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_3("Unsupported key type used: %1 - %2 - %3",_key,typeName _key,typeOf _key); + ERROR_2("Unsupported key type used: %1 - %2 - %3",_key,typeName _key); }; (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index 511133bfd04..defc822c54e 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -18,7 +18,7 @@ */ if (!EGVAR(common,settingsInitFinished)) exitWith { - EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(burn), _this]; + EGVAR(common,runAtSettingsInitialized) pushBack [LINKFUNC(burn), _this]; }; if (!GVAR(enabled)) exitWith {}; @@ -49,11 +49,10 @@ if (_unit call FUNC(isBurning)) exitWith { _unit setVariable [QGVAR(intensity), _intensity, true]; // Fire simulation (objects are handled differently) -private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator]] call CBA_fnc_globalEventJIP; -[_burnSimulationJipID, _unit] call CBA_fnc_removeGlobalEventJIP; +[QGVAR(burnSimulation), [_unit, _instigator], _unit] call CBA_fnc_targetEvent; // Spawn effects for unit private _burnEffectsJipID = [QGVAR(burnEffects), _unit] call CBA_fnc_globalEventJIP; [_burnEffectsJipID, _unit] call CBA_fnc_removeGlobalEventJIP; -_unit setVariable [QGVAR(jipIDs), [_burnSimulationJipID, _burnEffectsJipID], true]; +_unit setVariable [QGVAR(jipID), _burnEffectsJipID, true]; diff --git a/addons/fire/functions/fnc_burnIndicator.sqf b/addons/fire/functions/fnc_burnIndicator.sqf index 2874b69d115..5dbc1a8cbf0 100644 --- a/addons/fire/functions/fnc_burnIndicator.sqf +++ b/addons/fire/functions/fnc_burnIndicator.sqf @@ -16,14 +16,15 @@ * Public: No */ -params ["_unit", "_pfhHandle"]; +params ["_unit", "_pfhID"]; if (!alive _unit || {!(_unit call FUNC(isBurning))}) exitWith { - _pfhHandle call CBA_fnc_removePerFrameHandler; + _pfhID call CBA_fnc_removePerFrameHandler; _unit setVariable [QGVAR(burnUIPFH), nil]; }; +// Don't show burn overlay if unconscious or dead if !(_unit call EFUNC(common,isAwake)) exitWith {}; private _iteration = _unit getVariable [QGVAR(indicatorIteration), 0]; diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index 764d6383f87..e48fa38ec42 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -12,29 +12,27 @@ * None * * Example: - * player call ace_fire_fnc_burnSimulation + * [player, player] call ace_fire_fnc_burnSimulation * * Public: No */ params ["_unit", "_instigator"]; -// Reset variables -_unit setVariable [QGVAR(stopDropRoll), nil]; -_unit setVariable [QGVAR(burnCounter), nil]; - [{ params ["_args", "_pfhID"]; _args params ["_unit", "_instigator"]; - private _remote = !local _unit; - - // If unit is local and the fire has died out, the effects need to be cleaned up -> do not stop PFH here - if (isNull _unit || {_remote && {!(_unit call FUNC(isBurning))}}) exitWith { + if (isNull _unit) exitWith { _pfhID call CBA_fnc_removePerFrameHandler; }; - if (_remote) exitWith {}; + // Locality has changed + if (!local _unit) exitWith { + _pfhID call CBA_fnc_removePerFrameHandler; + + [QGVAR(burnSimulation), [_unit, _instigator], _unit] call CBA_fnc_targetEvent; + }; // If unit is invulnerable or in water or if the fire has died out, stop burning unit if ( @@ -42,21 +40,18 @@ _unit setVariable [QGVAR(burnCounter), nil]; {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} || {private _eyePos = eyePos _unit; surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}} ) exitWith { - // Remove global effects and simulation - { - _x call CBA_fnc_removeGlobalEventJIP; - } forEach (_unit getVariable [QGVAR(jipIDs), []]); + // Remove global effects + (_unit getVariable [QGVAR(jipID), ""]) call CBA_fnc_removeGlobalEventJIP; // Update globally that the unit isn't burning anymore _unit setVariable [QGVAR(intensity), nil, true]; _pfhID call CBA_fnc_removePerFrameHandler; - _unit setVariable [QGVAR(stopDropRoll), nil]; - _unit setVariable [QGVAR(burnCounter), nil]; - - if (!isPlayer _unit) then { + if (!isNil {_unit getVariable QGVAR(stopDropRoll)} && {!isPlayer _unit}) then { _unit setUnitPos "AUTO"; + + _unit setVariable [QGVAR(stopDropRoll), nil, true]; }; }; @@ -94,7 +89,7 @@ _unit setVariable [QGVAR(burnCounter), nil]; private _vehicle = objectParent _unit; if (isNull _vehicle && {_sdr || {0.05 > random 1}}) then { - _unit setVariable [QGVAR(stopDropRoll), true]; + _unit setVariable [QGVAR(stopDropRoll), true, true]; if (!_sdr) then { TRACE_1("stop, drop, roll!",_unit); diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf index 74f744cc35f..eb59faef724 100644 --- a/addons/fire/functions/fnc_fireManagerPFH.sqf +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -4,14 +4,13 @@ * Handles various objects on fire and determines if units close to objects deserve to get burned. * * Arguments: - * 0: Args (not used) - * 1: PFH Handle (not used) + * None * * Return Value: * None * * Example: - * [[], -1] call CBA_fnc_addPerFrameHandler + * ace_fire_fnc_fireManagerPFH call CBA_fnc_addPerFrameHandler * * Public: No */ @@ -37,8 +36,8 @@ private _adjustedIntensity = 0; _distancePercent = 1 - ((_fireLogic distance _x) / _radius); _adjustedIntensity = _intensity * _distancePercent; - // Don't burn if intensity is too low - if (BURN_MIN_INTENSITY > _adjustedIntensity) then { + // Don't burn if intensity is too low or already burning with higher intensity + if (BURN_MIN_INTENSITY > _adjustedIntensity || {(_x getVariable [QGVAR(intensity), 0]) > _adjustedIntensity}) then { continue; }; diff --git a/addons/zeus/functions/fnc_moduleBurn.sqf b/addons/zeus/functions/fnc_moduleBurn.sqf index e3e78a5f7b4..9fb3b085af8 100644 --- a/addons/zeus/functions/fnc_moduleBurn.sqf +++ b/addons/zeus/functions/fnc_moduleBurn.sqf @@ -17,21 +17,18 @@ params ["_logic"]; -if !(local _logic) exitWith {}; +if (!local _logic) exitWith {}; private _unit = attachedTo _logic; deleteVehicle _logic; switch (false) do { - case !(isNull _unit): { + case (!isNull _unit): { [LSTRING(NothingSelected)] call FUNC(showMessage); }; - case (_unit isKindOf "CAManBase"): { + case (_unit isKindOf "CAManBase" && {getNumber (configOf _unit >> "isPlayableLogic") == 0}): { [LSTRING(OnlyInfantry)] call FUNC(showMessage); }; - case (alive _unit): { - [LSTRING(OnlyAlive)] call FUNC(showMessage); - }; case (["ace_fire"] call EFUNC(common,isModLoaded)): { [LSTRING(RequiresAddon)] call FUNC(showMessage); }; From 2bf85c07419b8065f5db65111e96390e414ba34c Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:44:40 +0200 Subject: [PATCH 11/27] Medical damage fix for dead units, cleanup --- addons/fire/XEH_postInit.sqf | 4 ++-- addons/fire/functions/fnc_burnReaction.sqf | 5 +++-- addons/fire/functions/fnc_burnSimulation.sqf | 22 +++++++++++-------- addons/fire/functions/fnc_fireManagerPFH.sqf | 2 +- addons/fire/functions/fnc_medical_success.sqf | 18 ++++++++------- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index bfcecf80bf8..ed808d6946a 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -60,7 +60,7 @@ if (!isServer) exitWith {}; private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_2("Unsupported key type used: %1 - %2 - %3",_key,typeName _key); + ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); }; // To avoid issues, remove existing entries first before overwriting @@ -77,7 +77,7 @@ if (!isServer) exitWith {}; private _hashedKey = hashValue _key; if (isNil "_hashedKey") exitWith { - ERROR_2("Unsupported key type used: %1 - %2 - %3",_key,typeName _key); + ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); }; (GVAR(fireSources) deleteAt _hashedKey) params [["_fireLogic", objNull]]; diff --git a/addons/fire/functions/fnc_burnReaction.sqf b/addons/fire/functions/fnc_burnReaction.sqf index 3138a31cc23..5a9b75d48c0 100644 --- a/addons/fire/functions/fnc_burnReaction.sqf +++ b/addons/fire/functions/fnc_burnReaction.sqf @@ -16,8 +16,9 @@ params ["_unit"]; if ( GVAR(dropWeapon) > 0 && - {isNull objectParent _unit && {(currentWeapon _unit) != ""}} && - {!isPlayer _unit || GVAR(dropWeapon) >= 2} + {isNull objectParent _unit} && + {(currentWeapon _unit) != ""} && + {!isPlayer _unit || GVAR(dropWeapon) == 2} ) then { _unit call EFUNC(common,throwWeapon); }; diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index e48fa38ec42..ff64c3ffb24 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -67,8 +67,8 @@ params ["_unit", "_instigator"]; _distancePercent = 1 - ((_unit distance _x) / BURN_PROPAGATE_DISTANCE); _adjustedIntensity = _intensity * _distancePercent; - // Don't burn if intensity is too low - if (BURN_MIN_INTENSITY > _adjustedIntensity) then { + // Don't burn if intensity is too low or already burning with higher intensity + if (BURN_MIN_INTENSITY > _adjustedIntensity || {(_x getVariable [QGVAR(intensity), 0]) > _adjustedIntensity}) then { continue; }; @@ -138,15 +138,19 @@ params ["_unit", "_instigator"]; _unit call FUNC(burnReaction); }; + if (!isNull _instigator) then { + _unit setVariable [QEGVAR(medical,lastDamageSource), _instigator]; + _unit setVariable [QEGVAR(medical,lastInstigator), _instigator]; + }; + // Common burn areas are the hands and face https://www.ncbi.nlm.nih.gov/pubmed/16899341/ - private _woundSelection = ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] selectRandomWeighted [0.77, 0.5, 0.8, 0.8, 0.3, 0.3]; + private _bodyPart = ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] selectRandomWeighted [0.77, 0.5, 0.8, 0.8, 0.3, 0.3]; - if (GET_PAIN_PERCEIVED(_unit) < (PAIN_UNCONSCIOUS + random 0.2)) then { - // Keep pain around unconciousness limit to allow for more fun interactions - [_unit, _intensity / BURN_MAX_INTENSITY, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); - } else { - [_unit, 0.15, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); - }; + // Keep pain around unconciousness limit to allow for more fun interactions + private _damageToAdd = [0.15, _intensity / BURN_MAX_INTENSITY] select (!alive _unit || {GET_PAIN_PERCEIVED(_unit) < (PAIN_UNCONSCIOUS + random 0.2)}); + + // Use event directly, as ace_medical_fnc_addDamageToUnit requires unit to be alive + [QEGVAR(medical,woundReceived), [_unit, [[_damageToAdd, _bodyPart, _damageToAdd]], _instigator, "burn"]] call CBA_fnc_localEvent; _unit setVariable [QGVAR(intensity), _intensity, true]; // globally sync intensity across all clients to make sure simulation is deterministic }; diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf index eb59faef724..540caa7de76 100644 --- a/addons/fire/functions/fnc_fireManagerPFH.sqf +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: tcvm + * Author: tcvm, johnb43 * Handles various objects on fire and determines if units close to objects deserve to get burned. * * Arguments: diff --git a/addons/fire/functions/fnc_medical_success.sqf b/addons/fire/functions/fnc_medical_success.sqf index a84aab56444..ed4b8cb3262 100644 --- a/addons/fire/functions/fnc_medical_success.sqf +++ b/addons/fire/functions/fnc_medical_success.sqf @@ -2,6 +2,7 @@ /* * Author: tcvm * Decreases burning intensity on successful medical action. + * The medical action is looped until the user stops the interaction or the unit is no longer burning. * * Arguments: * 0: Medic @@ -25,15 +26,16 @@ _intensity = _intensity * INTENSITY_DECREASE_MULT_PAT_DOWN; _patient setVariable [QGVAR(intensity), _intensity, true]; -if (_intensity > BURN_MIN_INTENSITY) then { - TRACE_1("patient still burning, looping",_this); +// If the unit is still burning, loop the medical action +if !(_patient call FUNC(isBurning)) exitWith {}; - if (EGVAR(medical_gui,pendingReopen)) then { - TRACE_1("temporarily blocking medical menu reopen",_this); +TRACE_1("patient still burning, looping",_this); - EGVAR(medical_gui,pendingReopen) = false; - [{EGVAR(medical_gui,pendingReopen) = true}] call CBA_fnc_execNextFrame; - }; +if (EGVAR(medical_gui,pendingReopen)) then { + TRACE_1("temporarily blocking medical menu reopen",_this); - [_medic, _patient, _bodyPart, _classname] call EFUNC(medical_treatment,treatment); + EGVAR(medical_gui,pendingReopen) = false; + [{EGVAR(medical_gui,pendingReopen) = true}] call CBA_fnc_execNextFrame; }; + +[_medic, _patient, _bodyPart, _classname] call EFUNC(medical_treatment,treatment); From 46e58177dba03fad0fdf78db85ef090ec8d3f4e8 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 20 Apr 2024 17:39:25 +0200 Subject: [PATCH 12/27] Make wrecks cause fire damage --- addons/fire/XEH_postInit.sqf | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index ed808d6946a..3dcff3b07c6 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -14,13 +14,29 @@ }; }] call CBA_fnc_addEventHandler; -if (!isServer) exitWith {}; - ["CBA_settingsInitialized", { TRACE_1("settingsInit",GVAR(enabled)); if (!GVAR(enabled)) exitWith {}; + // Make burning wrecks into fire sources + ["AllVehicles", "Killed", { + params ["_vehicle", "", "", "_useEffects"]; + + if (_useEffects) then { + [QGVAR(addFireSource), [ + _vehicle, + (boundingBoxReal [_vehicle, "FireGeometry"]) select 2, + BURN_MAX_INTENSITY, + QGVAR(wreck) + hashValue _vehicle, + {!isNull _this && {_this getEntityInfo 13}}, + _vehicle + ]] call CBA_fnc_serverEvent; + }; + }, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; + + if (!isServer) exitWith {}; + GVAR(fireSources) = createHashMap; [QGVAR(addFireSource), { From 4b3d28338c761cb11f42d86b3f1d1155b6aa2de2 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 26 May 2024 10:04:03 +0200 Subject: [PATCH 13/27] Update XEH_PREP.hpp --- addons/fire/XEH_PREP.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/XEH_PREP.hpp b/addons/fire/XEH_PREP.hpp index efc48a1f23a..a352cdf2aaf 100644 --- a/addons/fire/XEH_PREP.hpp +++ b/addons/fire/XEH_PREP.hpp @@ -5,6 +5,6 @@ PREP(burnReaction); PREP(burnSimulation); PREP(fireManagerPFH); PREP(isBurning); +PREP(medical_canPatDown); PREP(medical_progress); PREP(medical_success); -PREP(medical_canPatDown); From 9546ca2963165320e1a5deb5980537de21e29289 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 26 May 2024 10:08:10 +0200 Subject: [PATCH 14/27] Update fnc_cookOffEffect.sqf --- addons/cookoff/functions/fnc_cookOffEffect.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_cookOffEffect.sqf b/addons/cookoff/functions/fnc_cookOffEffect.sqf index c755fc6fbb6..44282f2f6b8 100644 --- a/addons/cookoff/functions/fnc_cookOffEffect.sqf +++ b/addons/cookoff/functions/fnc_cookOffEffect.sqf @@ -38,7 +38,7 @@ if (isServer) then { }; if (_ring) then { - private _intensity = 20; + private _intensity = 6; private _radius = 1.5 * ((boundingBoxReal _obj) select 2); [QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, format [QGVAR(%1), hashValue _obj]]] call CBA_fnc_localEvent; }; From 48f3d192e2b45c435797b6c032b4837e8aac25f5 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:00:38 +0200 Subject: [PATCH 15/27] Update compats --- .../compat_sog/functions/fnc_woundsHandlerIncendiary.sqf | 8 ++------ .../compat_spe/functions/fnc_woundsHandlerIncendiary.sqf | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/addons/compat_sog/functions/fnc_woundsHandlerIncendiary.sqf b/addons/compat_sog/functions/fnc_woundsHandlerIncendiary.sqf index 75ee243f082..6d3b7a86783 100644 --- a/addons/compat_sog/functions/fnc_woundsHandlerIncendiary.sqf +++ b/addons/compat_sog/functions/fnc_woundsHandlerIncendiary.sqf @@ -18,8 +18,6 @@ * Public: No */ -#define BURN_THRESHOLD 1 - params ["_unit", "_damages"]; TRACE_2("woundsHandlerIncendiary",_unit,_damages); @@ -32,9 +30,7 @@ private _fireDamage = 0; private _intensity = linearConversion [0, 20, _fireDamage, 0, 10, true]; TRACE_2("",_intensity,_fireDamage); -if (_intensity > BURN_THRESHOLD) then { - TRACE_2("Setting unit ablaze",_intensity,BURN_THRESHOLD); - ["ace_fire_burn", [_unit, _intensity]] call CBA_fnc_globalEvent; -}; +// Let fire handle if unit is set ablaze or not +[QEGVAR(fire,burn), [_unit, _intensity]] call CBA_fnc_localEvent; _this // return diff --git a/addons/compat_spe/functions/fnc_woundsHandlerIncendiary.sqf b/addons/compat_spe/functions/fnc_woundsHandlerIncendiary.sqf index aa282e9be84..d2b0cb165c8 100644 --- a/addons/compat_spe/functions/fnc_woundsHandlerIncendiary.sqf +++ b/addons/compat_spe/functions/fnc_woundsHandlerIncendiary.sqf @@ -18,8 +18,6 @@ * Public: No */ -#define BURN_THRESHOLD 1 - params ["_unit", "_damages"]; TRACE_2("woundsHandlerIncendiary",_unit,_damages); @@ -32,9 +30,7 @@ private _fireDamage = 0; private _intensity = linearConversion [0, 20, _fireDamage, 0, 10, true]; TRACE_2("",_intensity,_fireDamage); -if (_intensity > BURN_THRESHOLD) then { - TRACE_2("Setting unit ablaze",_intensity,BURN_THRESHOLD); - ["ace_fire_burn", [_unit, _intensity]] call CBA_fnc_globalEvent; -}; +// Let fire handle if unit is set ablaze or not +[QEGVAR(fire,burn), [_unit, _intensity]] call CBA_fnc_localEvent; _this // return From a93c0b46a33a2083c3ae4fc14572e1e68c7c7349 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:19:28 +0200 Subject: [PATCH 16/27] Added TRACE macros --- addons/fire/functions/fnc_burn.sqf | 25 +++++++++++++++---- addons/fire/functions/fnc_burnSimulation.sqf | 12 +++++++++ addons/fire/functions/fnc_medical_success.sqf | 4 ++- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index defc822c54e..cd8bad71d4a 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -24,28 +24,43 @@ if (!EGVAR(common,settingsInitFinished)) exitWith { if (!GVAR(enabled)) exitWith {}; params ["_unit", "_intensity", ["_instigator", objNull]]; +TRACE_3("burn",_unit,_intensity,_instigator); -if (BURN_MIN_INTENSITY > _intensity) exitWith {}; +if (BURN_MIN_INTENSITY > _intensity) exitWith { + TRACE_3("intensity is too low",_unit,_intensity,BURN_MIN_INTENSITY); +}; // Check if unit is remote (objNull is remote) -if (!local _unit) exitWith {}; +if (!local _unit) exitWith { + TRACE_1("unit is null or not local",_unit); +}; // Check if the unit can burn (takes care of spectators and curators) -if (getNumber (configOf _unit >> "isPlayableLogic") == 1 || {!(_unit isKindOf "CAManBase")}) exitWith {}; +if (getNumber (configOf _unit >> "isPlayableLogic") == 1 || {!(_unit isKindOf "CAManBase")}) exitWith { + TRACE_1("unit is virtual or not a man",_unit); +}; // If unit is invulnerable, don't burn the unit -if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith {}; +if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith { + TRACE_1("unit is invulnerable",_unit); +}; private _eyePos = eyePos _unit; // Check if unit is mostly submerged in water -if (surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}) exitWith {}; +if (surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}) exitWith { + TRACE_1("unit is in water",_unit); +}; // If unit is already burning, update intensity, but don't add another PFH if (_unit call FUNC(isBurning)) exitWith { + TRACE_2("unit already burning, updating intensity",_unit,_intensity); + _unit setVariable [QGVAR(intensity), _intensity, true]; }; +TRACE_2("setting unit ablaze",_unit,_intensity); + _unit setVariable [QGVAR(intensity), _intensity, true]; // Fire simulation (objects are handled differently) diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index ff64c3ffb24..908ccb5ee0e 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -24,11 +24,15 @@ params ["_unit", "_instigator"]; _args params ["_unit", "_instigator"]; if (isNull _unit) exitWith { + TRACE_1("unit is null",_unit); + _pfhID call CBA_fnc_removePerFrameHandler; }; // Locality has changed if (!local _unit) exitWith { + TRACE_1("unit is no longer local",_unit); + _pfhID call CBA_fnc_removePerFrameHandler; [QGVAR(burnSimulation), [_unit, _instigator], _unit] call CBA_fnc_targetEvent; @@ -40,6 +44,8 @@ params ["_unit", "_instigator"]; {!(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]})} || {private _eyePos = eyePos _unit; surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}} ) exitWith { + TRACE_3("unit is no longer burning, invulnerable or in water",_unit,_unit call FUNC(isBurning),isDamageAllowed _unit && {_unit getVariable [ARR_2(QEGVAR(medical,allowDamage),true)]}); + // Remove global effects (_unit getVariable [QGVAR(jipID), ""]) call CBA_fnc_removeGlobalEventJIP; @@ -61,6 +67,8 @@ params ["_unit", "_instigator"]; // Propagate fire to other units (alive or dead) if it's intense if (_intensity >= BURN_THRESHOLD_INTENSE) then { + TRACE_2("check for other units",_unit,_intensity); + private _adjustedIntensity = 0; { @@ -73,11 +81,15 @@ params ["_unit", "_instigator"]; }; [QGVAR(burn), [_x, _adjustedIntensity, _instigator], _x] call CBA_fnc_targetEvent; + + TRACE_3("propagate fire",_x,_intensity,_adjustedIntensity); } forEach nearestObjects [_unit, ["CAManBase"], BURN_PROPAGATE_DISTANCE]; }; // Update intensity/fire reactions if (CBA_missionTime >= _unit getVariable [QGVAR(intensityUpdate), 0]) then { + TRACE_2("update intensity",_unit,_intensity); + _unit setVariable [QGVAR(intensityUpdate), CBA_missionTime + INTENSITY_UPDATE]; _intensity = _intensity - INTENSITY_LOSS - (rain / 10); diff --git a/addons/fire/functions/fnc_medical_success.sqf b/addons/fire/functions/fnc_medical_success.sqf index ed4b8cb3262..ca569e1280e 100644 --- a/addons/fire/functions/fnc_medical_success.sqf +++ b/addons/fire/functions/fnc_medical_success.sqf @@ -27,7 +27,9 @@ _intensity = _intensity * INTENSITY_DECREASE_MULT_PAT_DOWN; _patient setVariable [QGVAR(intensity), _intensity, true]; // If the unit is still burning, loop the medical action -if !(_patient call FUNC(isBurning)) exitWith {}; +if !(_patient call FUNC(isBurning)) exitWith { + TRACE_1("patient no longer burning, quitting",_this); +}; TRACE_1("patient still burning, looping",_this); From 0f24464658276ab71e79cee1f7cb18173fbfed83 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:21:29 +0200 Subject: [PATCH 17/27] Minor tweaks --- addons/fire/XEH_postInit.sqf | 14 +++++++------- addons/fire/functions/fnc_fireManagerPFH.sqf | 7 ++++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index ed808d6946a..8943db89c01 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -42,6 +42,13 @@ if (!isServer) exitWith {}; if (_radius == 0 || _intensity == 0) exitWith {}; if (_key isEqualTo "") exitWith {}; // key can be many types + // hashValue supports more types than hashmaps do by default, but not all (e.g. locations) + private _hashedKey = hashValue _key; + + if (isNil "_hashedKey") exitWith { + ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); + }; + // If a position is passed, create a static object at said position private _sourcePos = if (_isObject) then { getPosATL _source @@ -56,13 +63,6 @@ if (!isServer) exitWith {}; _fireLogic attachTo [_source]; }; - // hashValue supports more types than hashmaps do by default, but not all (e.g. locations) - private _hashedKey = hashValue _key; - - if (isNil "_hashedKey") exitWith { - ERROR_2("Unsupported key type used: %1 - %2",_key,typeName _key); - }; - // To avoid issues, remove existing entries first before overwriting if (_hashedKey in GVAR(fireSources)) then { [QGVAR(removeFireSource), _key] call CBA_fnc_localEvent; diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf index 540caa7de76..4cdc61a7ac6 100644 --- a/addons/fire/functions/fnc_fireManagerPFH.sqf +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -20,14 +20,17 @@ private _adjustedIntensity = 0; { _y params ["_fireLogic", "_radius", "_intensity", "_condition", "_conditionArgs"]; + TRACE_2("fireManagerPFH loop",_x,_y); // Remove when condition is no longer valid if !(_conditionArgs call _condition) then { - (GVAR(fireSources) deleteAt _x) params [["_fireLogic", objNull]]; + TRACE_2("condition no longer valid, deleting",_x,_y); detach _fireLogic; deleteVehicle _fireLogic; + GVAR(fireSources) deleteAt _x; + continue; }; @@ -42,5 +45,7 @@ private _adjustedIntensity = 0; }; [QGVAR(burn), [_x, _adjustedIntensity], _x] call CBA_fnc_targetEvent; + + TRACE_3("propagate fire",_x,_intensity,_adjustedIntensity); } forEach nearestObjects [_fireLogic, ["CAManBase"], _radius]; } forEach GVAR(fireSources); From 94acbf2dc9825b612278e8b6dab97a5e5709ab47 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:23:45 +0200 Subject: [PATCH 18/27] Update initSettings.inc.sqf --- addons/fire/initSettings.inc.sqf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/fire/initSettings.inc.sqf b/addons/fire/initSettings.inc.sqf index 431998ffd95..09cfcec5f0f 100644 --- a/addons/fire/initSettings.inc.sqf +++ b/addons/fire/initSettings.inc.sqf @@ -15,8 +15,7 @@ [LSTRING(Setting_FlareEnable), LSTRING(Setting_FlareDescription)], LSTRING(Category_DisplayName), false, - 1, - {[QGVAR(flareEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)} + 1 ] call CBA_fnc_addSetting; [ From de652d538239e8a08f7becfab9e5213e79bbf5ff Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:54:38 +0200 Subject: [PATCH 19/27] Update comment to bring up to standard --- addons/fire/initSettings.inc.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/initSettings.inc.sqf b/addons/fire/initSettings.inc.sqf index 09cfcec5f0f..edcd51a8a7e 100644 --- a/addons/fire/initSettings.inc.sqf +++ b/addons/fire/initSettings.inc.sqf @@ -6,7 +6,7 @@ true, 1, {[QGVAR(fireEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, - true // needs mission restart + true // Needs mission restart ] call CBA_fnc_addSetting; [ From 8c3dacc74ce5a9f78a6e59c8535e9b43f76563df Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:24:38 +0200 Subject: [PATCH 20/27] Update fnc_cookOffServer.sqf --- addons/cookoff/functions/fnc_cookOffServer.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/cookoff/functions/fnc_cookOffServer.sqf b/addons/cookoff/functions/fnc_cookOffServer.sqf index 303555ba28b..05111d7e694 100644 --- a/addons/cookoff/functions/fnc_cookOffServer.sqf +++ b/addons/cookoff/functions/fnc_cookOffServer.sqf @@ -175,7 +175,7 @@ if (_delayBetweenSmokeAndFire) then { 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; + [QEGVAR(fire,burn), [_x, _intensity * 1.5, _instigator], _x] call CBA_fnc_targetEvent; } forEach (crew _vehicle); }; From 209d3ff1b8ef5c253a3c37be3eea11f36f29de85 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:00:57 +0200 Subject: [PATCH 21/27] Update XEH_postInit.sqf --- addons/fire/XEH_postInit.sqf | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 8943db89c01..5b02624bbe9 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -2,7 +2,6 @@ [QGVAR(burn), LINKFUNC(burn)] call CBA_fnc_addEventHandler; [QGVAR(burnEffects), LINKFUNC(burnEffects)] call CBA_fnc_addEventHandler; -[QGVAR(burnObjectEffects), LINKFUNC(burnObjectEffects)] call CBA_fnc_addEventHandler; [QGVAR(burnSimulation), LINKFUNC(burnSimulation)] call CBA_fnc_addEventHandler; [QGVAR(playScream), { From a4968b52d7b088db04b2366a04feeeafa23f3164 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:21:17 +0200 Subject: [PATCH 22/27] Minor tweaks and cleanup --- addons/fire/functions/fnc_burn.sqf | 11 ++++++++--- addons/fire/functions/fnc_burnEffects.sqf | 4 ++-- addons/fire/functions/fnc_burnSimulation.sqf | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf index cd8bad71d4a..1cf0fc67592 100644 --- a/addons/fire/functions/fnc_burn.sqf +++ b/addons/fire/functions/fnc_burn.sqf @@ -5,8 +5,8 @@ * * Arguments: * 0: Unit - * 1: Intensity of fire - * 2: Instigator of fire (default: objNull) + * 1: Fire intensity + * 2: Fire instigator (default: objNull) * * Return Value: * None @@ -54,6 +54,11 @@ if (surfaceIsWater _eyePos && {(_eyePos select 2) < 0.1}) exitWith { // If unit is already burning, update intensity, but don't add another PFH if (_unit call FUNC(isBurning)) exitWith { + // Only allow intensity to be increased + if (_intensity <= (_unit getVariable [QGVAR(intensity), 0])) exitWith { + TRACE_2("unit already burning, no intensity update",_unit,_intensity); + }; + TRACE_2("unit already burning, updating intensity",_unit,_intensity); _unit setVariable [QGVAR(intensity), _intensity, true]; @@ -63,7 +68,7 @@ TRACE_2("setting unit ablaze",_unit,_intensity); _unit setVariable [QGVAR(intensity), _intensity, true]; -// Fire simulation (objects are handled differently) +// Fire simulation (fire sources are handled differently) [QGVAR(burnSimulation), [_unit, _instigator], _unit] call CBA_fnc_targetEvent; // Spawn effects for unit diff --git a/addons/fire/functions/fnc_burnEffects.sqf b/addons/fire/functions/fnc_burnEffects.sqf index da690207216..4dadda8526c 100644 --- a/addons/fire/functions/fnc_burnEffects.sqf +++ b/addons/fire/functions/fnc_burnEffects.sqf @@ -76,7 +76,7 @@ if (isServer) then { }; // Display burn indicators - if (_unit == ACE_player && {alive _unit} && {isNil {_unit getVariable QGVAR(burnUIPFH)}}) then { // this accounts for player remote controlled a new unit + if (_unit == ACE_player && {alive _unit} && {isNil {_unit getVariable QGVAR(burnUIPFH)}}) then { // This accounts for player remote controlled a new unit private _burnIndicatorPFH = [LINKFUNC(burnIndicator), 1, _unit] call CBA_fnc_addPerFrameHandler; _unit setVariable [QGVAR(burnUIPFH), _burnIndicatorPFH]; }; @@ -120,7 +120,7 @@ if (isServer) then { _fireParticle setParticleRandom [ 0.04 * _intensity, // life time [0.05, 0.05, 2], // position - [0.05 * _intensity, 0.05 * _intensity, 0.05 * _intensity], // move velocity + [0.05, 0.05, 0.05] vectorMultiply _intensity, // move velocity 0, // rotation velocity 0.06 * _intensity, // size [0, 0, 0, 0], // color diff --git a/addons/fire/functions/fnc_burnSimulation.sqf b/addons/fire/functions/fnc_burnSimulation.sqf index 908ccb5ee0e..8a1dddfc151 100644 --- a/addons/fire/functions/fnc_burnSimulation.sqf +++ b/addons/fire/functions/fnc_burnSimulation.sqf @@ -164,6 +164,6 @@ params ["_unit", "_instigator"]; // Use event directly, as ace_medical_fnc_addDamageToUnit requires unit to be alive [QEGVAR(medical,woundReceived), [_unit, [[_damageToAdd, _bodyPart, _damageToAdd]], _instigator, "burn"]] call CBA_fnc_localEvent; - _unit setVariable [QGVAR(intensity), _intensity, true]; // globally sync intensity across all clients to make sure simulation is deterministic + _unit setVariable [QGVAR(intensity), _intensity, true]; // Globally sync intensity across all clients to make sure simulation is deterministic }; }, BURN_PROPAGATE_UPDATE, [_unit, _instigator]] call CBA_fnc_addPerFrameHandler; From 5aeb44c1a6c06f1308b21def4787aa07a110fcdf Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 11 Aug 2024 16:42:48 +0200 Subject: [PATCH 23/27] Update XEH_postInit.sqf --- addons/fire/XEH_postInit.sqf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 1050d757538..6037600e2ce 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -9,6 +9,22 @@ [QGVAR(burnEffects), LINKFUNC(burnEffects)] call CBA_fnc_addEventHandler; [QGVAR(burnSimulation), LINKFUNC(burnSimulation)] call CBA_fnc_addEventHandler; + // Make burning wrecks into fire sources + ["AllVehicles", "Killed", { + params ["_vehicle", "", "", "_useEffects"]; + + if (_useEffects) then { + [QGVAR(addFireSource), [ + _vehicle, + (boundingBoxReal [_vehicle, "FireGeometry"]) select 2, + BURN_MAX_INTENSITY, + QGVAR(wreck) + hashValue _vehicle, + {!isNull _this && {_this getEntityInfo 13}}, + _vehicle + ]] call CBA_fnc_serverEvent; + }; + }, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; + [QGVAR(playScream), { params ["_scream", "_source"]; From 401b5d144f2009f5a6130e390dcb526d193cdbc4 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 16 Nov 2024 02:28:53 -0800 Subject: [PATCH 24/27] Update addons/fire/XEH_postInit.sqf Co-authored-by: PabstMirror --- addons/fire/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 6037600e2ce..b1833a644d9 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -23,7 +23,7 @@ _vehicle ]] call CBA_fnc_serverEvent; }; - }, true, ["CAManBase", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; + }, true, ["Man", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; [QGVAR(playScream), { params ["_scream", "_source"]; From c9c5a98fa2b10e22d081698c66a2ea6300b4abcb Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 16 Nov 2024 02:29:35 -0800 Subject: [PATCH 25/27] Update addons/fire/XEH_postInit.sqf Co-authored-by: PabstMirror --- addons/fire/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index b1833a644d9..999b273b96e 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -13,7 +13,7 @@ ["AllVehicles", "Killed", { params ["_vehicle", "", "", "_useEffects"]; - if (_useEffects) then { + if (_useEffects && {!isNull _vehicle} && {_vehicle getEntityInfo 13}) then { [QGVAR(addFireSource), [ _vehicle, (boundingBoxReal [_vehicle, "FireGeometry"]) select 2, From 0bb80ab3605674ed693d6824b24e03815cae50c8 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 16 Nov 2024 11:52:25 +0100 Subject: [PATCH 26/27] Update XEH_postInit.sqf --- addons/fire/XEH_postInit.sqf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index 999b273b96e..b9ed257557b 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -13,17 +13,17 @@ ["AllVehicles", "Killed", { params ["_vehicle", "", "", "_useEffects"]; - if (_useEffects && {!isNull _vehicle} && {_vehicle getEntityInfo 13}) then { + if (_useEffects && {_vehicle getEntityInfo 13}) then { [QGVAR(addFireSource), [ _vehicle, (boundingBoxReal [_vehicle, "FireGeometry"]) select 2, BURN_MAX_INTENSITY, QGVAR(wreck) + hashValue _vehicle, - {!isNull _this && {_this getEntityInfo 13}}, + {_this getEntityInfo 13}, _vehicle ]] call CBA_fnc_serverEvent; }; - }, true, ["Man", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; + }, true, ["Man", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; // Use "Man" to excluded animals as well [QGVAR(playScream), { params ["_scream", "_source"]; From c56ccc540fbe3484eaaaedecaa9ba037c9c0ff27 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sat, 16 Nov 2024 11:40:20 -0800 Subject: [PATCH 27/27] Update addons/fire/XEH_postInit.sqf --- addons/fire/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf index b9ed257557b..ed9b1b62523 100644 --- a/addons/fire/XEH_postInit.sqf +++ b/addons/fire/XEH_postInit.sqf @@ -23,7 +23,7 @@ _vehicle ]] call CBA_fnc_serverEvent; }; - }, true, ["Man", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; // Use "Man" to excluded animals as well + }, true, ["Man", "StaticWeapon"], true] call CBA_fnc_addClassEventHandler; // Use "Man" to exclude animals as well [QGVAR(playScream), { params ["_scream", "_source"];