Skip to content

Commit 475ac68

Browse files
authored
Merge pull request #1 from johnb432/dev
1.0.3.0
2 parents 2101086 + 4e332ec commit 475ac68

12 files changed

Lines changed: 377 additions & 96 deletions

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

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ _unit setVariable ["armor_modifier_ace_main_hitPointMultiplier_chest", [armorMul
2626
_unit setVariable ["armor_modifier_ace_main_hitPointMultiplier_limb", [armorMultiplier, minimumArmor, maximumArmor], true];
2727
```
2828

29+
2 is usually the minimum hitpoint armor a unit has without any equipment on.
30+
2931
<h2>Examples</h2>
3032

3133
* If **Player hitpoint damage reduction - chest** is set to `[10, 0, 0]`, it means that you take a 10th of the damage to the chest.

README_steam.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ _unit setVariable ["armor_modifier_ace_main_hitPointMultiplier_chest", [armorMul
2929
_unit setVariable ["armor_modifier_ace_main_hitPointMultiplier_limb", [armorMultiplier, minimumArmor, maximumArmor], true];
3030
[/code]
3131

32+
2 is usually the minimum hitpoint armor a unit has without any equipment on.
33+
3234
[h2]Examples[/h2]
3335
[list]
3436
[*] If [b]Player hitpoint damage reduction - chest[/b] is set to '[10, 0, 0]', it means that you take a 10th of the damage to the chest.

addons/main/CfgVersioning.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class CfgSettings {
2+
class CBA {
3+
class Versioning {
4+
class PREFIX {
5+
class Dependencies {
6+
ACE[] = {"ace_main", {3, 18, 0}, "true"};
7+
CBA[] = {"cba_main", {3, 16, 0}, "true"};
8+
};
9+
};
10+
};
11+
};
12+
};

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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ class CfgPatches {
2020
};
2121

2222
#include "CfgEventHandlers.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: 81 additions & 81 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
@@ -19,13 +18,14 @@
1918
*/
2019

2120
params ["_args", ["_ignoreAllowDamageACE", false]];
22-
_args params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint", "_directHit"];
21+
_args params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint", "_directHit", "_context"];
2322

2423
// HD sometimes triggers for remote units - ignore.
2524
if !(local _unit) exitWith {nil};
2625

2726
// Get missing meta info
2827
private _oldDamage = 0;
28+
private _structuralDamage = _context == 0;
2929

3030
if (_hitPoint isEqualTo "") then {
3131
_hitPoint = "#structural";
@@ -38,26 +38,30 @@ if (_hitPoint isEqualTo "") then {
3838
if !(isDamageAllowed _unit && {_unit getVariable ["ace_medical_allowDamage", true] || _ignoreAllowDamageACE}) exitWith {_oldDamage};
3939

4040
private _newDamage = _damage - _oldDamage;
41+
42+
// _newDamage == 0 happens occasionally for vehiclehit events (see line 80 onwards), just exit early to save some frametime
43+
// context 4 is engine "bleeding". For us, it's just a duplicate event for #structural which we can ignore without any issues
44+
if (_context != 2 && {_context == 4 || _newDamage == 0}) exitWith {
45+
TRACE_4("Skipping engine bleeding or zero damage",_ammo,_newDamage,_directHit,_context);
46+
_oldDamage
47+
};
48+
4149
// Get scaled armor value of hitpoint and calculate damage before armor
4250
// We scale using passThrough to handle explosive-resistant armor properly (#9063)
4351
// We need realDamage to determine which limb was hit correctly
4452
[_unit, _hitpoint] call ace_medical_engine_fnc_getHitpointArmor params ["_armor", "_armorScaled"];
45-
4653
private _realDamage = _newDamage * _armor;
47-
48-
// ACE <3.16.0 does not return "_armorScaled"
49-
if (_hitPoint isNotEqualTo "#structural" && {!isNil "_armorScaled"}) then {
50-
private _armorCoef = _armor / _armorScaled;
54+
if (!_structuralDamage) then {
55+
private _armorCoef = _armor/_armorScaled;
5156
private _damageCoef = linearConversion [0, 1, ace_medical_engine_damagePassThroughEffect, 1, _armorCoef];
5257
_newDamage = _newDamage * _damageCoef;
5358
};
54-
55-
TRACE_4("Received hit",_hitpoint,_ammo,_newDamage,_realDamage);
59+
TRACE_6("Received hit",_hitpoint,_ammo,_newDamage,_realDamage,_directHit,_context);
5660

5761
// Drowning doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
5862
// Damage occurs in consistent increments
5963
if (
60-
_hitPoint isEqualTo "#structural" &&
64+
_structuralDamage &&
6165
{getOxygenRemaining _unit <= 0.5} &&
6266
{_damage isEqualTo (_oldDamage + 0.005)}
6367
) exitWith {
@@ -67,14 +71,16 @@ if (
6771
0
6872
};
6973

74+
// Faster than (vehicle _unit), also handles dead units
75+
private _vehicle = objectParent _unit;
76+
private _inVehicle = !isNull _vehicle;
77+
private _environmentDamage = _ammo == "";
78+
7079
// Crashing a vehicle doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
7180
// It does fire the EH multiple times, but this seems to scale with the intensity of the crash
72-
private _vehicle = vehicle _unit;
7381
if (
7482
ace_medical_enableVehicleCrashes &&
75-
{_hitPoint isEqualTo "#structural"} &&
76-
{_ammo isEqualTo ""} &&
77-
{!isNull _vehicle} &&
83+
{_environmentDamage && _inVehicle && _structuralDamage} &&
7884
{vectorMagnitude (velocity _vehicle) > 5}
7985
// todo: no way to detect if stationary and another vehicle hits you
8086
) exitWith {
@@ -85,19 +91,16 @@ if (
8591
};
8692

8793
// Receiving explosive damage inside a vehicle doesn't trigger for each hitpoint
88-
// This is the case for mines, explosives, artillery, and catastrophic vehicle explosions
89-
// Triggers twice, but that doesn't matter as damage is low
94+
// This is the case for mines, explosives, artillery, and catasthrophic vehicle explosions
9095
if (
91-
_hitPoint isEqualTo "#structural" &&
92-
{!isNull _vehicle} &&
93-
{_ammo isNotEqualTo ""} &&
96+
(!_environmentDamage && _inVehicle && _structuralDamage) &&
9497
{
9598
private _ammoCfg = configFile >> "CfgAmmo" >> _ammo;
9699
GET_NUMBER(_ammoCfg >> "explosive",0) > 0 ||
97100
{GET_NUMBER(_ammoCfg >> "indirectHit",0) > 0}
98101
}
99-
) exitwith {
100-
TRACE_6("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage,_damages);
102+
) exitWith {
103+
TRACE_5("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage);
101104

102105
_unit setVariable ["ace_medical_lastDamageSource", _shooter];
103106
_unit setVariable ["ace_medical_lastInstigator", _instigator];
@@ -107,9 +110,59 @@ if (
107110
0
108111
};
109112

110-
// This hitpoint is set to trigger last, evaluate all the stored damage values
111-
// to determine where wounds are applied
112-
if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
113+
// Get setting for particular unit
114+
private _multiplierArray = switch (true) do {
115+
case (_hitPoint in ["hitface", "hitneck", "hithead"]): {
116+
_unit getVariable [QGVAR(hitPointMultiplier_head), [GVAR(hitPointMultiplier_ai_head), GVAR(hitPointMultiplier_player_head)] select (isPlayer _unit)]
117+
};
118+
case (_hitPoint in ["hitpelvis" ,"hitabdomen", "hitdiaphragm", "hitchest"]): {
119+
_unit getVariable [QGVAR(hitPointMultiplier_chest), [GVAR(hitPointMultiplier_ai_chest), GVAR(hitPointMultiplier_player_chest)] select (isPlayer _unit)]
120+
};
121+
case (_hitPoint in ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"]): {
122+
_unit getVariable [QGVAR(hitPointMultiplier_limb), [GVAR(hitPointMultiplier_ai_limb), GVAR(hitPointMultiplier_player_limb)] select (isPlayer _unit)]
123+
};
124+
default {
125+
DEFAULT_SETTINGS
126+
};
127+
};
128+
129+
private _modifiedNewDamage = _newDamage;
130+
private _modifiedRealDamage = _realDamage;
131+
132+
// If default settings, we don't need to change anything, so skip calculcations and let ace handle damage
133+
if (_multiplierArray isNotEqualTo DEFAULT_SETTINGS) then {
134+
_multiplierArray params ["_hitPointMultiplier", "_armorMin", "_armorMax"];
135+
136+
switch (true) do {
137+
case (_armorMin >= 1 && {_armor < _armorMin}): {
138+
// This will decrease damage
139+
_modifiedNewDamage = _newDamage * _armor / _armorMin;
140+
_modifiedRealDamage = _realDamage * _armor / _armorMin;
141+
142+
TRACE_6("Under min armor",_armor,_armorMin,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
143+
};
144+
case (_armorMax >= 1 && {_armor > _armorMax}): {
145+
// This will increase damage
146+
_modifiedNewDamage = _newDamage * _armor / _armorMax;
147+
_modifiedRealDamage = _realDamage * _armor / _armorMax;
148+
149+
TRACE_6("Over max armor",_armor,_armorMax,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
150+
};
151+
};
152+
153+
_modifiedNewDamage = _modifiedNewDamage / _hitPointMultiplier;
154+
_modifiedRealDamage = _modifiedRealDamage / _hitPointMultiplier;
155+
156+
TRACE_5("Hitpoint damage multiplied",_armor,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
157+
};
158+
159+
// Damages are stored for last iteration of the HandleDamage event (_context == 2)
160+
_unit setVariable [format ["ace_medical_engine_$%1", _hitPoint], [_realDamage, _newDamage, _modifiedRealDamage, _modifiedNewDamage]];
161+
162+
// Ref https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#HandleDamage
163+
// Context 2 means this is the last iteration of HandleDamage, so figure out which hitpoint took the most real damage and send wound event
164+
// Don't exit, as the last iteration can be one of the hitpoints that we need to keep _oldDamage for
165+
if (_context == 2) then {
113166
_unit setVariable ["ace_medical_lastDamageSource", _shooter];
114167
_unit setVariable ["ace_medical_lastInstigator", _instigator];
115168

@@ -161,7 +214,7 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
161214

162215
// Environmental damage sources all have empty ammo string
163216
// No explicit source given, we infer from differences between them
164-
if (_ammo isEqualTo "") then {
217+
if (_environmentDamage) then {
165218
// Any collision with terrain/vehicle/object has a shooter
166219
// Check this first because burning can happen at any velocity
167220
if !(isNull _shooter) then {
@@ -203,62 +256,9 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
203256
"ace_medical_engine_$HitLeftArm","ace_medical_engine_$HitRightArm","ace_medical_engine_$HitLeftLeg","ace_medical_engine_$HitRightLeg",
204257
"ace_medical_engine_$#structural"
205258
];
206-
207-
0
208-
};
209-
210-
// Get setting for particular unit
211-
private _multiplierArray = switch (true) do {
212-
case (_hitPoint in ["hitface", "hitneck", "hithead"]): {
213-
_unit getVariable [QGVAR(hitPointMultiplier_head), [GVAR(hitPointMultiplier_ai_head), GVAR(hitPointMultiplier_player_head)] select (isPlayer _unit)]
214-
};
215-
case (_hitPoint in ["hitpelvis" ,"hitabdomen", "hitdiaphragm", "hitchest"]): {
216-
_unit getVariable [QGVAR(hitPointMultiplier_chest), [GVAR(hitPointMultiplier_ai_chest), GVAR(hitPointMultiplier_player_chest)] select (isPlayer _unit)]
217-
};
218-
case (_hitPoint in ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"]): {
219-
_unit getVariable [QGVAR(hitPointMultiplier_limb), [GVAR(hitPointMultiplier_ai_limb), GVAR(hitPointMultiplier_player_limb)] select (isPlayer _unit)]
220-
};
221-
default {
222-
DEFAULT_SETTINGS
223-
};
224-
};
225-
226-
private _modifiedNewDamage = _newDamage;
227-
private _modifiedRealDamage = _realDamage;
228-
229-
// If default settings, we don't need to change anything, so skip calculcations and let ace handle damage
230-
if (_multiplierArray isNotEqualTo DEFAULT_SETTINGS) then {
231-
_multiplierArray params ["_hitPointMultiplier", "_armorMin", "_armorMax"];
232-
233-
switch (true) do {
234-
case (_armorMin >= 1 && {_armor < _armorMin}): {
235-
// This will decrease damage
236-
_modifiedNewDamage = _newDamage * _armor / _armorMin;
237-
_modifiedRealDamage = _realDamage * _armor / _armorMin;
238-
239-
TRACE_6("Under min armor",_armor,_armorMin,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
240-
};
241-
case (_armorMax >= 1 && {_armor > _armorMax}): {
242-
// This will increase damage
243-
_modifiedNewDamage = _newDamage * _armor / _armorMax;
244-
_modifiedRealDamage = _realDamage * _armor / _armorMax;
245-
246-
TRACE_6("Over max armor",_armor,_armorMax,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
247-
};
248-
};
249-
250-
_modifiedNewDamage = _modifiedNewDamage / _hitPointMultiplier;
251-
_modifiedRealDamage = _modifiedRealDamage / _hitPointMultiplier;
252-
253-
TRACE_5("Hitpoint damage multiplied",_armor,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage);
254259
};
255260

256-
// Damages are stored for "ace_hdbracket" event triggered last
257-
_unit setVariable [format ["ace_medical_engine_$%1", _hitPoint], [_realDamage, _newDamage, _modifiedRealDamage, _modifiedNewDamage]];
258-
259261
// Engine damage to these hitpoints controls blood visuals, limping, weapon sway
260262
// Handled in fnc_damageBodyPart, persist here
261-
if (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"]) exitWith {_oldDamage};
262-
263-
// We store our own damage values so engine damage is unnecessary
264-
0
263+
// For all other hitpoints, we store our own damage values, so engine damage is unnecessary
264+
[0, _oldDamage] select (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"])

0 commit comments

Comments
 (0)