diff --git a/addons/fire/$PBOPREFIX$ b/addons/fire/$PBOPREFIX$ new file mode 100644 index 00000000000..ec282b453b6 --- /dev/null +++ b/addons/fire/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\fire diff --git a/addons/fire/ACE_Medical_Treatment_Actions.hpp b/addons/fire/ACE_Medical_Treatment_Actions.hpp new file mode 100644 index 00000000000..434a794fa70 --- /dev/null +++ b/addons/fire/ACE_Medical_Treatment_Actions.hpp @@ -0,0 +1,20 @@ +class EGVAR(medical_treatment,actions) { + class BasicBandage; + class PatDown: BasicBandage { + displayName = CSTRING(Actions_PatDown); + displayNameProgress = CSTRING(Actions_PerformingPatDown); + icon = ""; + category = "advanced"; + treatmentLocations = 0; + allowedSelections[] = {"All"}; + allowSelfTreatment = 1; + medicRequired = 0; + treatmentTime = 5; + items[] = {}; + condition = QFUNC(medical_canPatDown); + callbackSuccess = QFUNC(medical_success); + callbackProgress = QFUNC(medical_progress); + consumeItem = 0; + litter[] = {}; + }; +}; diff --git a/addons/fire/CfgEventHandlers.hpp b/addons/fire/CfgEventHandlers.hpp new file mode 100644 index 00000000000..0d3301d6e0a --- /dev/null +++ b/addons/fire/CfgEventHandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preStart)); + }; +}; + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_postInit)); + }; +}; diff --git a/addons/fire/CfgSounds.hpp b/addons/fire/CfgSounds.hpp new file mode 100644 index 00000000000..c4b821144ae --- /dev/null +++ b/addons/fire/CfgSounds.hpp @@ -0,0 +1,26 @@ +// 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)), db + 8, 1};\ + titles[] = {}; \ +} + +class CfgSounds { + CREATE_SCREAM(1); + CREATE_SCREAM(2); + CREATE_SCREAM(3); + CREATE_SCREAM(4); + CREATE_SCREAM(5); + CREATE_SCREAM(6); + CREATE_SCREAM(7); + CREATE_SCREAM(8); + CREATE_SCREAM(9); + CREATE_SCREAM(10); + CREATE_SCREAM(11); + CREATE_SCREAM(12); + CREATE_SCREAM(13); + CREATE_SCREAM(14); + CREATE_SCREAM(15); +}; diff --git a/addons/fire/RscTitles.hpp b/addons/fire/RscTitles.hpp new file mode 100644 index 00000000000..3ccb8c349f1 --- /dev/null +++ b/addons/fire/RscTitles.hpp @@ -0,0 +1,41 @@ +class RscTitles { + class RscPicture; + class GVAR(onFire1) { + idd = -1; + movingEnable = "true"; + duration = 0.1; + fadein = 0.15; + fadeout = 0.75; + name = QGVAR(onFire1); + onload = QUOTE(with uiNamespace do {GVAR(onFireIndicator1) = _this select 0}); + + class controls { + class GVAR(indicator): RscPicture { + idc = -1; + type = 0; + style = 48; + colorBackground[] = {0, 0, 0, 0}; + colorText[] = {0.9, 0.9, 0.9, 0.6}; + font = "LucidaConsoleB"; + sizeEx = 0.023; + x = "SafeZoneX"; + y = "SafeZoneY"; + w = "SafeZoneW + 0.05"; + h = "SafeZoneH + 0.05"; + text = PATHTOF(data\overlay_burn_1.paa); + }; + }; + }; + + class GVAR(onFire2): GVAR(onFire1) { + idd = -1; + name = QGVAR(onFire2); + onload = QUOTE(with uiNamespace do {GVAR(onFireIndicator2) = _this select 0}); + + class controls: controls { + class GVAR(indicator): GVAR(indicator) { + text = PATHTOF(data\overlay_burn_2.paa); + }; + }; + }; +}; diff --git a/addons/fire/XEH_PREP.hpp b/addons/fire/XEH_PREP.hpp new file mode 100644 index 00000000000..511c9c0bb68 --- /dev/null +++ b/addons/fire/XEH_PREP.hpp @@ -0,0 +1,9 @@ +PREP(burn); +PREP(isBurning); +PREP(isPlant); +PREP(burnIndicator); +PREP(fireManagerPFH); + +PREP(medical_progress); +PREP(medical_success); +PREP(medical_canPatDown); diff --git a/addons/fire/XEH_postInit.sqf b/addons/fire/XEH_postInit.sqf new file mode 100644 index 00000000000..f89a062eff1 --- /dev/null +++ b/addons/fire/XEH_postInit.sqf @@ -0,0 +1,34 @@ +#include "script_component.hpp" + +[QGVAR(burn), FUNC(burn)] call CBA_fnc_addEventHandler; +[QGVAR(playScream), { + params ["_scream", "_source"]; + _source say3D _scream; +}] call CBA_fnc_addEventHandler; + +["ace_settingsInitialized", { + TRACE_1("settingsInit", GVAR(enabled)); + if (!GVAR(enabled)) exitWith {}; + + if (isServer) then { + [QGVAR(addFireSource), { + 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; + }] 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; diff --git a/addons/fire/XEH_preInit.sqf b/addons/fire/XEH_preInit.sqf new file mode 100644 index 00000000000..e69c1159273 --- /dev/null +++ b/addons/fire/XEH_preInit.sqf @@ -0,0 +1,13 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +#include "initSettings.sqf" + +GVAR(burningPlants) = []; + +ADDON = true; diff --git a/addons/fire/XEH_preStart.sqf b/addons/fire/XEH_preStart.sqf new file mode 100644 index 00000000000..022888575ed --- /dev/null +++ b/addons/fire/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/fire/config.cpp b/addons/fire/config.cpp new file mode 100644 index 00000000000..ad67f9beab6 --- /dev/null +++ b/addons/fire/config.cpp @@ -0,0 +1,20 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common", "ace_medical_engine"}; + author = ECSTRING(common,ACETeam); + authors[] = {"commy2", "Brandon (TCVM)"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "CfgSounds.hpp" +#include "ACE_Medical_Treatment_Actions.hpp" +#include "RscTitles.hpp" diff --git a/addons/fire/data/overlay_burn_1.paa b/addons/fire/data/overlay_burn_1.paa new file mode 100644 index 00000000000..d3871b4b7b7 Binary files /dev/null and b/addons/fire/data/overlay_burn_1.paa differ diff --git a/addons/fire/data/overlay_burn_2.paa b/addons/fire/data/overlay_burn_2.paa new file mode 100644 index 00000000000..7f87ec9458b Binary files /dev/null and b/addons/fire/data/overlay_burn_2.paa differ diff --git a/addons/fire/functions/fnc_burn.sqf b/addons/fire/functions/fnc_burn.sqf new file mode 100644 index 00000000000..e5208809669 --- /dev/null +++ b/addons/fire/functions/fnc_burn.sqf @@ -0,0 +1,348 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Makes object catch fire. Only call from events. Local effects only. + * Arbitrary values to ignite people. Assumed maximum is "10". + * + * Arguments: + * 0: Vehicle + * 1: Intensity of fire + * 2: Instigator of fire (default: objNull) + * + * Return Value: + * None + * + * Example: + * [player, 4] call ace_fire_fnc_burn + * + * 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 +#define MAX_INTENSITY 10 +#define MIN_INTENSITY 1 + +params ["_unit", "_intensity", ["_instigator", objNull]]; + +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 [MAX_INTENSITY, 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 isEqualTo 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 isEqualTo ace_player) }) then { + private _burnCounter = ace_player 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; + }; + ace_player 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, but if its too high this wont do anything substantial + _intensity = _intensity - (1 / _intensity); + }; + }; + + if ((_unit isEqualTo vehicle _unit) && { !(currentWeapon _unit isEqualTo "") }) then { + [_unit] call EFUNC(hitreactions,throwWeapon); + }; + + private _soundID = floor (1 + random 15); + private _sound = format [QGVAR(scream_%1), _soundID]; + [QGVAR(playScream), [_sound, _unit]] call CBA_fnc_globalEvent; + }; + + // 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 / MAX_INTENSITY, _woundSelection, "burn", _instigator] call EFUNC(medical,addDamageToUnit); + } else { + [_unit, 0.15, _woundSelection, "unknown", _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 isEqualTo 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], "destructionEffect1"]; + }; + + _unit setVariable [QGVAR(burning), true]; + _unit setVariable [QGVAR(intensity), _intensity]; + _unit setVariable [QGVAR(burnUIPFH), -1]; + + 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]; + }; + + private _soundID = floor (1 + random 15); + private _sound = format [QGVAR(scream_%1), _soundID]; + [QGVAR(playScream), [_sound, _unit]] call CBA_fnc_globalEvent; + }; + + _lastIntensityUpdate = 0; + _lastPropogateUpdate = 0; + + _isThisUnitAlive = true; +}, { + (_this getVariable "params") params ["_unit"]; + + // deinit function + deleteVehicle _fireParticle; + deleteVehicle _smokeParticle; + deleteVehicle _fireLight; + deleteVehicle _lightFlare; + deleteVehicle _fireSound; + + if (local _unit) then { + if (!isPlayer _unit) then { + _unit setUnitPos "AUTO"; + _unit setVariable [QGVAR(stopDropRoll), false]; + }; + }; + _unit setVariable [QGVAR(burning), false]; +}, { + // run condition + true +}, { + // exit condition + (_this getVariable "params") params ["_unit"]; + + private _unitAlive = (alive _unit) && { getNumber ((configOf _unit) >> "isPlayableLogic") != 1 }; + private _unitIsUnit = { (_unit != vehicle _unit) && { isNull vehicle _unit } }; + + !_unitAlive || _unitIsUnit || { _intensity <= MIN_INTENSITY } || { !([_unit] call FUNC(isBurning)) } +}, ["_intensity", "_fireParticle", "_smokeParticle", "_fireLight", "_fireSound", "_lightFlare", "_lastIntensityUpdate", "_lastPropogateUpdate", "_isThisUnitAlive"]] call CBA_fnc_createPerFrameHandlerObject; diff --git a/addons/fire/functions/fnc_burnIndicator.sqf b/addons/fire/functions/fnc_burnIndicator.sqf new file mode 100644 index 00000000000..d5c9de25f38 --- /dev/null +++ b/addons/fire/functions/fnc_burnIndicator.sqf @@ -0,0 +1,36 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Run once per second in a PFH. Update screen effects with burn indicator. + * + * Arguments: + * 0: Unit on fire + * 1: PFH Handle + * + * Return Value: + * None + * + * Example: + * [player, 4] 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 (!([_unit] call FUNC(isBurning)) || { !alive _unit }) then { + [_pfhHandle] call CBA_fnc_removePerFrameHandler; + _unit setVariable [QGVAR(burnUIPFH), -1]; +}; diff --git a/addons/fire/functions/fnc_fireManagerPFH.sqf b/addons/fire/functions/fnc_fireManagerPFH.sqf new file mode 100644 index 00000000000..8f750911904 --- /dev/null +++ b/addons/fire/functions/fnc_fireManagerPFH.sqf @@ -0,0 +1,43 @@ +#include "script_component.hpp" +/* + * Author: Brandon (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. + * + * Arguments: + * 0: Unit on fire + * 1: PFH Handle + * + * Return Value: + * None + * + * Example: + * [FUNC(fireManagerPFH), 0.25, [_unit]] call CBA_fnc_addPerFrameHandler + * + * Public: No + */ + +params ["_args", "_handle"]; + +[GVAR(fireSources), { + _value params ["", "", "", "_condition", "_conditionArgs"]; + _conditionArgs call _condition; +}] call CBA_fnc_hashFilter; + +[GVAR(fireSources), { + _value params ["_source", "_radius", "_intensity"]; + private _attachedObject = attachedTo _source; + private _sourcePos = getPosATL _source; + if !(_attachedObject isEqualTo objNull) then { + _sourcePos = getPosATL _attachedObject; + }; + + private _nearEntities = _sourcePos nearEntities ["Man", _radius]; + { + 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; + }; + } forEach _nearEntities; +}] call CBA_fnc_hashEachPair; diff --git a/addons/fire/functions/fnc_isBurning.sqf b/addons/fire/functions/fnc_isBurning.sqf new file mode 100644 index 00000000000..1e62f393097 --- /dev/null +++ b/addons/fire/functions/fnc_isBurning.sqf @@ -0,0 +1,23 @@ +#include "script_component.hpp" +/* + * Author: commy2 + * Check if object is burning. + * + * Arguments: + * 0: Vehicle + * + * Return Value: + * None + * + * Example: + * player call ace_fire_fnc_isBurning + * + * Public: Yes + */ + +params [["_unit", objNull, [objNull]]]; + +_unit getVariable [QGVAR(burning), false] || { + GVAR(burningPlants) = GVAR(burningPlants) select {!isNull _x}; + _unit in GVAR(burningPlants) +} diff --git a/addons/fire/functions/fnc_isPlant.sqf b/addons/fire/functions/fnc_isPlant.sqf new file mode 100644 index 00000000000..4fd982a7ced --- /dev/null +++ b/addons/fire/functions/fnc_isPlant.sqf @@ -0,0 +1,20 @@ +#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 new file mode 100644 index 00000000000..3bf959330f4 --- /dev/null +++ b/addons/fire/functions/fnc_medical_canPatDown.sqf @@ -0,0 +1,21 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Returns if unit can pat down fire or not. + * + * Arguments: + * 0: Medic (not used) + * 1: Patient + * + * Return Value: + * Can Pat-Down + * + * Example: + * [nil, player] call ace_fire_fnc_medical_canPatDown + * + * Public: No + */ + +params ["", "_patient"]; + +[_patient] call FUNC(isBurning) diff --git a/addons/fire/functions/fnc_medical_progress.sqf b/addons/fire/functions/fnc_medical_progress.sqf new file mode 100644 index 00000000000..fc78befea0c --- /dev/null +++ b/addons/fire/functions/fnc_medical_progress.sqf @@ -0,0 +1,23 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Checks if patient is still burning for medical progress to continue. + * + * Arguments: + * 0: Arguments + * 0: Medic + * 1: Patient + * + * Return Value: + * Continue pat down + * + * Example: + * [[player, cursorObject]] call ace_fire_fnc_medical_progress + * + * Public: No + */ + +params ["_args"]; +_args params ["_medic", "_patient"]; + +[_patient] call FUNC(isBurning) diff --git a/addons/fire/functions/fnc_medical_success.sqf b/addons/fire/functions/fnc_medical_success.sqf new file mode 100644 index 00000000000..8a37ebd76d6 --- /dev/null +++ b/addons/fire/functions/fnc_medical_success.sqf @@ -0,0 +1,23 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Decreases burning intensity on successful medical action. + * + * Arguments: + * 0: Medic + * 1: Patient + * + * Return Value: + * None + * + * Example: + * [player, cursorObject] call ace_fire_fnc_medical_success + * + * Public: No + */ + +params ["_medic", "_patient"]; + +private _intensity = _patient getVariable [QGVAR(intensity), 0]; +_intensity = _intensity * (4/5); +_patient setVariable [QGVAR(intensity), _intensity, true]; diff --git a/addons/fire/functions/script_component.hpp b/addons/fire/functions/script_component.hpp new file mode 100644 index 00000000000..782fabed762 --- /dev/null +++ b/addons/fire/functions/script_component.hpp @@ -0,0 +1 @@ +#include "\z\ace\addons\fire\script_component.hpp" diff --git a/addons/fire/initSettings.sqf b/addons/fire/initSettings.sqf new file mode 100644 index 00000000000..6919c35f10d --- /dev/null +++ b/addons/fire/initSettings.sqf @@ -0,0 +1,19 @@ +[ + QGVAR(enabled), "CHECKBOX", + ["STR_A3_OPTIONS_ENABLED", LSTRING(setting_description)], + LSTRING(category_displayName), + true, // default value + true, // isGlobal + {[QGVAR(fireEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_settings_fnc_init; + +[ + QGVAR(enableFlare), "CHECKBOX", + [LSTRING(setting_flareEnable), LSTRING(setting_flareDescription)], + LSTRING(category_displayName), + false, // default value + true, // isGlobal + {[QGVAR(flareEnabled), _this] call EFUNC(common,cbaSettings_settingChanged)}, + true // Needs mission restart +] call CBA_settings_fnc_init; diff --git a/addons/fire/script_component.hpp b/addons/fire/script_component.hpp new file mode 100644 index 00000000000..289e3d13f1d --- /dev/null +++ b/addons/fire/script_component.hpp @@ -0,0 +1,32 @@ +#define COMPONENT fire +#define COMPONENT_BEAUTIFIED Fire +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define CBA_DEBUG_SYNCHRONOUS +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_FIRE + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_FIRE + #define DEBUG_SETTINGS DEBUG_SETTINGS_FIRE +#endif + +#include "\z\ace\addons\main\script_macros.hpp" +#include "\z\ace\addons\medical_engine\script_macros_medical.hpp" + +#define FIRE_MANAGER_PFH_DELAY 0.25 +#define FLARE_SIZE_MODIFIER 5 +#define PRONE_ROLLING_ANIMS [\ + "amovppnemstpsnonwnondnon_amovppnemevasnonwnondl",\ + "amovppnemstpsnonwnondnon_amovppnemevasnonwnondr",\ + "amovppnemstpsraswrfldnon_amovppnemevaslowwrfldl",\ + "amovppnemstpsraswrfldnon_amovppnemevaslowwrfldr",\ + "amovppnemstpsraswpstdnon_amovppnemevaslowwpstdl",\ + "amovppnemstpsraswpstdnon_amovppnemevaslowwpstdr",\ + "amovppnemstpsoptwbindnon_amovppnemevasoptwbindl",\ + "amovppnemstpsoptwbindnon_amovppnemevasoptwbindr"\ +] diff --git a/addons/fire/sounds/scream1.ogg b/addons/fire/sounds/scream1.ogg new file mode 100644 index 00000000000..c705370958d Binary files /dev/null and b/addons/fire/sounds/scream1.ogg differ diff --git a/addons/fire/sounds/scream10.ogg b/addons/fire/sounds/scream10.ogg new file mode 100644 index 00000000000..1c42e762e1e Binary files /dev/null and b/addons/fire/sounds/scream10.ogg differ diff --git a/addons/fire/sounds/scream11.ogg b/addons/fire/sounds/scream11.ogg new file mode 100644 index 00000000000..c215ad3a61a Binary files /dev/null and b/addons/fire/sounds/scream11.ogg differ diff --git a/addons/fire/sounds/scream12.ogg b/addons/fire/sounds/scream12.ogg new file mode 100644 index 00000000000..11bc13fd917 Binary files /dev/null and b/addons/fire/sounds/scream12.ogg differ diff --git a/addons/fire/sounds/scream13.ogg b/addons/fire/sounds/scream13.ogg new file mode 100644 index 00000000000..726cd87be54 Binary files /dev/null and b/addons/fire/sounds/scream13.ogg differ diff --git a/addons/fire/sounds/scream14.ogg b/addons/fire/sounds/scream14.ogg new file mode 100644 index 00000000000..eff98f7ebc8 Binary files /dev/null and b/addons/fire/sounds/scream14.ogg differ diff --git a/addons/fire/sounds/scream15.ogg b/addons/fire/sounds/scream15.ogg new file mode 100644 index 00000000000..fa7c5d884bb Binary files /dev/null and b/addons/fire/sounds/scream15.ogg differ diff --git a/addons/fire/sounds/scream2.ogg b/addons/fire/sounds/scream2.ogg new file mode 100644 index 00000000000..8f79081fcdd Binary files /dev/null and b/addons/fire/sounds/scream2.ogg differ diff --git a/addons/fire/sounds/scream3.ogg b/addons/fire/sounds/scream3.ogg new file mode 100644 index 00000000000..2749b01a741 Binary files /dev/null and b/addons/fire/sounds/scream3.ogg differ diff --git a/addons/fire/sounds/scream4.ogg b/addons/fire/sounds/scream4.ogg new file mode 100644 index 00000000000..c92497e8695 Binary files /dev/null and b/addons/fire/sounds/scream4.ogg differ diff --git a/addons/fire/sounds/scream5.ogg b/addons/fire/sounds/scream5.ogg new file mode 100644 index 00000000000..23fb6c7ed92 Binary files /dev/null and b/addons/fire/sounds/scream5.ogg differ diff --git a/addons/fire/sounds/scream6.ogg b/addons/fire/sounds/scream6.ogg new file mode 100644 index 00000000000..9a14a69e744 Binary files /dev/null and b/addons/fire/sounds/scream6.ogg differ diff --git a/addons/fire/sounds/scream7.ogg b/addons/fire/sounds/scream7.ogg new file mode 100644 index 00000000000..ab1970ee53d Binary files /dev/null and b/addons/fire/sounds/scream7.ogg differ diff --git a/addons/fire/sounds/scream8.ogg b/addons/fire/sounds/scream8.ogg new file mode 100644 index 00000000000..688460e934a Binary files /dev/null and b/addons/fire/sounds/scream8.ogg differ diff --git a/addons/fire/sounds/scream9.ogg b/addons/fire/sounds/scream9.ogg new file mode 100644 index 00000000000..72ef6e4f7cb Binary files /dev/null and b/addons/fire/sounds/scream9.ogg differ diff --git a/addons/fire/stringtable.xml b/addons/fire/stringtable.xml new file mode 100644 index 00000000000..90e1431bdb6 --- /dev/null +++ b/addons/fire/stringtable.xml @@ -0,0 +1,23 @@ + + + + + ACE Fire + + + Pat Down Fire + + + Patting Down Fire + + + Allow units to catch fire + + + Enable fire-flare at night + + + Uses a flare effect to increase fire intensity at night + + +