diff --git a/.hemtt/project.toml b/.hemtt/project.toml index 8d7e635..85af87c 100644 --- a/.hemtt/project.toml +++ b/.hemtt/project.toml @@ -14,3 +14,8 @@ include = [ "LICENSE", "README.md" ] + +[lints.sqf.var_all_caps] +options.ignore = [ + "NSM_JUMPPACK_DAMAGE_*", +] diff --git a/CHANGELOG.md b/CHANGELOG.md index ecbf7a1..703dba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Changelog for Armor Modifier - ACE 8.12.2024 + +1.0.4.0 +- Fixed bug where units were unkillable in Zeus. +- Removed backwards compatibility with ACE 3.17.1 +- Upped requirement from Arma 2.16 to Arma 2.18 + # Changelog for Armor Modifier - ACE 28.9.2024 1.0.3.0 diff --git a/addons/main/CfgVersioning.hpp b/addons/main/CfgVersioning.hpp index b8af963..9210835 100644 --- a/addons/main/CfgVersioning.hpp +++ b/addons/main/CfgVersioning.hpp @@ -4,7 +4,7 @@ class CfgSettings { class PREFIX { class Dependencies { ACE[] = {"ace_main", {3, 18, 0}, "true"}; - CBA[] = {"cba_main", {3, 16, 0}, "true"}; + CBA[] = {"cba_main", {3, 18, 0}, "true"}; }; }; }; diff --git a/addons/main/XEH_PREP.hpp b/addons/main/XEH_PREP.hpp index b8c1b8b..3b2bf28 100644 --- a/addons/main/XEH_PREP.hpp +++ b/addons/main/XEH_PREP.hpp @@ -1,5 +1 @@ -if (getNumber (configFile >> "CfgPatches" >> "ace_main" >> "version") >= 3.18) then { - PREP(handleDamage,handleDamage); -} else { - PREP(handleDamage,handleDamageOld); -}; +PREP(handleDamage); diff --git a/addons/main/config.cpp b/addons/main/config.cpp index 351d419..5a887c2 100644 --- a/addons/main/config.cpp +++ b/addons/main/config.cpp @@ -20,6 +20,4 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" - -// Don't force ACE version until 3.18.0 has been out for a while -// #include "CfgVersioning.hpp" +#include "CfgVersioning.hpp" diff --git a/addons/main/functions/fnc_handleDamage.sqf b/addons/main/functions/fnc_handleDamage.sqf index ab1ebfd..7e41b3c 100644 --- a/addons/main/functions/fnc_handleDamage.sqf +++ b/addons/main/functions/fnc_handleDamage.sqf @@ -37,7 +37,11 @@ if (_hitPoint isEqualTo "") then { // Damage can be disabled with old variable or via sqf command allowDamage if !(isDamageAllowed _unit && {_unit getVariable ["ace_medical_allowDamage", true] || _ignoreAllowDamageACE}) exitWith {_oldDamage}; +// Killing units via End key is an edge case (#10375) +// This didn't matter pre-Arma 3 2.18 but now this goes through the event handler +// TODO: Structural fire damage >= 1 in a single damage event could still be caught here and we don't want that, but we haven't found a better way to catch this, fire damage should be small most of the time anyway private _newDamage = _damage - _oldDamage; +if (_structuralDamage && {(abs (_newDamage - 1)) < 0.001 && _ammo == "" && isNull _shooter && isNull _instigator}) exitWith {_damage}; // _newDamage == 0 happens occasionally for vehiclehit events (see line 80 onwards), just exit early to save some frametime // context 4 is engine "bleeding". For us, it's just a duplicate event for #structural which we can ignore without any issues diff --git a/addons/main/functions/fnc_handleDamageOld.sqf b/addons/main/functions/fnc_handleDamageOld.sqf deleted file mode 100644 index e8ad79a..0000000 --- a/addons/main/functions/fnc_handleDamageOld.sqf +++ /dev/null @@ -1,263 +0,0 @@ -#include "..\script_component.hpp" -/* - * Author: commy2, kymckay, modified by johnb43 - * Original: - * HandleDamage EH where wound events are raised based on incoming damage. - * Be aware that for each source of damage, the EH can fire multiple times (once for each hitpoint). - * We store these incoming damages and compare them on our final hitpoint: "ace_hdbracket". - * Added: - * Handling of damage to allow armor modifcation. For ACE 3.17.1 and prior. - * - * Arguments: - * Handle damage EH - * - * Return Value: - * Damage to be inflicted - * - * Public: No - */ - -params ["_args", ["_ignoreAllowDamageACE", false]]; -_args params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint", "_directHit"]; - -// HD sometimes triggers for remote units - ignore. -if !(local _unit) exitWith {nil}; - -// Get missing meta info -private _oldDamage = 0; - -if (_hitPoint isEqualTo "") then { - _hitPoint = "#structural"; - _oldDamage = damage _unit; -} else { - _oldDamage = _unit getHitIndex _hitPointIndex; -}; - -// Damage can be disabled with old variable or via sqf command allowDamage -if !(isDamageAllowed _unit && {_unit getVariable ["ace_medical_allowDamage", true] || _ignoreAllowDamageACE}) exitWith {_oldDamage}; - -private _newDamage = _damage - _oldDamage; -// 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 _realDamage = _newDamage * _armor; - -// ACE <3.16.0 does not return "_armorScaled" -if (_hitPoint isNotEqualTo "#structural" && {!isNil "_armorScaled"}) then { - private _armorCoef = _armor / _armorScaled; - private _damageCoef = linearConversion [0, 1, ace_medical_engine_damagePassThroughEffect, 1, _armorCoef]; - _newDamage = _newDamage * _damageCoef; -}; - -TRACE_4("Received hit",_hitpoint,_ammo,_newDamage,_realDamage); - -// Drowning doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs -// Damage occurs in consistent increments -if ( - _hitPoint isEqualTo "#structural" && - {getOxygenRemaining _unit <= 0.5} && - {_damage isEqualTo (_oldDamage + 0.005)} -) exitWith { - TRACE_5("Drowning",_unit,_shooter,_instigator,_damage,_newDamage); - ["ace_medical_woundReceived", [_unit, [[_newDamage, "Body", _newDamage]], _unit, "drowning"]] call CBA_fnc_localEvent; - - 0 -}; - -// Crashing a vehicle doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs -// It does fire the EH multiple times, but this seems to scale with the intensity of the crash -private _vehicle = vehicle _unit; -if ( - ace_medical_enableVehicleCrashes && - {_hitPoint isEqualTo "#structural"} && - {_ammo isEqualTo ""} && - {!isNull _vehicle} && - {vectorMagnitude (velocity _vehicle) > 5} - // todo: no way to detect if stationary and another vehicle hits you -) exitWith { - TRACE_5("Crash",_unit,_shooter,_instigator,_damage,_newDamage); - ["ace_medical_woundReceived", [_unit, [[_newDamage, _hitPoint, _newDamage]], _unit, "vehiclecrash"]] call CBA_fnc_localEvent; - - 0 -}; - -// Receiving explosive damage inside a vehicle doesn't trigger for each hitpoint -// This is the case for mines, explosives, artillery, and catastrophic vehicle explosions -// Triggers twice, but that doesn't matter as damage is low -if ( - _hitPoint isEqualTo "#structural" && - {!isNull _vehicle} && - {_ammo isNotEqualTo ""} && - { - private _ammoCfg = configFile >> "CfgAmmo" >> _ammo; - GET_NUMBER(_ammoCfg >> "explosive",0) > 0 || - {GET_NUMBER(_ammoCfg >> "indirectHit",0) > 0} - } -) exitWith { - TRACE_6("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage,_damages); - - _unit setVariable ["ace_medical_lastDamageSource", _shooter]; - _unit setVariable ["ace_medical_lastInstigator", _instigator]; - - ["ace_medical_woundReceived", [_unit, [[_newDamage, _hitPoint, _newDamage]], _shooter, "vehiclehit"]] call CBA_fnc_localEvent; - - 0 -}; - -// This hitpoint is set to trigger last, evaluate all the stored damage values -// to determine where wounds are applied -if (_hitPoint isEqualTo "ace_hdbracket") exitWith { - _unit setVariable ["ace_medical_lastDamageSource", _shooter]; - _unit setVariable ["ace_medical_lastInstigator", _instigator]; - - private _damageStructural = _unit getVariable ["ace_medical_engine_$#structural", [0,0,0,0]]; - - // --- Head - private _damageHead = [ - _unit getVariable ["ace_medical_engine_$HitFace", [0,0,0,0]], - _unit getVariable ["ace_medical_engine_$HitNeck", [0,0,0,0]], - _unit getVariable ["ace_medical_engine_$HitHead", [0,0,0,0]] - ]; - _damageHead sort false; - _damageHead = _damageHead select 0; - - // --- Body - private _damageBody = [ - _unit getVariable ["ace_medical_engine_$HitPelvis", [0,0,0,0]], - _unit getVariable ["ace_medical_engine_$HitAbdomen", [0,0,0,0]], - _unit getVariable ["ace_medical_engine_$HitDiaphragm", [0,0,0,0]], - _unit getVariable ["ace_medical_engine_$HitChest", [0,0,0,0]] - // HitBody removed as it's a placeholder hitpoint and the high armor value (1000) throws the calculations off - ]; - _damageBody sort false; - _damageBody = _damageBody select 0; - - // --- Arms and Legs - private _damageLeftArm = _unit getVariable ["ace_medical_engine_$HitLeftArm", [0,0,0,0]]; - private _damageRightArm = _unit getVariable ["ace_medical_engine_$HitRightArm", [0,0,0,0]]; - private _damageLeftLeg = _unit getVariable ["ace_medical_engine_$HitLeftLeg", [0,0,0,0]]; - private _damageRightLeg = _unit getVariable ["ace_medical_engine_$HitRightLeg", [0,0,0,0]]; - - // Find hit point that received the maxium damage - // Priority used for sorting if incoming damage is equal - private _allDamages = [ - // Real damage (ignoring armor), Actual damage (with armor), Real damage modified (ignoring armor), Modified damage (with armor) - [_damageHead select 0, PRIORITY_HEAD, _damageHead select 1, "Head", _damageHead param [2, _damageHead select 0], _damageHead param [3, _damageHead select 1]], - [_damageBody select 0, PRIORITY_BODY, _damageBody select 1, "Body", _damageBody param [2, _damageBody select 0], _damageBody param [3, _damageBody select 1]], - [_damageLeftArm select 0, PRIORITY_LEFT_ARM, _damageLeftArm select 1, "LeftArm", _damageLeftArm param [2, _damageLeftArm select 0], _damageLeftArm param [3, _damageLeftArm select 1]], - [_damageRightArm select 0, PRIORITY_RIGHT_ARM, _damageRightArm select 1, "RightArm", _damageRightArm param [2, _damageRightArm select 0], _damageRightArm param [3, _damageRightArm select 1]], - [_damageLeftLeg select 0, PRIORITY_LEFT_LEG, _damageLeftLeg select 1, "LeftLeg", _damageLeftLeg param [2, _damageLeftLeg select 0], _damageLeftLeg param [3, _damageLeftLeg select 1]], - [_damageRightLeg select 0, PRIORITY_RIGHT_LEG, _damageRightLeg select 1, "RightLeg", _damageRightLeg param [2, _damageRightLeg select 0], _damageRightLeg param [3, _damageRightLeg select 1]], - [_damageStructural select 0, PRIORITY_STRUCTURAL, _damageStructural select 1, "#structural", _damageStructural param [2, _damageStructural select 0], _damageStructural param [3, _damageStructural select 1]] - ]; - TRACE_2("incoming",_allDamages,_damageStructural); - - _allDamages sort false; - // Use modified damages instead of initial ones - _allDamages = _allDamages apply {[_x select 5, _x select 3, _x select 4]}; - - // Environmental damage sources all have empty ammo string - // No explicit source given, we infer from differences between them - if (_ammo isEqualTo "") then { - // Any collision with terrain/vehicle/object has a shooter - // Check this first because burning can happen at any velocity - if !(isNull _shooter) then { - /* - If shooter != unit then they hit unit, otherwise it could be: - - Unit hitting anything at speed - - An empty vehicle hitting unit - - A physX object hitting unit - Assume fall damage for downward velocity because it's most common - */ - if (_shooter == _unit && {(velocity _unit select 2) < -2}) then { - _ammo = "falling"; - TRACE_5("Fall",_unit,_shooter,_instigator,_damage,_allDamages); - } else { - _ammo = "collision"; - TRACE_5("Collision",_unit,_shooter,_instigator,_damage,_allDamages); - }; - } else { - // Anything else is almost guaranteed to be fire damage - _ammo = "fire"; - TRACE_5("Fire Damage",_unit,_shooter,_instigator,_damage,_allDamages); - }; - }; - - // No wounds for minor damage - // TODO check if this needs to be changed for burning damage (occurs as lots of small events that we add together) - if ((_allDamages select 0 select 0) > 1E-3) then { - TRACE_1("received",_allDamages); - ["ace_medical_woundReceived", [_unit, _allDamages, _shooter, _ammo]] call CBA_fnc_localEvent; - }; - - // Clear stored damages otherwise they will influence future damage events - // (aka wounds will pile onto the historically most damaged hitpoint) - { - _unit setVariable [_x, nil]; - } forEach [ - "ace_medical_engine_$HitFace","ace_medical_engine_$HitNeck","ace_medical_engine_$HitHead", - "ace_medical_engine_$HitPelvis","ace_medical_engine_$HitAbdomen","ace_medical_engine_$HitDiaphragm","ace_medical_engine_$HitChest","ace_medical_engine_$HitBody", - "ace_medical_engine_$HitLeftArm","ace_medical_engine_$HitRightArm","ace_medical_engine_$HitLeftLeg","ace_medical_engine_$HitRightLeg", - "ace_medical_engine_$#structural" - ]; - - 0 -}; - -// Get setting for particular unit -private _multiplierArray = switch (true) do { - case (_hitPoint in ["hitface", "hitneck", "hithead"]): { - _unit getVariable [QGVAR(hitPointMultiplier_head), [GVAR(hitPointMultiplier_ai_head), GVAR(hitPointMultiplier_player_head)] select (isPlayer _unit)] - }; - case (_hitPoint in ["hitpelvis" ,"hitabdomen", "hitdiaphragm", "hitchest"]): { - _unit getVariable [QGVAR(hitPointMultiplier_chest), [GVAR(hitPointMultiplier_ai_chest), GVAR(hitPointMultiplier_player_chest)] select (isPlayer _unit)] - }; - case (_hitPoint in ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"]): { - _unit getVariable [QGVAR(hitPointMultiplier_limb), [GVAR(hitPointMultiplier_ai_limb), GVAR(hitPointMultiplier_player_limb)] select (isPlayer _unit)] - }; - default { - DEFAULT_SETTINGS - }; -}; - -private _modifiedNewDamage = _newDamage; -private _modifiedRealDamage = _realDamage; - -// If default settings, we don't need to change anything, so skip calculcations and let ace handle damage -if (_multiplierArray isNotEqualTo DEFAULT_SETTINGS) then { - _multiplierArray params ["_hitPointMultiplier", "_armorMin", "_armorMax"]; - - switch (true) do { - case (_armorMin >= 1 && {_armor < _armorMin}): { - // This will decrease damage - _modifiedNewDamage = _newDamage * _armor / _armorMin; - _modifiedRealDamage = _realDamage * _armor / _armorMin; - - TRACE_6("Under min armor",_armor,_armorMin,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage); - }; - case (_armorMax >= 1 && {_armor > _armorMax}): { - // This will increase damage - _modifiedNewDamage = _newDamage * _armor / _armorMax; - _modifiedRealDamage = _realDamage * _armor / _armorMax; - - TRACE_6("Over max armor",_armor,_armorMax,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage); - }; - }; - - _modifiedNewDamage = _modifiedNewDamage / _hitPointMultiplier; - _modifiedRealDamage = _modifiedRealDamage / _hitPointMultiplier; - - TRACE_5("Hitpoint damage multiplied",_armor,_newDamage,_modifiedNewDamage,_realDamage,_modifiedRealDamage); -}; - -// Damages are stored for "ace_hdbracket" event triggered last -_unit setVariable [format ["ace_medical_engine_$%1", _hitPoint], [_realDamage, _newDamage, _modifiedRealDamage, _modifiedNewDamage]]; - -// Engine damage to these hitpoints controls blood visuals, limping, weapon sway -// Handled in fnc_damageBodyPart, persist here -if (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"]) exitWith {_oldDamage}; - -// We store our own damage values so engine damage is unnecessary -0 diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 102bf43..cdbb52a 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -7,10 +7,10 @@ #ifdef DISABLE_COMPILE_CACHE #undef PREP - #define PREP(fncName,filename) DFUNC(fncName) = compile preprocessFileLineNumbers QPATHTOF(functions\DOUBLES(fnc,filename).sqf) + #define PREP(fncName) DFUNC(fncName) = compile preprocessFileLineNumbers QPATHTOF(functions\DOUBLES(fnc,fncName).sqf) #else #undef PREP - #define PREP(fncName,filename) [QPATHTOF(functions\DOUBLES(fnc,filename).sqf), QFUNC(fncName)] call CBA_fnc_compileFunction + #define PREP(fncName) [QPATHTOF(functions\DOUBLES(fnc,fncName).sqf), QFUNC(fncName)] call CBA_fnc_compileFunction #endif // #include "\z\ace\addons\medical_engine\script_component.hpp" diff --git a/addons/main/script_mod.hpp b/addons/main/script_mod.hpp index 719db23..ecfd9f8 100644 --- a/addons/main/script_mod.hpp +++ b/addons/main/script_mod.hpp @@ -8,6 +8,6 @@ #define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD // MINIMAL required version for the Mod. Components can specify others.. -#define REQUIRED_VERSION 2.16 +#define REQUIRED_VERSION 2.18 #define COMPONENT_NAME QUOTE(Armor Modifier - ACE) diff --git a/addons/main/script_version.hpp b/addons/main/script_version.hpp index 9636dec..c8e7104 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 3 +#define PATCHLVL 4 #define BUILD 0