Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions addons/medical/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ PREP(isInStableCondition);
PREP(isInjured);
PREP(serializeState);
PREP(setUnconscious);
PREP(sortStatement_armor);
PREP(statBarStatement_armor);
PREP(statTextStatement_armor);
14 changes: 14 additions & 0 deletions addons/medical/arsenal/ACE_Arsenal_Sorts.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class EGVAR(arsenal,sorts) {
class sortBase;
class ACE_protectionBallistic: sortBase {
condition = QUOTE(!(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)])); // Hide if medical is enabled
};
class ACE_protectionExplosive: ACE_protectionBallistic {
condition = QUOTE(!(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)])); // Hide if medical is enabled
};
class GVAR(armor): ACE_protectionBallistic {
displayName = CSTRING(sortByArmorText);
condition = QUOTE(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)]); // Show if medical is enabled
statement = QUOTE(call FUNC(sortStatement_armor));
};
};
17 changes: 17 additions & 0 deletions addons/medical/arsenal/ACE_Arsenal_Stats.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class EGVAR(arsenal,stats) {
class statBase;
class ACE_ballisticProtection: statBase {
condition = QUOTE(!(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)])); // Hide if medical is enabled
};
class ACE_explosiveResistance: statBase {
condition = QUOTE(!(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)])); // Hide if medical is enabled
};
class GVAR(armor): ACE_ballisticProtection {
displayName = "$STR_UI_ABAR";
condition = QUOTE(missionNamespace getVariable [ARR_2(QQEGVAR(medical,enabled),false)]); // Show if medical is enabled
showBar = 1;
barStatement = QUOTE((_this select 1) call FUNC(statBarStatement_armor));
showText = 1;
textStatement = QUOTE((_this select 1) call FUNC(statTextStatement_armor));
};
};
19 changes: 19 additions & 0 deletions addons/medical/arsenal/config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "script_component.hpp"

class CfgPatches {
class SUBADDON {
addonRootClass = QUOTE(COMPONENT);
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"ace_medical_engine",
"ace_arsenal"
};
skipWhenMissingDependencies = 1;
VERSION_CONFIG;
};
};

#include "ACE_Arsenal_Stats.hpp"
#include "ACE_Arsenal_Sorts.hpp"
3 changes: 3 additions & 0 deletions addons/medical/arsenal/script_component.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define SUBCOMPONENT arsenal
#define SUBCOMPONENT_BEAUTIFIED Arsenal
#include "..\script_component.hpp"
23 changes: 23 additions & 0 deletions addons/medical/functions/fnc_sortStatement_armor.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Statement to sort items by their armor level.
*
* Arguments:
* 0: Item Config <CONFIG>
*
* Return Value:
* Sorting Value <NUMBER>
*
* Public: No
*/

params ["_config"];

// Same classification the armor penetration model and the armor stat use
private _itemType = getNumber (_config >> "ItemInfo" >> "type");
private _hitpoint = ["HitChest", "HitHead"] select (_itemType == TYPE_HEADGEAR);

([configName _config, _hitpoint] call EFUNC(medical_engine,getItemPlate)) params ["_armorLevel"];

_armorLevel
29 changes: 29 additions & 0 deletions addons/medical/functions/fnc_statBarStatement_armor.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Bar statement for armor.
*
* Arguments:
* 0: Item config path <CONFIG>
*
* Return Value:
* Bar statement <NUMBER>
*
* Public: No
*/

params ["_config"];

// Use the same classification the armor penetration model uses, so the arsenal can't disagree
// with what actually happens when the wearer gets shot
private _itemType = getNumber (_config >> "ItemInfo" >> "type");
private _isHeadgear = _itemType == TYPE_HEADGEAR;

private _hitpoint = ["HitChest", "HitHead"] select _isHeadgear;
// Ceilings are equal today, but headgear is rated against different threats than plates, so keep
// the bar normalised per type in case they diverge again
private _maxLevel = [MAX_PLATE_LEVEL, MAX_HELMET_LEVEL] select _isHeadgear;

([configName _config, _hitpoint] call EFUNC(medical_engine,getItemPlate)) params ["_armorLevel"];

0.01 max (_armorLevel / _maxLevel) min 1
34 changes: 34 additions & 0 deletions addons/medical/functions/fnc_statTextStatement_armor.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Text statement for armor.
*
* Arguments:
* 0: Item config path <CONFIG>
*
* Return Value:
* Stat Text <STRING>
*
* Public: No
*/

params ["_config"];

// Use the same classification the armor penetration model uses, so the arsenal can't disagree
// with what actually happens when the wearer gets shot
private _itemType = getNumber (_config >> "ItemInfo" >> "type");
private _hitpoint = ["HitChest", "HitHead"] select (_itemType == TYPE_HEADGEAR);

([configName _config, _hitpoint] call EFUNC(medical_engine,getItemPlate)) params ["_armorLevel"];

// Levels are continuous (a blend of the armor and passThrough readings), round for display
_armorLevel = 0 max (round _armorLevel) min MAX_PLATE_LEVEL;

localize ([
"STR_A3_SP_NOARMOR",
"STR_A3_SP_AL_I",
"STR_A3_SP_AL_II",
"STR_A3_SP_AL_III",
"STR_A3_SP_AL_IV",
"STR_A3_SP_AL_V"
] select _armorLevel)
3 changes: 3 additions & 0 deletions addons/medical/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@
<Hungarian>Játékosok és AI</Hungarian>
<Ukrainian>Гравців і ботів</Ukrainian>
</Key>
<Key ID="STR_ACE_Medical_sortByArmorText">
<English>Sort by armor level</English>
</Key>
<Key ID="STR_ACE_Medical_spontaneousWakeUpEpinephrineBoost_Description">
<English>When an unconscious patient has Epinephrine in their system, the time between spontaneous wake up checks is divided by this value.</English>
<Czech>Zvyšuje jak často je proveden test na probuzení z bezvědomí pokud má pacient Epinefrin ve svém krevním oběhu.</Czech>
Expand Down
3 changes: 3 additions & 0 deletions addons/medical_damage/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ call FUNC(parseConfigForInjuries);
// Used for armor penetration calculation
GVAR(ammoCache) = createHashMap;

// Resolved armor thickness/passThrough per uniform+vest+headgear+hitpoint combination
GVAR(armorLayerCache) = createHashMap;

/*
addMissionEventHandler ["Loaded",{
INFO("Mission Loaded - Reloading medical configs for extension");
Expand Down
20 changes: 13 additions & 7 deletions addons/medical_damage/functions/fnc_getAmmoData.sqf
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Returns base damage value, penetration factor, and expected muzzle velocity of a given round, either from a cache or by reading the ammo config.
* Returns base damage value, penetration multiplier, expected muzzle velocity and explosive fraction
* of a given round, either from a cache or by reading the ammo config.
*
* Arguments:
* 0: Ammo <STRING>
*
* Return Value:
* Base damage value, penetration factor, muzzle velocity <ARRAY of NUMBER>
* 0: Base damage value <NUMBER>
* 1: Penetration factor, mm RHA per m/s (caliber * penetrability) <NUMBER>
* 2: Muzzle velocity <NUMBER>
* 3: Fraction of damage that is explosive rather than kinetic, 0..1 <NUMBER>
*
* Example:
* "B_556x45_Ball" call ace_medical_damage_fnc_getAmmoData
*
* Public: No
*/

// Baseline penetrability used for armor penetration calculation, see (https://community.bistudio.com/wiki/CfgAmmo_Config_Reference#caliber)
// Penetration depth in mm is velocity * caliber * penetrability / 1000, RHA penetrability is 15
// ref https://community.bistudio.com/wiki/CfgAmmo_Config_Reference#caliber
#define ARMOR_PENETRABILITY 0.015

params ["_ammo"];
Expand All @@ -25,12 +30,13 @@ GVAR(ammoCache) getOrDefaultCall [toLowerANSI _ammo, {
private _ammoConfig = configFile >> "CfgAmmo" >> _ammo;

if (isNull _ammoConfig) then {
[0, 0, 0] // return
[0, 0, 0, 0] // return
} else {
private _hit = getNumber (_ammoConfig >> "hit");
private _caliber = getNumber (_ammoConfig >> "caliber");
private _penFactor = getNumber (_ammoConfig >> "caliber") * ARMOR_PENETRABILITY;
private _typicalSpeed = getNumber (_ammoConfig >> "typicalSpeed");
private _penFactor = _caliber * ARMOR_PENETRABILITY;
[_hit, _penFactor, _typicalSpeed] // return
// Some vanilla ammo goes above 1 (B_20mm is 1.8), clamp so callers can rely on the range
private _explosive = 0 max getNumber (_ammoConfig >> "explosive") min 1;
[_hit, _penFactor, _typicalSpeed, _explosive] // return
};
}, true]
Loading