diff --git a/addons/medical/dev/watchVariable.sqf b/addons/medical/dev/watchVariable.sqf index b09a0f7144..0d02a74e19 100644 --- a/addons/medical/dev/watchVariable.sqf +++ b/addons/medical/dev/watchVariable.sqf @@ -61,7 +61,7 @@ GVAR(dev_watchVariableRunning) = true; // Damage: private _damage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _limping = if (_unit getVariable [QEGVAR(medical,isLimping), false]) then {"[ Limping ]"} else {""}; - _return pushBack format ["Damage: [H: %1] [B: %2] %3", (_damage select 0) toFixed 2, (_damage select 1) toFixed 2]; + _return pushBack format ["BodyPartDamage: [H: %1] [B: %2]", (_damage select 0) toFixed 2, (_damage select 1) toFixed 2]; _return pushBack format ["[LA:%1] [RA: %2] [LL:%3] [RL: %4]", (_damage select 2) toFixed 2, (_damage select 3) toFixed 2, (_damage select 4) toFixed 2, (_damage select 5) toFixed 2]; _return pushBack format ["Hitpoints: [HHed:%1] [HBod: %2]", (_unit getHitPointDamage "HitHead") toFixed 2, (_unit getHitPointDamage "HitBody") toFixed 2]; diff --git a/addons/medical_damage/XEH_PREP.hpp b/addons/medical_damage/XEH_PREP.hpp index ad2055ccc5..7f3a5b1102 100644 --- a/addons/medical_damage/XEH_PREP.hpp +++ b/addons/medical_damage/XEH_PREP.hpp @@ -1,3 +1,4 @@ +PREP(determineIfFatal); PREP(getTypeOfDamage); PREP(handleIncapacitation); PREP(parseConfigForInjuries); diff --git a/addons/medical_damage/functions/fnc_determineIfFatal.sqf b/addons/medical_damage/functions/fnc_determineIfFatal.sqf new file mode 100644 index 0000000000..fc674cf75b --- /dev/null +++ b/addons/medical_damage/functions/fnc_determineIfFatal.sqf @@ -0,0 +1,62 @@ +#include "script_component.hpp" +/* + * Author: PabstMirror, Glowbal + * Determines if damage is fatal + * + * Arguments: + * 0: The Unit + * 1: Part No + * 2: Damage Array - QGVAR(medical,bodyPartDamage) + * 3: New Damage + * + * ReturnValue: + * Was Fatal + * + * Example: + * [player, 0, 1.4, 0.7] call ace_medical_damage_fnc_determineIfFatal + * + * Public: No + */ + +#define WEIBULL_K 6.5625 +#define WEIBULL_L 0.704523 + +params ["_unit", "_part", "_bodyPartDamage", "_woundDamage"]; + +if (_part > 1) exitWith { false }; + +scopeName "main"; + +if (EGVAR(medical,fatalDamageSource) in [0, 2]) then { + // Emulate damage to vital organs - Original rewrite logic, only powerfull headshots or random torso shots + if (_part == 0 && {_woundDamage >= HEAD_DAMAGE_THRESHOLD}) exitWith { + // Fatal damage to the head is guaranteed death + TRACE_1("determineIfFatal: lethal headshot",_woundDamage); + true breakOut "main"; + }; + if (_part == 1 && {_woundDamage >= ORGAN_DAMAGE_THRESHOLD} && {random 1 < HEART_HIT_CHANCE}) exitWith { + // Fatal damage to torso has various results based on organ hit - Heart shot is lethal + TRACE_1("determineIfFatal: lethal heartshot",_woundDamage); + true breakOut "main"; + }; +}; +if (EGVAR(medical,fatalDamageSource) in [1, 2]) then { + // Sum of trauma to critical areas can be fatal (e.g. many small hits) + private _damageThreshold = if (isPlayer _unit) then { EGVAR(medical,playerDamageThreshold) } else { EGVAR(medical,AIDamageThreshold) }; + private _headThreshhold = 1.25 * _damageThreshold; + private _bodyThreshhold = 1.5 * _damageThreshold; + + _bodyPartDamage params ["_headDamage", "_bodyDamage"]; + + private _vitalDamage = ((_headDamage - _headThreshhold) max 0) + ((_bodyDamage - _bodyThreshhold) max 0); + private _chanceFatal = 1 - exp -((_vitalDamage/WEIBULL_L)^WEIBULL_K); + TRACE_3("",_bodyPartDamage,_vitalDamage,_chanceFatal); + + if (_chanceFatal > random 1) exitWith { + TRACE_1("determineIfFatal: lethal trauma",_woundDamage); + true breakOut "main"; + }; +}; + +false + diff --git a/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf b/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf index 969dc257fd..ee07f8508e 100644 --- a/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf +++ b/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf @@ -121,26 +121,16 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then { _critialDamage = true; }; + if ([_unit, _bodyPartNToAdd, _bodyPartDamage, _woundDamage] call FUNC(determineIfFatal)) then { + TRACE_1("determineIfFatal returned true",_woundDamage); + [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; + }; #ifdef DEBUG_MODE_FULL systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, _woundDamage toFixed 2, _woundDamage > PENETRATION_THRESHOLD, _bleeding toFixed 3, _pain toFixed 3]; #endif - // Emulate damage to vital organs switch (true) do { - // Fatal damage to the head is guaranteed death - case (_bodyPartNToAdd == 0 && {_woundDamage >= HEAD_DAMAGE_THRESHOLD}): { - TRACE_1("lethal headshot",_woundDamage toFixed 2); - [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; - }; - // Fatal damage to torso has various results based on organ hit - case (_bodyPartNToAdd == 1 && {_woundDamage >= ORGAN_DAMAGE_THRESHOLD}): { - // Heart shot is lethal - if (random 1 < HEART_HIT_CHANCE) then { - TRACE_1("lethal heartshot",_woundDamage toFixed 2); - [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; - }; - }; case (_causeFracture && {EGVAR(medical,fractures) > 0} && {_bodyPartNToAdd > 1} && {_woundDamage > FRACTURE_DAMAGE_THRESHOLD}): { TRACE_1("limb fracture",_bodyPartNToAdd); private _fractures = GET_FRACTURES(_unit); diff --git a/addons/medical_damage/initSettings.sqf b/addons/medical_damage/initSettings.sqf index 25a153739c..e508f74621 100644 --- a/addons/medical_damage/initSettings.sqf +++ b/addons/medical_damage/initSettings.sqf @@ -1,3 +1,12 @@ +[ + QEGVAR(medical,fatalDamageSource), + "LIST", + [LSTRING(fatalDamageSource_DisplayName), LSTRING(fatalDamageSource_Description)], + [ELSTRING(medical,Category)], + [[0, 1, 2], [LSTRING(fatalDamageSource_vitalShotsOnly), LSTRING(fatalDamageSource_trauma), LSTRING(fatalDamageSource_both)], 0], + true +] call CBA_settings_fnc_init; + [ QEGVAR(medical,playerDamageThreshold), "SLIDER", diff --git a/addons/medical_damage/script_component.hpp b/addons/medical_damage/script_component.hpp index c567aeeae7..272dc7d565 100644 --- a/addons/medical_damage/script_component.hpp +++ b/addons/medical_damage/script_component.hpp @@ -4,7 +4,7 @@ // #define DEBUG_MODE_FULL // #define DISABLE_COMPILE_CACHE -//#define ENABLE_PERFORMANCE_COUNTERS +// #define ENABLE_PERFORMANCE_COUNTERS #ifdef DEBUG_ENABLED_MEDICAL_DAMAGE #define DEBUG_MODE_FULL diff --git a/addons/medical_damage/stringtable.xml b/addons/medical_damage/stringtable.xml index cc1ba5b6f6..6ac2818879 100644 --- a/addons/medical_damage/stringtable.xml +++ b/addons/medical_damage/stringtable.xml @@ -477,5 +477,20 @@ 大きな刺し傷 대형 관통상 + + Fatal Damage Source + + + Determines what damage can be fatal + + + Only large hits to vital organs + + + Sum of trauma + + + Either + diff --git a/addons/medical_treatment/functions/fnc_bandageLocal.sqf b/addons/medical_treatment/functions/fnc_bandageLocal.sqf index f001d2f0c1..3f16f3ca76 100644 --- a/addons/medical_treatment/functions/fnc_bandageLocal.sqf +++ b/addons/medical_treatment/functions/fnc_bandageLocal.sqf @@ -18,6 +18,7 @@ */ params ["_patient", "_bodyPart", "_bandage"]; +TRACE_3("bandageLocal",_patient,_bodyPart,_bandage); private _partIndex = ALL_BODY_PARTS find toLower _bodyPart; if (_partIndex < 0) exitWith {false}; @@ -54,4 +55,26 @@ if ((EGVAR(medical,limping) == 1) && {_partIndex > 3} && {_amountOf <= 0} && {_p [_patient] call EFUNC(medical_engine,updateDamageEffects); }; +if (GVAR(clearTraumaAfterBandage)) then { + TRACE_2("clearTraumaAfterBandage - checking open wounds",_partIndex,_openWounds); + if ((_openWounds findIf { + _x params ["", "_xBodyPartN", "_xAmountOf"]; + (_partIndex ==_xBodyPartN) && {_xAmountOf > 0} + }) == -1) then { + + private _bodyPartDamage = _patient getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; + _bodyPartDamage set [_partIndex, 0]; + _patient setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; + TRACE_2("fully healed",_partIndex,_bodyPartDamage); + + switch (_partIndex) do { + case 0: { [_patient, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case 1: { [_patient, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case 2; + case 3: { [_patient, false, false, true, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + default { [_patient, false, false, false, true] call EFUNC(medical_engine,updateBodyPartVisuals); }; + }; + }; +}; + true diff --git a/addons/medical_treatment/initSettings.sqf b/addons/medical_treatment/initSettings.sqf index f2956877f2..7e4eda5e98 100644 --- a/addons/medical_treatment/initSettings.sqf +++ b/addons/medical_treatment/initSettings.sqf @@ -29,6 +29,15 @@ true ] call CBA_settings_fnc_init; +[ + QGVAR(clearTraumaAfterBandage), + "CHECKBOX", + [LSTRING(clearTraumaAfterBandage_DisplayName), LSTRING(clearTraumaAfterBandage_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory_Treatment)], + false, + true +] call CBA_settings_fnc_init; + [ QGVAR(advancedMedication), "CHECKBOX", diff --git a/addons/medical_treatment/stringtable.xml b/addons/medical_treatment/stringtable.xml index a4c75679e6..675e39f5ea 100644 --- a/addons/medical_treatment/stringtable.xml +++ b/addons/medical_treatment/stringtable.xml @@ -3687,5 +3687,23 @@ 个人急救包使用条件 個人急救包使用條件 + + Clear Trauma After Bandage + + + Heal fully bandaged hitpoints + Lecz w pełni zabandażowane hitpointy + Curar miembros totalmente vendados + Исцелять полностью перебинтованные части тела + Curar pontos de vida totalmente enfaixados + Heal fully bandaged hitpoints + Cura hitpoints completamente bendati + Soigner les plaies entièrement bandées + Heilt vollständig bandagierte Trefferpunkte + 包帯は体力を完全に回復する + 붕대를 감은후 체력을 회복함 + 完全医疗包扎的部位至痊愈 + 完全醫療包紮的部位至痊癒 +