Skip to content
Open
Show file tree
Hide file tree
Changes from all 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