Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Medical changes 2022 #44

Merged
merged 4 commits into from
Nov 6, 2022
Merged
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
124 changes: 123 additions & 1 deletion addons/ace_medical_tweaks/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,129 @@ class CfgPatches {
units[] = {};
weapons[] = {};
requiredAddons[] = {
"ace_medical_status"
"ace_medical_status",
"ace_medical_statemachine",
"ace_medical_damage",
"ace_medical_treatment"
};
};
};

// avoid the cardiac arrest state when receiving would-be-fatal damage,
// forcing unconsciousness instead
// note that this doesn't disable cardiac arrest completely - other logic
// can still enter that state, ie. very low blood / vitals checking code
class ACE_Medical_StateMachine {
class Default {
class FatalVitals {
targetState = "Unconscious";
events[] = {"ace_medical_FatalVitals"}; // split Bleedout
};
class FatalInjury {
targetState = "Dead";
//events[] = {QEGVAR(medical,FatalInjury)};
};
class Bleedout {
targetState = "Dead";
events[] = {"ace_medical_Bleedout"};
};
};
class Injured {
class FatalVitals {
targetState = "Unconscious";
events[] = {"ace_medical_FatalVitals"}; // split Bleedout
};
class FatalInjury {
targetState = "Dead";
//events[] = {QEGVAR(medical,FatalInjury)};
};
class Bleedout {
targetState = "Dead";
events[] = {"ace_medical_Bleedout"};
};
};
class Unconscious {
delete FatalTransitions;
class FatalInjury {
targetState = "Dead";
//events[] = {QEGVAR(medical,FatalInjury)};
};
class Bleedout {
targetState = "Dead";
events[] = {"ace_medical_Bleedout"};
};
};
};

class ACE_Medical_Injuries {
class wounds {
// make burns bleed a little bit, so they can be bandaged/stitched
// - unlike bruises, they don't produce other wounds that would bleed,
// and are rare enough to where bleeding probably doesn't matter
class ThermalBurn {
bleeding = 0.01;
};
};
class damageTypes {
// generally less wounds per bullet
class bullet {
//thresholds[] = {{20, 10}, {4.5, 2}, {3, 1}, {0, 1}};
thresholds[] = {{20, 6}, {5, 1}, {0, 1}};
delete Contusion;
};
// notably less wounds per small explosive effect, but at least 1
class grenade {
//thresholds[] = {{20, 10}, {10, 5}, {4, 3}, {1.5, 2}, {0.8, 2}, {0.3, 1}, {0, 0}};
thresholds[] = {{20, 8}, {10, 3}, {4, 2}, {0.3, 1}, {0, 0}};
class Contusion { weighting[] = {{0.5, 0}, {0.35, 0.2}}; };
};
// a lot of wounds for big damage, but very few for small damage
class explosive {
//thresholds[] = {{20, 15}, {8, 7}, {2, 3}, {1.2, 2}, {0.4, 1}, {0,0}};
thresholds[] = {{20, 15}, {8, 4}, {0.4, 1}, {0, 0}};
class Contusion { weighting[] = {{0.5, 0}, {0.35, 0.2}}; };
};
// shrapnel - same idea as explosive, but less wounds overall
class shell {
//thresholds[] = {{20, 10}, {10, 5}, {4.5, 2}, {2, 2}, {0.8, 1}, {0.2, 1}, {0, 0}};
thresholds[] = {{20, 10}, {10, 3}, {4, 2}, {0.2, 1}, {0, 0}};
class Cut { weighting[] = {{0.7, 0}, {0.35, 1}}; };
class Contusion { weighting[] = {{0.5, 0}, {0.35, 0.2}}; };
};
class vehiclecrash {
delete Contusion; // due to discrete weight ranges
};
class collision {
class Contusion { weighting[] = {{0.4, 0}, {0.2, 0.2}}; };
};
// fall damage - reduce overall bruise amount
class falling {
//thresholds[] = {{8, 4}, {1, 1}, {0.2, 1}, {0.1, 0.7}, {0, 0.5}};
thresholds[] = {{8, 3}, {1, 1}, {0.2, 1}, {0.1, 0.7}, {0, 0.5}};
class Contusion { weighting[] = {{0.4, 0}, {0.2, 0.2}}; };
};
// backblast - same idea as fall damage
class backblast {
//thresholds[] = {{1, 6}, {1, 5}, {0.55, 5}, {0.55, 2}, {0, 2}};
thresholds[] = {{1, 3}, {0.55, 2}, {0, 1}};
class Contusion { weighting[] = {{0.35, 0}, {0.35, 0.2}}; };
};
class punch {
class Contusion { weighting[] = {{0.35, 0}, {0.35, 0.2}}; };
};
};
};

class ace_medical_treatment {
class Medication {
class Morphine {
// lower the effect on heart rate, to avoid the need of many
// epinephrines to counter it + actually allow people to wake
// up without epinephrine use
hrIncreaseLow[] = {-1, -5};
hrIncreaseNormal[] = {-3, -8};
hrIncreaseHigh[] = {-6, -12};
timeTillMaxEffect = 10;
};
};
};
Expand Down
17 changes: 14 additions & 3 deletions addons/ace_medical_tweaks/custom_hasStableVitals.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@

params ["_unit"];

//if (GET_BLOOD_VOLUME(_unit) < BLOOD_VOLUME_CLASS_2_HEMORRHAGE) exitWith { false };
// if lost "a large amount of blood"
// && doesn't have epinephrine in the system || does and is unlucky,
// then do not wake up
//
// note that this assumes 100% wakeup chance *while epi is in the system*
// eg. maximum spontaneousWakeUpEpinephrineBoost, and this 100% is reduced
// further by the 'random' command
//if (
// GET_BLOOD_VOLUME(_unit) < BLOOD_VOLUME_CLASS_3_HEMORRHAGE
// ) exitWith { false };
//&& {[_unit, "Epinephrine"] call ace_medical_status_fnc_getMedicationCount == 0 || false}

if IN_CRDC_ARRST(_unit) exitWith { false };

//private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
Expand All @@ -11,9 +22,9 @@ if IN_CRDC_ARRST(_unit) exitWith { false };

private _bloodPressure = GET_BLOOD_PRESSURE(_unit);
_bloodPressure params ["_bloodPressureL", "_bloodPressureH"];
if (_bloodPressureL < 50 || {_bloodPressureH < 60}) exitWith { false };
if (_bloodPressureL < 40 || {_bloodPressureH < 60}) exitWith { false };

private _heartRate = GET_HEART_RATE(_unit);
if (_heartRate < 40) exitWith { false };

true
true;
43 changes: 43 additions & 0 deletions addons/ace_medical_tweaks/heal_hitpoints/config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class CfgPatches {
class cnto_ace_medical_tweaks_heal_hitpoints {
units[] = {};
weapons[] = {};
magazines[] = {};
requiredAddons[] = {
"cba_events",
"cba_xeh",
"ace_medical",
"ace_medical_engine",
"ace_medical_gui",
"ace_medical_damage"
};
};
};

class CfgFunctions {
class cnto_ace_medical_tweaks_heal_hitpoints {
class all {
file = "\cnto\additions\ace_medical_tweaks\heal_hitpoints";
class init;
class onStitch;
};
class overriden {
class orig_updateBodyImage {
file = "z\ace\addons\medical_gui\functions\fnc_updateBodyImage.sqf";
};
};
};
class ace_medical_gui {
class all {
class updateBodyImage {
file = "\cnto\additions\ace_medical_tweaks\heal_hitpoints\custom_updateBodyImage.sqf";
};
};
};
};

class Extended_PreInit_EventHandlers {
class cnto_ace_medical_tweaks_heal_hitpoints {
init = "[] call cnto_ace_medical_tweaks_heal_hitpoints_fnc_init";
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#define PREFIX ace
#include "\x\cba\addons\main\script_macros_common.hpp"
#include "\z\ace\addons\medical_engine\script_macros_medical.hpp"

params ["_ctrl", "_target"];

// collect damage/trauma from all wounds (used only for blue GUI coloring)
//
// this is basically the same as ACE natively calculating it for
// ace_medical_bodyPartDamage, except we can display it independently
// of the real ace_medical_bodyPartDamage set for the _target unit

private _trauma = [0,0,0,0,0,0];

// count only fully auto-treated bruises,
// see fn_onStitch.sqf for the params
{
_x params ["_classID", "_bodypartIndex", "_amountOf", "_bloodloss", "_damage"];
if (_amountOf == 0) then { continue };
private _wound_name = ace_medical_damage_woundClassNamesComplex select _classID;
if (_wound_name find "Contusion" == 0) then {
private _orig = _trauma select _bodypartIndex;
_trauma set [_bodypartIndex, _orig + _amountOf*_damage];
};
} forEach GET_OPEN_WOUNDS(_target);

{
_x params ["_classID", "_bodypartIndex", "_amountOf", "_bloodloss", "_damage"];
private _orig = _trauma select _bodypartIndex;
_trauma set [_bodypartIndex, _orig + _amountOf*_damage];
} forEach (GET_BANDAGED_WOUNDS(_target) + GET_STITCHED_WOUNDS(_target));

// the default is to use the darkest blue even for medium-ish
// wounds - tone it down, so darker blue is reserved only for
// heavier ones
_trauma = _trauma apply { _x * 0.3 };

// fool the original ACE updateBodyImage function
// by faking bodyPartDamage for the duration of the function run
// - this works reliably because we run unscheduled
private _backup = _target getVariable ["ace_medical_bodyPartDamage", [0,0,0,0,0,0]];
_target setVariable ["ace_medical_bodyPartDamage", _trauma];
_this call cnto_ace_medical_tweaks_heal_hitpoints_fnc_orig_updateBodyImage;
_target setVariable ["ace_medical_bodyPartDamage", _backup];
13 changes: 13 additions & 0 deletions addons/ace_medical_tweaks/heal_hitpoints/fn_init.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
["CBA_settingsInitialized", {
// just to make sure it's not enabled
ace_medical_treatment_clearTrauma = 0;
}] call CBA_fnc_addEventHandler;

["ace_treatmentSucceded", {
params ["_medic", "_patient", "_bodyPart", "_classname"];
if (_classname != "SurgicalKit") exitWith {};
if (!local _patient) exitWith {
["ace_treatmentSucceded", _this, _patient] call CBA_fnc_targetEvent;
};
_patient call cnto_ace_medical_tweaks_heal_hitpoints_fnc_onStitch;
}] call CBA_fnc_addEventHandler;
70 changes: 70 additions & 0 deletions addons/ace_medical_tweaks/heal_hitpoints/fn_onStitch.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#define PREFIX ace
#include "\x\cba\addons\main\script_macros_common.hpp"
#include "\z\ace\addons\medical_engine\script_macros_medical.hpp"

private _restore_hit_idx = [true,true,true,true,true,true];

// open wound entries persist even after bandaging/stitching
{
_x params ["_classID", "_bodypartIndex", "_amountOf", "_bloodloss", "_damage"];

// bandaged/stitched, nothing open remains;
// used for partially bandaged wounds
if (_amountOf == 0) then { continue };

// don't ask me why
private _wound_name = ace_medical_damage_woundClassNamesComplex select _classID;
// treat bruises as always bandaged/stitched
if (_wound_name find "Contusion" == 0) then { continue };

// finally, an untreated open wound;
_restore_hit_idx set [_bodypartIndex, false];
} forEach GET_OPEN_WOUNDS(_this);

// bandaged wounds are easier - they disappear after stitching
{
_x params ["_classID", "_bodypartIndex", "_amountOf", "_bloodloss", "_damage"];
_restore_hit_idx set [_bodypartIndex, false];
} forEach GET_BANDAGED_WOUNDS(_this);


// if a body part made it this far, it doesn't contain any
// unstitched wounds - restore lost trauma

// restore vanilla game hitpoints

private _current = _this getHitPointDamage "hitHead";
if (_current > 0 && _restore_hit_idx select HITPOINT_INDEX_HEAD) then {
_this setHitPointDamage ["hitHead", 0];
};

_current = _this getHitPointDamage "hitBody";
if (_current > 0 && _restore_hit_idx select HITPOINT_INDEX_BODY) then {
_this setHitPointDamage ["hitBody", 0];
};

_current = _this getHitPointDamage "hitHands";
if (_current > 0 && _restore_hit_idx select HITPOINT_INDEX_LARM && _restore_hit_idx select HITPOINT_INDEX_RARM) then {
_this setHitPointDamage ["hitHands", 0];
};

_current = _this getHitPointDamage "hitLegs";
if (_current > 0 && _restore_hit_idx select HITPOINT_INDEX_LLEG && _restore_hit_idx select HITPOINT_INDEX_RLEG) then {
_this setHitPointDamage ["hitLegs", 0];
};

// update ACE trauma

private _ace_damage_old = _this getVariable ["ace_medical_bodyPartDamage", [0,0,0,0,0,0]];
private _ace_damage_new = +_ace_damage_old;

{
if (_x) then {
_ace_damage_new set [_forEachIndex, 0];
};
} forEach _restore_hit_idx;

// avoid unnecessary network traffic
if (_ace_damage_new isNotEqualTo _ace_damage_old) then {
_this setVariable ["ace_medical_bodyPartDamage", _ace_damage_new, true];
};