Skip to content

Commit 4e332ec

Browse files
committed
1.0.3.0
1 parent 056c35b commit 4e332ec

9 files changed

Lines changed: 282 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# Changelog for Armor Modifier - ACE 28.9.2024
2+
3+
1.0.3.0
4+
- Updated to work with ACE 3.18.0. Remains backwards compatible with ACE 3.17.1.
5+
16
# Changelog for Armor Modifier - ACE 26.3.2024
27

38
1.0.2.0

addons/main/XEH_PREP.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
PREP(handleDamage);
1+
if (getNumber (configFile >> "CfgPatches" >> "ace_main" >> "version") >= 3.18) then {
2+
PREP(handleDamage,handleDamage);
3+
} else {
4+
PREP(handleDamage,handleDamageOld);
5+
};

addons/main/addon.toml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,2 @@
11
[rapify]
22
enabled = true
3-
4-
[binarize]
5-
enabled = true
6-
7-
[asc]
8-
enabled = true

addons/main/config.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ class CfgPatches {
2020
};
2121

2222
#include "CfgEventHandlers.hpp"
23-
#include "CfgVersioning.hpp"
23+
24+
// Don't force ACE version until 3.18.0 has been out for a while
25+
// #include "CfgVersioning.hpp"

addons/main/functions/fnc_handleDamage.sqf

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
#include "..\script_component.hpp"
2-
32
/*
43
* Author: commy2, kymckay, modified by johnb43
54
* Original:
65
* HandleDamage EH where wound events are raised based on incoming damage.
76
* Be aware that for each source of damage, the EH can fire multiple times (once for each hitpoint).
87
* We store these incoming damages and compare them on our final hitpoint: "ace_hdbracket".
98
* Added:
10-
* Handling of damage to allow armor modifcation.
9+
* Handling of damage to allow armor modifcation. For ACE 3.18.0 and later.
1110
*
1211
* Arguments:
1312
* Handle damage EH
@@ -100,7 +99,7 @@ if (
10099
GET_NUMBER(_ammoCfg >> "explosive",0) > 0 ||
101100
{GET_NUMBER(_ammoCfg >> "indirectHit",0) > 0}
102101
}
103-
) exitwith {
102+
) exitWith {
104103
TRACE_5("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage);
105104

106105
_unit setVariable ["ace_medical_lastDamageSource", _shooter];
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
#include "..\script_component.hpp"
2+
/*
3+
* Author: commy2, kymckay, modified by johnb43
4+
* Original:
5+
* HandleDamage EH where wound events are raised based on incoming damage.
6+
* Be aware that for each source of damage, the EH can fire multiple times (once for each hitpoint).
7+
* We store these incoming damages and compare them on our final hitpoint: "ace_hdbracket".
8+
* Added:
9+
* Handling of damage to allow armor modifcation. For ACE 3.17.1 and prior.
10+
*
11+
* Arguments:
12+
* Handle damage EH
13+
*
14+
* Return Value:
15+
* Damage to be inflicted <NUMBER>
16+
*
17+
* Public: No
18+
*/
19+
20+
params ["_args", ["_ignoreAllowDamageACE", false]];
21+
_args params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint", "_directHit"];
22+
23+
// HD sometimes triggers for remote units - ignore.
24+
if !(local _unit) exitWith {nil};
25+
26+
// Get missing meta info
27+
private _oldDamage = 0;
28+
29+
if (_hitPoint isEqualTo "") then {
30+
_hitPoint = "#structural";
31+
_oldDamage = damage _unit;
32+
} else {
33+
_oldDamage = _unit getHitIndex _hitPointIndex;
34+
};
35+
36+
// Damage can be disabled with old variable or via sqf command allowDamage
37+
if !(isDamageAllowed _unit && {_unit getVariable ["ace_medical_allowDamage", true] || _ignoreAllowDamageACE}) exitWith {_oldDamage};
38+
39+
private _newDamage = _damage - _oldDamage;
40+
// Get scaled armor value of hitpoint and calculate damage before armor
41+
// We scale using passThrough to handle explosive-resistant armor properly (#9063)
42+
// We need realDamage to determine which limb was hit correctly
43+
[_unit, _hitpoint] call ace_medical_engine_fnc_getHitpointArmor params ["_armor", "_armorScaled"];
44+
45+
private _realDamage = _newDamage * _armor;
46+
47+
// ACE <3.16.0 does not return "_armorScaled"
48+
if (_hitPoint isNotEqualTo "#structural" && {!isNil "_armorScaled"}) then {
49+
private _armorCoef = _armor / _armorScaled;
50+
private _damageCoef = linearConversion [0, 1, ace_medical_engine_damagePassThroughEffect, 1, _armorCoef];
51+
_newDamage = _newDamage * _damageCoef;
52+
};
53+
54+
TRACE_4("Received hit",_hitpoint,_ammo,_newDamage,_realDamage);
55+
56+
// Drowning doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
57+
// Damage occurs in consistent increments
58+
if (
59+
_hitPoint isEqualTo "#structural" &&
60+
{getOxygenRemaining _unit <= 0.5} &&
61+
{_damage isEqualTo (_oldDamage + 0.005)}
62+
) exitWith {
63+
TRACE_5("Drowning",_unit,_shooter,_instigator,_damage,_newDamage);
64+
["ace_medical_woundReceived", [_unit, [[_newDamage, "Body", _newDamage]], _unit, "drowning"]] call CBA_fnc_localEvent;
65+
66+
0
67+
};
68+
69+
// Crashing a vehicle doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
70+
// It does fire the EH multiple times, but this seems to scale with the intensity of the crash
71+
private _vehicle = vehicle _unit;
72+
if (
73+
ace_medical_enableVehicleCrashes &&
74+
{_hitPoint isEqualTo "#structural"} &&
75+
{_ammo isEqualTo ""} &&
76+
{!isNull _vehicle} &&
77+
{vectorMagnitude (velocity _vehicle) > 5}
78+
// todo: no way to detect if stationary and another vehicle hits you
79+
) exitWith {
80+
TRACE_5("Crash",_unit,_shooter,_instigator,_damage,_newDamage);
81+
["ace_medical_woundReceived", [_unit, [[_newDamage, _hitPoint, _newDamage]], _unit, "vehiclecrash"]] call CBA_fnc_localEvent;
82+
83+
0
84+
};
85+
86+
// Receiving explosive damage inside a vehicle doesn't trigger for each hitpoint
87+
// This is the case for mines, explosives, artillery, and catastrophic vehicle explosions
88+
// Triggers twice, but that doesn't matter as damage is low
89+
if (
90+
_hitPoint isEqualTo "#structural" &&
91+
{!isNull _vehicle} &&
92+
{_ammo isNotEqualTo ""} &&
93+
{
94+
private _ammoCfg = configFile >> "CfgAmmo" >> _ammo;
95+
GET_NUMBER(_ammoCfg >> "explosive",0) > 0 ||
96+
{GET_NUMBER(_ammoCfg >> "indirectHit",0) > 0}
97+
}
98+
) exitWith {
99+
TRACE_6("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage,_damages);
100+
101+
_unit setVariable ["ace_medical_lastDamageSource", _shooter];
102+
_unit setVariable ["ace_medical_lastInstigator", _instigator];
103+
104+
["ace_medical_woundReceived", [_unit, [[_newDamage, _hitPoint, _newDamage]], _shooter, "vehiclehit"]] call CBA_fnc_localEvent;
105+
106+
0
107+
};
108+
109+
// This hitpoint is set to trigger last, evaluate all the stored damage values
110+
// to determine where wounds are applied
111+
if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
112+
_unit setVariable ["ace_medical_lastDamageSource", _shooter];
113+
_unit setVariable ["ace_medical_lastInstigator", _instigator];
114+
115+
private _damageStructural = _unit getVariable ["ace_medical_engine_$#structural", [0,0,0,0]];
116+
117+
// --- Head
118+
private _damageHead = [
119+
_unit getVariable ["ace_medical_engine_$HitFace", [0,0,0,0]],
120+
_unit getVariable ["ace_medical_engine_$HitNeck", [0,0,0,0]],
121+
_unit getVariable ["ace_medical_engine_$HitHead", [0,0,0,0]]
122+
];
123+
_damageHead sort false;
124+
_damageHead = _damageHead select 0;
125+
126+
// --- Body
127+
private _damageBody = [
128+
_unit getVariable ["ace_medical_engine_$HitPelvis", [0,0,0,0]],
129+
_unit getVariable ["ace_medical_engine_$HitAbdomen", [0,0,0,0]],
130+
_unit getVariable ["ace_medical_engine_$HitDiaphragm", [0,0,0,0]],
131+
_unit getVariable ["ace_medical_engine_$HitChest", [0,0,0,0]]
132+
// HitBody removed as it's a placeholder hitpoint and the high armor value (1000) throws the calculations off
133+
];
134+
_damageBody sort false;
135+
_damageBody = _damageBody select 0;
136+
137+
// --- Arms and Legs
138+
private _damageLeftArm = _unit getVariable ["ace_medical_engine_$HitLeftArm", [0,0,0,0]];
139+
private _damageRightArm = _unit getVariable ["ace_medical_engine_$HitRightArm", [0,0,0,0]];
140+
private _damageLeftLeg = _unit getVariable ["ace_medical_engine_$HitLeftLeg", [0,0,0,0]];
141+
private _damageRightLeg = _unit getVariable ["ace_medical_engine_$HitRightLeg", [0,0,0,0]];
142+
143+
// Find hit point that received the maxium damage
144+
// Priority used for sorting if incoming damage is equal
145+
private _allDamages = [
146+
// Real damage (ignoring armor), Actual damage (with armor), Real damage modified (ignoring armor), Modified damage (with armor)
147+
[_damageHead select 0, PRIORITY_HEAD, _damageHead select 1, "Head", _damageHead param [2, _damageHead select 0], _damageHead param [3, _damageHead select 1]],
148+
[_damageBody select 0, PRIORITY_BODY, _damageBody select 1, "Body", _damageBody param [2, _damageBody select 0], _damageBody param [3, _damageBody select 1]],
149+
[_damageLeftArm select 0, PRIORITY_LEFT_ARM, _damageLeftArm select 1, "LeftArm", _damageLeftArm param [2, _damageLeftArm select 0], _damageLeftArm param [3, _damageLeftArm select 1]],
150+
[_damageRightArm select 0, PRIORITY_RIGHT_ARM, _damageRightArm select 1, "RightArm", _damageRightArm param [2, _damageRightArm select 0], _damageRightArm param [3, _damageRightArm select 1]],
151+
[_damageLeftLeg select 0, PRIORITY_LEFT_LEG, _damageLeftLeg select 1, "LeftLeg", _damageLeftLeg param [2, _damageLeftLeg select 0], _damageLeftLeg param [3, _damageLeftLeg select 1]],
152+
[_damageRightLeg select 0, PRIORITY_RIGHT_LEG, _damageRightLeg select 1, "RightLeg", _damageRightLeg param [2, _damageRightLeg select 0], _damageRightLeg param [3, _damageRightLeg select 1]],
153+
[_damageStructural select 0, PRIORITY_STRUCTURAL, _damageStructural select 1, "#structural", _damageStructural param [2, _damageStructural select 0], _damageStructural param [3, _damageStructural select 1]]
154+
];
155+
TRACE_2("incoming",_allDamages,_damageStructural);
156+
157+
_allDamages sort false;
158+
// Use modified damages instead of initial ones
159+
_allDamages = _allDamages apply {[_x select 5, _x select 3, _x select 4]};
160+
161+
// Environmental damage sources all have empty ammo string
162+
// No explicit source given, we infer from differences between them
163+
if (_ammo isEqualTo "") then {
164+
// Any collision with terrain/vehicle/object has a shooter
165+
// Check this first because burning can happen at any velocity
166+
if !(isNull _shooter) then {
167+
/*
168+
If shooter != unit then they hit unit, otherwise it could be:
169+
- Unit hitting anything at speed
170+
- An empty vehicle hitting unit
171+
- A physX object hitting unit
172+
Assume fall damage for downward velocity because it's most common
173+
*/
174+
if (_shooter == _unit && {(velocity _unit select 2) < -2}) then {
175+
_ammo = "falling";
176+
TRACE_5("Fall",_unit,_shooter,_instigator,_damage,_allDamages);
177+
} else {
178+
_ammo = "collision";
179+
TRACE_5("Collision",_unit,_shooter,_instigator,_damage,_allDamages);
180+
};
181+
} else {
182+
// Anything else is almost guaranteed to be fire damage
183+
_ammo = "fire";
184+
TRACE_5("Fire Damage",_unit,_shooter,_instigator,_damage,_allDamages);
185+
};
186+
};
187+
188+
// No wounds for minor damage
189+
// TODO check if this needs to be changed for burning damage (occurs as lots of small events that we add together)
190+
if ((_allDamages select 0 select 0) > 1E-3) then {
191+
TRACE_1("received",_allDamages);
192+
["ace_medical_woundReceived", [_unit, _allDamages, _shooter, _ammo]] call CBA_fnc_localEvent;
193+
};
194+
195+
// Clear stored damages otherwise they will influence future damage events
196+
// (aka wounds will pile onto the historically most damaged hitpoint)
197+
{
198+
_unit setVariable [_x, nil];
199+
} forEach [
200+
"ace_medical_engine_$HitFace","ace_medical_engine_$HitNeck","ace_medical_engine_$HitHead",
201+
"ace_medical_engine_$HitPelvis","ace_medical_engine_$HitAbdomen","ace_medical_engine_$HitDiaphragm","ace_medical_engine_$HitChest","ace_medical_engine_$HitBody",
202+
"ace_medical_engine_$HitLeftArm","ace_medical_engine_$HitRightArm","ace_medical_engine_$HitLeftLeg","ace_medical_engine_$HitRightLeg",
203+
"ace_medical_engine_$#structural"
204+
];
205+
206+
0
207+
};
208+
209+
// Get setting for particular unit
210+
private _multiplierArray = switch (true) do {
211+
case (_hitPoint in ["hitface", "hitneck", "hithead"]): {
212+
_unit getVariable [QGVAR(hitPointMultiplier_head), [GVAR(hitPointMultiplier_ai_head), GVAR(hitPointMultiplier_player_head)] select (isPlayer _unit)]
213+
};
214+
case (_hitPoint in ["hitpelvis" ,"hitabdomen", "hitdiaphragm", "hitchest"]): {
215+
_unit getVariable [QGVAR(hitPointMultiplier_chest), [GVAR(hitPointMultiplier_ai_chest), GVAR(hitPointMultiplier_player_chest)] select (isPlayer _unit)]
216+
};
217+
case (_hitPoint in ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"]): {
218+
_unit getVariable [QGVAR(hitPointMultiplier_limb), [GVAR(hitPointMultiplier_ai_limb), GVAR(hitPointMultiplier_player_limb)] select (isPlayer _unit)]
219+
};
220+
default {
221+
DEFAULT_SETTINGS
222+
};
223+
};
224+
225+
private _modifiedNewDamage = _newDamage;
226+
private _modifiedRealDamage = _realDamage;
227+
228+
// If default settings, we don't need to change anything, so skip calculcations and let ace handle damage
229+
if (_multiplierArray isNotEqualTo DEFAULT_SETTINGS) then {
230+
_multiplierArray params ["_hitPointMultiplier", "_armorMin", "_armorMax"];
231+
232+
switch (true) do {
233+
case (_armorMin >= 1 && {_armor < _armorMin}): {
234+
// This will decrease damage
235+
_modifiedNewDamage = _newDamage * _armor / _armorMin;
236+
_modifiedRealDamage = _realDamage * _armor / _armorMin;
237+
238+
TRACE_6("Under min armor",_armor,_armorMin,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
239+
};
240+
case (_armorMax >= 1 && {_armor > _armorMax}): {
241+
// This will increase damage
242+
_modifiedNewDamage = _newDamage * _armor / _armorMax;
243+
_modifiedRealDamage = _realDamage * _armor / _armorMax;
244+
245+
TRACE_6("Over max armor",_armor,_armorMax,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
246+
};
247+
};
248+
249+
_modifiedNewDamage = _modifiedNewDamage / _hitPointMultiplier;
250+
_modifiedRealDamage = _modifiedRealDamage / _hitPointMultiplier;
251+
252+
TRACE_5("Hitpoint damage multiplied",_armor,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
253+
};
254+
255+
// Damages are stored for "ace_hdbracket" event triggered last
256+
_unit setVariable [format ["ace_medical_engine_$%1", _hitPoint], [_realDamage, _newDamage, _modifiedRealDamage, _modifiedNewDamage]];
257+
258+
// Engine damage to these hitpoints controls blood visuals, limping, weapon sway
259+
// Handled in fnc_damageBodyPart, persist here
260+
if (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"]) exitWith {_oldDamage};
261+
262+
// We store our own damage values so engine damage is unnecessary
263+
0

addons/main/script_macros.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
#include "\x\cba\addons\main\script_macros_common.hpp"
22

3-
// This part includes parts of the CBA and ACE3 macro libraries
4-
#define GETMVAR(var1,var2) (missionNamespace getVariable [ARR_2(var1,var2)])
5-
#define SETMVAR(var1,var2,var3) (missionNamespace setVariable [ARR_3(var1,var2,var3)])
6-
73
#define DEFAULT_SETTINGS [ARR_3(1,0,0)]
84
#define MINIMUM_SETTINGS [ARR_3(0.001,0,0)]
95

106
#define DFUNC(var1) TRIPLES(ADDON,fnc,var1)
117

128
#ifdef DISABLE_COMPILE_CACHE
139
#undef PREP
14-
#define PREP(fncName) DFUNC(fncName) = compile preprocessFileLineNumbers QPATHTOF(functions\DOUBLES(fnc,fncName).sqf)
10+
#define PREP(fncName,filename) DFUNC(fncName) = compile preprocessFileLineNumbers QPATHTOF(functions\DOUBLES(fnc,filename).sqf)
1511
#else
1612
#undef PREP
17-
#define PREP(fncName) [QPATHTOF(functions\DOUBLES(fnc,fncName).sqf), QFUNC(fncName)] call CBA_fnc_compileFunction
13+
#define PREP(fncName,filename) [QPATHTOF(functions\DOUBLES(fnc,filename).sqf), QFUNC(fncName)] call CBA_fnc_compileFunction
1814
#endif
1915

2016
// #include "\z\ace\addons\medical_engine\script_component.hpp"

addons/main/script_mod.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD
99

1010
// MINIMAL required version for the Mod. Components can specify others..
11-
#define REQUIRED_VERSION 2.14
11+
#define REQUIRED_VERSION 2.16
1212

1313
#define COMPONENT_NAME QUOTE(Armor Modifier - ACE)

addons/main/script_version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#define MAJOR 1
22
#define MINOR 0
3-
#define PATCHLVL 2
3+
#define PATCHLVL 3
44
#define BUILD 0

0 commit comments

Comments
 (0)