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 {
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;
};

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(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
};
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;
[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;

View File

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

View File

@ -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 <OBJECT>
* 0: Unit <OBJECT>
* 1: Intensity of fire <NUMBER>
* 2: Instigator of fire <OBJECT> (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);
};

View File

@ -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 {

View File

@ -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

View File

@ -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) <ARRAY>
@ -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);

View File

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

View File

@ -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

View File

@ -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;

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
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