Fire deals more damage

This commit is contained in:
johnb432 2024-02-05 13:17:33 +01:00
parent ccb09e60d7
commit 41bd5bf5c3
13 changed files with 138 additions and 77 deletions

View File

@ -38,7 +38,7 @@ if (isServer) then {
}; };
if (_ring) then { if (_ring) then {
private _intensity = 6; private _intensity = 20;
private _radius = 1.5 * ((boundingBoxReal _obj) select 2); private _radius = 1.5 * ((boundingBoxReal _obj) select 2);
[QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, format [QGVAR(%1), hashValue _obj]]] call CBA_fnc_localEvent; [QEGVAR(fire,addFireSource), [_obj, _radius, _intensity, format [QGVAR(%1), hashValue _obj]]] call CBA_fnc_localEvent;
}; };

View File

@ -0,0 +1,7 @@
class CfgVehicles {
class Static;
class GVAR(logic): Static {
scope = 1;
displayName = "";
};
};

View File

@ -2,6 +2,7 @@
[QGVAR(burn), LINKFUNC(burn)] call CBA_fnc_addEventHandler; [QGVAR(burn), LINKFUNC(burn)] call CBA_fnc_addEventHandler;
[QGVAR(burnEffects), LINKFUNC(burnEffects)] 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(burnSimulation), LINKFUNC(burnSimulation)] call CBA_fnc_addEventHandler;
// Only play sound if enabled in settings // Only play sound if enabled in settings
@ -22,23 +23,67 @@ if (isServer) then {
GVAR(fireSources) = createHashMap; GVAR(fireSources) = createHashMap;
[QGVAR(addFireSource), { [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 { // Check if the source is valid
_fireLogic attachTo [_source]; 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 { } else {
_fireLogic setPosASL _source; ASLToATL _source
}; };
GVAR(fireSources) set [_key, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]]; 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 [_hashedKey, [_fireLogic, _radius, _intensity, _condition, _conditionArgs]];
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
[QGVAR(removeFireSource), { [QGVAR(removeFireSource), {
params ["_key"]; 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; }] call CBA_fnc_addEventHandler;
[LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler; [LINKFUNC(fireManagerPFH), FIRE_MANAGER_PFH_DELAY, []] call CBA_fnc_addPerFrameHandler;

View File

@ -24,6 +24,7 @@ class CfgPatches {
#include "CfgEventHandlers.hpp" #include "CfgEventHandlers.hpp"
#include "CfgSounds.hpp" #include "CfgSounds.hpp"
#include "CfgVehicles.hpp"
#include "ACE_Medical_Treatment_Actions.hpp" #include "ACE_Medical_Treatment_Actions.hpp"
#include "RscTitles.hpp" #include "RscTitles.hpp"

View File

@ -1,10 +1,10 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: tcvm, johnb43 * Author: johnb43
* Makes object catch fire. Only call from targeted events, is applied globally. * Makes a unit catch fire. Only call from targeted events, is applied globally.
* *
* Arguments: * Arguments:
* 0: Vehicle <OBJECT> * 0: Unit <OBJECT>
* 1: Intensity of fire <NUMBER> * 1: Intensity of fire <NUMBER>
* 2: Instigator of fire <OBJECT> (default: objNull) * 2: Instigator of fire <OBJECT> (default: objNull)
* *
@ -25,31 +25,35 @@ if (!GVAR(enabled)) exitWith {};
params ["_unit", "_intensity", ["_instigator", objNull]]; params ["_unit", "_intensity", ["_instigator", objNull]];
if (BURN_MIN_INTENSITY > _intensity) exitWith {};
// Check if unit is remote (objNull is remote) // Check if unit is remote (objNull is remote)
if (!local _unit) exitWith {}; if (!local _unit) exitWith {};
// Check if the unit can burn (takes care of spectators and curators) // 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 !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) exitWith {};
// If unit is already burning, don't burn more private _unitPos = getPosASL _unit;
if (_unit call FUNC(isBurning)) exitWith {};
// 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]; _unit setVariable [QGVAR(intensity), _intensity, true];
// Fire simulation // Fire simulation (objects are handled differently)
private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator], format [QGVAR(burnSimulation_%1), hashValue _unit]] call CBA_fnc_globalEventJIP; private _burnSimulationJipID = [QGVAR(burnSimulation), [_unit, _instigator]] call CBA_fnc_globalEventJIP;
[_burnSimulationJipID, _unit] call CBA_fnc_removeGlobalEventJIP; [_burnSimulationJipID, _unit] call CBA_fnc_removeGlobalEventJIP;
// Spawn effects for unit // 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; [_burnEffectsJipID, _unit] call CBA_fnc_removeGlobalEventJIP;
_unit setVariable [QGVAR(jipIDs), [_burnSimulationJipID, _burnEffectsJipID], true]; _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);
};

View File

@ -26,7 +26,7 @@ private _lightFlare = objNull;
if (hasInterface) then { if (hasInterface) then {
_fireParticle = "#particlesource" createVehicleLocal _unitPos; _fireParticle = "#particlesource" createVehicleLocal _unitPos;
_fireParticle attachTo [_unit, [0, 0, 0]]; _fireParticle attachTo [_unit];
_fireParticle setDropInterval 0.03; _fireParticle setDropInterval 0.03;
_smokeParticle = "#particlesource" createVehicleLocal _unitPos; _smokeParticle = "#particlesource" createVehicleLocal _unitPos;
@ -35,7 +35,7 @@ if (hasInterface) then {
_fireLight setLightIntensity 0; _fireLight setLightIntensity 0;
_fireLight setLightAmbient [0.8, 0.6, 0.2]; _fireLight setLightAmbient [0.8, 0.6, 0.2];
_fireLight setLightColor [1, 0.5, 0.4]; _fireLight setLightColor [1, 0.5, 0.4];
_fireLight attachTo [_unit, [0, 0, 0]]; _fireLight attachTo [_unit];
_fireLight setLightDayLight false; _fireLight setLightDayLight false;
_lightFlare = "#lightpoint" createVehicleLocal _unitPos; _lightFlare = "#lightpoint" createVehicleLocal _unitPos;
@ -128,17 +128,8 @@ if (isServer) then {
0 // random direction intensity 0 // random direction intensity
]; ];
_smokeParticle setDropInterval 0.15;
_smokeParticle setParticleCircle [0, [0, 0, 0]]; _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 [ _smokeParticle setParticleParams [
["\A3\data_f\ParticleEffects\Universal\Universal", 16, 7, 48], // sprite sheet values ["\A3\data_f\ParticleEffects\Universal\Universal", 16, 7, 48], // sprite sheet values
"", // animation name "", // animation name
@ -164,13 +155,21 @@ if (isServer) then {
"", // before destroy script "", // before destroy script
_unit // particle source _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); _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]; _fireLight setLightAttenuation [1, 10 max (5 min (10 - _intensity)), 0, 15];
_lightFlare setLightBrightness (_intensity / 30);
_lightFlare setLightFlareSize (_intensity * (3 / 4)) * FLARE_SIZE_MODIFIER; _lightFlare setLightFlareSize (_intensity * (3 / 4)) * FLARE_SIZE_MODIFIER;
if (!GVAR(enableFlare)) then { 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 // Always keep flare visible to perceiving unit as long as it isn't the player
if (_unit != ACE_player) then { if (_unit != ACE_player) then {
private _distanceToUnit = _unit distance ACE_player;
private _relativeAttachPoint = [0, 0, 0.3]; private _relativeAttachPoint = [0, 0, 0.3];
if (_distanceToUnit > 1.5) then { if (_distanceToUnit > 1.5) then {

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: tcvm, johnb43 * 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". * Arbitrary values to ignite people. Assumed maximum is "10".
* *
* Arguments: * Arguments:
@ -29,20 +29,18 @@ _unit setVariable [QGVAR(burnCounter), nil];
private _remote = !local _unit; 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 { if (isNull _unit || {_remote && {!(_unit call FUNC(isBurning))}}) exitWith {
_pfhID call CBA_fnc_removePerFrameHandler; _pfhID call CBA_fnc_removePerFrameHandler;
}; };
if (_remote) exitWith {}; 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 is invulnerable or in water or if the fire has died out, stop burning unit
if ( if (
!(_unit call FUNC(isBurning)) || !(_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 { ) exitWith {
// Remove global effects and simulation // Remove global effects and simulation
{ {
@ -66,17 +64,21 @@ _unit setVariable [QGVAR(burnCounter), nil];
private _intensity = _unit getVariable [QGVAR(intensity), 0]; 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 { if (_intensity >= BURN_THRESHOLD_INTENSE) then {
_unitPos = ASLToAGL _unitPos; private _adjustedIntensity = 0;
{ {
if !(_x call FUNC(isBurning)) then { _distancePercent = 1 - ((_unit distance _x) / BURN_PROPAGATE_DISTANCE);
_distancePercent = 1 - ((_unitPos 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 // Update intensity/fire reactions

View File

@ -1,8 +1,7 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: tcvm * Author: tcvm
* Handles various fire objects and determines if local units deserves to get burned. * Handles various objects on fire and determines if units close to objects deserve to get burned.
* Used to handle external burning objects, not used internally because internal methods are more performant.
* *
* Arguments: * Arguments:
* 0: Args (not used) <ARRAY> * 0: Args (not used) <ARRAY>
@ -12,34 +11,37 @@
* None * None
* *
* Example: * Example:
* [ace_fire_fnc_fireManagerPFH, 0.25] call CBA_fnc_addPerFrameHandler * [[], -1] call CBA_fnc_addPerFrameHandler
* *
* Public: No * Public: No
*/ */
private _attachedObject = objNull;
private _sourcePos = [];
private _distancePercent = 0; 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 // Remove when condition is no longer valid
if !(_conditionArgs call _condition) then { if !(_conditionArgs call _condition) then {
GVAR(fireSources) deleteAt _x; (GVAR(fireSources) deleteAt _x) params [["_fireLogic", objNull]];
detach _fireLogic;
deleteVehicle _fireLogic;
continue; continue;
}; };
_attachedObject = attachedTo _source; // Burn units (alive or dead) close to the fire
_sourcePos = ASLtoAGL getPosASL ([_source, _attachedObject] select (!isNull _attachedObject));
// Burn units close to the fire
{ {
if !(_x call FUNC(isBurning)) then { _distancePercent = 1 - ((_fireLogic distance _x) / _radius);
_distancePercent = 1 - ((_sourcePos 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); } forEach GVAR(fireSources);

View File

@ -1,10 +1,10 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: commy2 * Author: commy2
* Check if unit is burning. * Check if an object is burning.
* *
* Arguments: * Arguments:
* 0: Unit <OBJECT> * 0: Object <OBJECT>
* *
* Return Value: * Return Value:
* None * None
@ -15,6 +15,6 @@
* Public: Yes * 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

View File

@ -37,8 +37,8 @@
#define INTENSITY_DECREASE_MULT_PAT_DOWN 0.8 #define INTENSITY_DECREASE_MULT_PAT_DOWN 0.8
#define INTENSITY_DECREASE_MULT_ROLLING INTENSITY_DECREASE_MULT_PAT_DOWN #define INTENSITY_DECREASE_MULT_ROLLING INTENSITY_DECREASE_MULT_PAT_DOWN
#define INTENSITY_LOSS 0.03 #define INTENSITY_LOSS 0.02
#define INTENSITY_UPDATE 3 #define INTENSITY_UPDATE 2
#define BURN_PROPAGATE_UPDATE 1 #define BURN_PROPAGATE_UPDATE 1
#define BURN_PROPAGATE_DISTANCE 2 #define BURN_PROPAGATE_DISTANCE 2
#define BURN_THRESHOLD_INTENSE 3 #define BURN_THRESHOLD_INTENSE 3

View File

@ -153,7 +153,7 @@ class CfgAmmo {
class ACE_G_M14: SmokeShell { class ACE_G_M14: SmokeShell {
GVAR(incendiary) = 1; GVAR(incendiary) = 1;
model = QPATHTOF(models\ace_anm14th3_armed.p3d); model = QPATHTOF(models\ace_anm14th3_armed.p3d);
hit = 5; hit = 10;
indirectHit = 4; indirectHit = 4;
indirectHitRange = 1.1; indirectHitRange = 1.1;
dangerRadiusHit = 50; dangerRadiusHit = 50;

View File

@ -29,7 +29,7 @@ class CfgVehicles {
scope = 1; // Should be 1 (private) or 2 (public), scope 0 will cause errors on object creation scope = 1; // Should be 1 (private) or 2 (public), scope 0 will cause errors on object creation
displayName = "New ACE attachable item"; displayName = "New ACE attachable item";
model = "\path\to\my\model.p3d"; model = "\path\to\my\model.p3d";
vehicleClass = ""; vehicleClass = "";
}; };
}; };
``` ```

View File

@ -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 0 | Source of flame | Object/Position ASL | Required
1 | Radius of fire | Number | Required 1 | Radius of fire | Number | Required
2 | Intensity of fire (1, 10] | Number | Required 2 | Intensity of fire (1, 10] | Number | Required
3 | Fire source ID | Any | Required 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 }`) 4 | Condition to stop fire | Code | Optional (default: `{true}`)
5 | Arguments to pass to condition | Any | Optional (default: `[]`) 5 | Arguments to pass to condition | Any | Optional (default: `[]`)
### 1.2 Removing fire source ### 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) | 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