diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a42e9..8b1ff33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# Changelog for Armor Modifier - ACE 25.6.2025 + +1.0.6.0 +- Added compatibility with upcoming ACE 3.20.0 + # Changelog for Armor Modifier - ACE 9.2.2025 1.0.5.0 diff --git a/addons/main/XEH_PREP.hpp b/addons/main/XEH_PREP.hpp index 3b2bf28..1cbb909 100644 --- a/addons/main/XEH_PREP.hpp +++ b/addons/main/XEH_PREP.hpp @@ -1 +1,3 @@ +PREP(getHitpointArmor); +PREP(getItemArmor); PREP(handleDamage); diff --git a/addons/main/XEH_preInit.sqf b/addons/main/XEH_preInit.sqf index 38ab306..92b2200 100644 --- a/addons/main/XEH_preInit.sqf +++ b/addons/main/XEH_preInit.sqf @@ -7,4 +7,6 @@ ADDON = false; // CBA Settings #include "initSettings.inc.sqf" +GVAR(armorCache) = createHashMap; + ADDON = true; diff --git a/addons/main/functions/fnc_getHitpointArmor.sqf b/addons/main/functions/fnc_getHitpointArmor.sqf new file mode 100644 index 0000000..5a112a5 --- /dev/null +++ b/addons/main/functions/fnc_getHitpointArmor.sqf @@ -0,0 +1,51 @@ +#include "..\script_component.hpp" +/* + * Author: Pterolatypus, LinkIsGrim + * (This file is a copy from ACE3 3.19 with minor simplifications) + * Checks a unit's equipment to calculate the total armor on a hitpoint. + * + * Arguments: + * 0: Unit + * 1: Hitpoint + * + * Return Value: + * Total armor and scaled armor for the given hitpoint + * + * Example: + * [player, "HitChest"] call armor_modifier_ace_main_fnc_getHitpointArmor + * + * Public: No + */ + +params ["_unit", "_hitpoint"]; + +private _uniform = uniform _unit; +// If unit is naked, use its underwear class instead +if (_uniform isEqualTo "") then { + _uniform = getText (configOf _unit >> "nakedUniform"); +}; + +private _gear = [ + _uniform, + vest _unit, + headgear _unit +]; + +private _rags = _gear joinString "$"; +private _var = format [QGVAR(armorCache$%1), _hitpoint]; +_unit getVariable [_var, ["", 0, 0]] params ["_prevRags", "_armor"]; + +if (_rags != _prevRags) then { + _armor = 0; + + { + _armor = _armor + ([_x, _hitpoint] call FUNC(getItemArmor)); + } forEach _gear; + + // Armor should be at least 1 to prevent dividing by 0 + _armor = _armor max 1; + + _unit setVariable [_var, [_rags, _armor]]; +}; + +_armor // return diff --git a/addons/main/functions/fnc_getItemArmor.sqf b/addons/main/functions/fnc_getItemArmor.sqf new file mode 100644 index 0000000..d3d7c74 --- /dev/null +++ b/addons/main/functions/fnc_getItemArmor.sqf @@ -0,0 +1,47 @@ +#include "..\script_component.hpp" +/* + * Author: Pterolatypus, LinkIsGrim + * Returns the regular and scaled armor values the given item provides to a particular hitpoint, either from a cache or by reading the item config. + * + * Arguments: + * 0: Item Class + * 1: Hitpoint + * + * Return Value: + * Regular and scaled item armor for the given hitpoint + * + * Example: + * ["V_PlateCarrier_rgr", "HitChest"] call armor_modifier_ace_main_fnc_getItemArmor + * + * Public: No + */ + +params ["_item", "_hitpoint"]; + +GVAR(armorCache) getOrDefaultCall [_this joinString "$", { + TRACE_2("Cache miss",_item,_hitpoint); + private _armor = 0; + + if !("" in [_item, _hitpoint]) then { + private _itemInfo = configFile >> "CfgWeapons" >> _item >> "ItemInfo"; + private _itemType = getNumber (_itemInfo >> "type"); + + if (_itemType == TYPE_UNIFORM) then { + private _unitCfg = configFile >> "CfgVehicles" >> getText (_itemInfo >> "uniformClass"); + _armor = if (_hitpoint == "#structural") then { + // TODO: I'm not sure if this should be multiplied by the base armor value or not + getNumber (_unitCfg >> "armorStructural") + } else { + getNumber (_unitCfg >> "armor") * (1 max getNumber (_unitCfg >> "HitPoints" >> _hitpoint >> "armor")) + }; + } else { + private _condition = format ["getText (_x >> 'hitpointName') == '%1'", _hitpoint]; + private _entry = configProperties [_itemInfo >> "HitpointsProtectionInfo", _condition] param [0, configNull]; + if (!isNull _entry) then { + _armor = getNumber (_entry >> "armor"); + }; + }; + }; + + _armor // return +}, true] diff --git a/addons/main/functions/fnc_handleDamage.sqf b/addons/main/functions/fnc_handleDamage.sqf index 6ba77c0..ec5eb0e 100644 --- a/addons/main/functions/fnc_handleDamage.sqf +++ b/addons/main/functions/fnc_handleDamage.sqf @@ -63,13 +63,8 @@ if (_context != 2 && {_context == 4 || _newDamage == 0}) exitWith { // Get scaled armor value of hitpoint and calculate damage before armor // We scale using passThrough to handle explosive-resistant armor properly (#9063) // We need realDamage to determine which limb was hit correctly -[_unit, _hitpoint] call ace_medical_engine_fnc_getHitpointArmor params ["_armor", "_armorScaled"]; +private _armor = [_unit, _hitpoint] call FUNC(getHitpointArmor); private _realDamage = _newDamage * _armor; -if (!_structuralDamage) then { - private _armorCoef = _armor/_armorScaled; - private _damageCoef = linearConversion [0, 1, ace_medical_engine_damagePassThroughEffect, 1, _armorCoef]; - _newDamage = _newDamage * _damageCoef; -}; TRACE_6("Received hit",_hitpoint,_ammo,_newDamage,_realDamage,_directHit,_context); // Drowning doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index cdbb52a..b3eb716 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -22,4 +22,6 @@ #define PRIORITY_RIGHT_LEG (1 + random 1) #define PRIORITY_STRUCTURAL 1 +#define TYPE_UNIFORM 801 + #define GET_NUMBER(config,default) (if (isNumber (config)) then {getNumber (config)} else {default}) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index b185a02..b78c750 100644 --- a/addons/main/script_version.hpp +++ b/addons/main/script_version.hpp @@ -1,4 +1,4 @@ #define MAJOR 1 #define MINOR 0 -#define PATCHLVL 5 +#define PATCHLVL 6 #define BUILD 0