From 131ef576b45b8257a7a3aa887cd9390fd0a25dfa Mon Sep 17 00:00:00 2001 From: Glowbal Date: Fri, 15 Jul 2016 12:23:47 +0200 Subject: [PATCH] Add medical treatments and configuration --- .../ACE_Medical_Treatments.hpp | 1065 +++++++++++++++++ addons/medical_treatment/XEH_PREP.hpp | 52 + .../fnc_actionCheckBloodPressure.sqf | 22 + .../fnc_actionCheckBloodPressureLocal.sqf | 64 + .../functions/fnc_actionCheckPulse.sqf | 22 + .../functions/fnc_actionCheckPulseLocal.sqf | 56 + .../functions/fnc_actionCheckResponse.sqf | 24 + .../functions/fnc_actionDiagnose.sqf | 46 + .../functions/fnc_actionLoadUnit.sqf | 30 + .../functions/fnc_actionPlaceInBodyBag.sqf | 52 + .../functions/fnc_actionRemoveTourniquet.sqf | 54 + .../functions/fnc_actionUnloadUnit.sqf | 24 + .../functions/fnc_addToLog.sqf | 50 + .../functions/fnc_addToTriageCard.sqf | 43 + .../functions/fnc_addUnloadPatientActions.sqf | 40 + .../functions/fnc_canTreat.sqf | 2 +- .../fnc_displayPatientInformation.sqf | 193 +++ .../functions/fnc_displayTriageCard.sqf | 76 ++ .../functions/fnc_dropDownTriageCard.sqf | 31 + .../functions/fnc_getTriageStatus.sqf | 28 + .../functions/fnc_handleBandageOpening.sqf | 120 ++ .../functions/fnc_hasItem.sqf | 41 + .../functions/fnc_hasItems.sqf | 31 + .../functions/fnc_isBeingCarried.sqf | 26 + .../functions/fnc_isBeingDragged.sqf | 26 + .../functions/fnc_medicationEffectLoop.sqf | 42 + .../functions/fnc_modifyMedicalAction.sqf | 37 + .../functions/fnc_onMedicationUsage.sqf | 80 ++ .../functions/fnc_treatment.sqf | 4 +- .../functions/fnc_treatmentAdvanced_CPR.sqf | 30 + .../fnc_treatmentAdvanced_CPRLocal.sqf | 35 + .../fnc_treatmentAdvanced_bandage.sqf | 38 + .../fnc_treatmentAdvanced_bandageLocal.sqf | 173 +++ .../fnc_treatmentAdvanced_fullHeal.sqf | 21 + .../fnc_treatmentAdvanced_fullHealLocal.sqf | 72 ++ ...reatmentAdvanced_fullHealTreatmentTime.sqf | 24 + .../fnc_treatmentAdvanced_medication.sqf | 36 + .../fnc_treatmentAdvanced_medicationLocal.sqf | 98 ++ ...eatmentAdvanced_surgicalKit_onProgress.sqf | 35 + .../functions/fnc_treatmentBasic_bloodbag.sqf | 25 + .../fnc_treatmentBasic_bloodbagLocal.sqf | 27 + .../functions/fnc_treatmentBasic_epipen.sqf | 24 + .../functions/fnc_treatmentBasic_morphine.sqf | 26 + .../fnc_treatmentBasic_morphineLocal.sqf | 27 + .../functions/fnc_treatmentIV.sqf | 35 + .../functions/fnc_treatmentIVLocal.sqf | 42 + .../functions/fnc_treatmentTourniquet.sqf | 48 + .../fnc_treatmentTourniquetLocal.sqf | 26 + .../functions/fnc_treatment_failure.sqf | 4 +- .../functions/fnc_treatment_success.sqf | 4 +- .../functions/fnc_useItem.sqf | 58 + .../functions/fnc_useItems.sqf | 37 + addons/medical_treatment/stringtable.xml | 5 + 53 files changed, 3324 insertions(+), 7 deletions(-) create mode 100644 addons/medical_treatment/ACE_Medical_Treatments.hpp create mode 100644 addons/medical_treatment/functions/fnc_actionCheckBloodPressure.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionCheckBloodPressureLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionCheckPulse.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionCheckPulseLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionCheckResponse.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionDiagnose.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionLoadUnit.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionPlaceInBodyBag.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionRemoveTourniquet.sqf create mode 100644 addons/medical_treatment/functions/fnc_actionUnloadUnit.sqf create mode 100644 addons/medical_treatment/functions/fnc_addToLog.sqf create mode 100644 addons/medical_treatment/functions/fnc_addToTriageCard.sqf create mode 100644 addons/medical_treatment/functions/fnc_addUnloadPatientActions.sqf create mode 100644 addons/medical_treatment/functions/fnc_displayPatientInformation.sqf create mode 100644 addons/medical_treatment/functions/fnc_displayTriageCard.sqf create mode 100644 addons/medical_treatment/functions/fnc_dropDownTriageCard.sqf create mode 100644 addons/medical_treatment/functions/fnc_getTriageStatus.sqf create mode 100644 addons/medical_treatment/functions/fnc_handleBandageOpening.sqf create mode 100644 addons/medical_treatment/functions/fnc_hasItem.sqf create mode 100644 addons/medical_treatment/functions/fnc_hasItems.sqf create mode 100644 addons/medical_treatment/functions/fnc_isBeingCarried.sqf create mode 100644 addons/medical_treatment/functions/fnc_isBeingDragged.sqf create mode 100644 addons/medical_treatment/functions/fnc_medicationEffectLoop.sqf create mode 100644 addons/medical_treatment/functions/fnc_modifyMedicalAction.sqf create mode 100644 addons/medical_treatment/functions/fnc_onMedicationUsage.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_CPR.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_CPRLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_bandage.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_bandageLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHeal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealTreatmentTime.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_medication.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_medicationLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentAdvanced_surgicalKit_onProgress.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentBasic_bloodbag.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentBasic_bloodbagLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentBasic_epipen.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentBasic_morphine.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentBasic_morphineLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentIV.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentIVLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentTourniquet.sqf create mode 100644 addons/medical_treatment/functions/fnc_treatmentTourniquetLocal.sqf create mode 100644 addons/medical_treatment/functions/fnc_useItem.sqf create mode 100644 addons/medical_treatment/functions/fnc_useItems.sqf create mode 100644 addons/medical_treatment/stringtable.xml diff --git a/addons/medical_treatment/ACE_Medical_Treatments.hpp b/addons/medical_treatment/ACE_Medical_Treatments.hpp new file mode 100644 index 0000000000..e7cb5e2b27 --- /dev/null +++ b/addons/medical_treatment/ACE_Medical_Treatments.hpp @@ -0,0 +1,1065 @@ + +class ACE_Medical_Treatments { + class Basic { + class Bandage { + displayName = ECSTRING(medical,Bandage); + displayNameProgress = ECSTRING(medical,Bandaging); + category = "bandage"; + treatmentLocations[] = {"All"}; + allowedSelections[] = {"All"}; + allowSelfTreatment = 1; + requiredMedic = 0; + treatmentTime = 5; + treatmentTimeSelfCoef = 1; + items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}}; + condition = ""; + patientStateCondition = 0; + itemConsumed = 1; + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_bandage)); + callbackFailure = ""; + callbackProgress = ""; + + animationPatient = ""; + animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; + animationPatientUnconsciousExcludeOn[] = {"ainjppnemstpsnonwrfldnon"}; + animationCaller = "AinvPknlMstpSlayWrflDnon_medicOther"; + animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther"; + animationCallerSelf = "AinvPknlMstpSlayW[wpn]Dnon_medic"; + animationCallerSelfProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; + litter[] = { + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection <= 0", {"ACE_MedicalLitter_clean"}} + }; + }; + class Morphine: Bandage { + displayName = ECSTRING(medical,Inject_Morphine); + displayNameProgress = ECSTRING(medical,Injecting_Morphine); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + allowSelfTreatment = 1; + category = "medication"; + treatmentTime = 2; + items[] = {"ACE_morphine"}; + callbackSuccess = QUOTE(DFUNC(treatmentBasic_morphine)); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = { {"All", "", {"ACE_MedicalLitter_morphine"}} }; + }; + class Epinephrine: Bandage { + displayName = ECSTRING(medical,Inject_Epinephrine); + displayNameProgress = ECSTRING(medical,Injecting_Epinephrine); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + allowSelfTreatment = 1; + category = "medication"; + requiredMedic = QEGVAR(medical,medicSetting_basicEpi); + treatmentTime = 3; + items[] = {"ACE_epinephrine"}; + callbackSuccess = QUOTE(DFUNC(treatmentBasic_epipen)); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = { {"All", "", {"ACE_MedicalLitter_epinephrine"}} }; + treatmentLocations[] = {QGVAR(useLocation_basicEpi)}; + }; + class BloodIV: Bandage { + displayName = ECSTRING(medical,Transfuse_Blood); + displayNameProgress = ECSTRING(medical,Transfusing_Blood); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + allowSelfTreatment = 0; + category = "advanced"; + requiredMedic = 1; + treatmentTime = 20; + items[] = {"ACE_bloodIV"}; + // callbackSuccess = QUOTE(DFUNC(treatmentBasic_bloodbag)); + callbackSuccess = QUOTE(DFUNC(treatmentIV)); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = {}; + }; + class BloodIV_500: BloodIV { + category = "advanced"; + items[] = {"ACE_bloodIV_500"}; + }; + class BloodIV_250: BloodIV { + category = "advanced"; + items[] = {"ACE_bloodIV_250"}; + }; + class BodyBag: Bandage { + displayName = ECSTRING(medical,PlaceInBodyBag); + displayNameProgress = ECSTRING(medical,PlacingInBodyBag); + category = "advanced"; + treatmentLocations[] = {"All"}; + requiredMedic = 0; + treatmentTime = 4; + items[] = {"ACE_bodyBag"}; + condition = "!alive (_this select 1);"; + callbackSuccess = QUOTE(DFUNC(actionPlaceInBodyBag)); + callbackFailure = ""; + callbackProgress = ""; + animationPatient = ""; + animationPatientUnconscious = ""; + itemConsumed = 1; + litter[] = {}; + }; + class Diagnose: Bandage { + displayName = ECSTRING(medical,Actions_Diagnose); + displayNameProgress = ECSTRING(medical,Actions_Diagnosing); + category = "examine"; + treatmentLocations[] = {"All"}; + allowedSelections[] = {"head", "body"}; + requiredMedic = 0; + treatmentTime = 1; + items[] = {}; + callbackSuccess = QUOTE(DFUNC(actionDiagnose)); + callbackFailure = ""; + callbackProgress = ""; + animationPatient = ""; + animationCaller = ""; // TODO + itemConsumed = 0; + litter[] = {}; + }; + class CPR: Bandage { + displayName = ECSTRING(medical,Actions_CPR); + displayNameProgress = ECSTRING(medical,Actions_PerformingCPR); + category = "advanced"; + treatmentLocations[] = {"All"}; + allowedSelections[] = {"body"}; + allowSelfTreatment = 0; + requiredMedic = 0; + treatmentTime = 15; + items[] = {}; + condition = QUOTE(!([(_this select 1)] call ace_common_fnc_isAwake) && EGVAR(medical,enableRevive)>0); + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_CPR)); + callbackFailure = ""; + callbackProgress = "!([((_this select 0) select 1)] call ace_common_fnc_isAwake)"; + animationPatient = ""; + animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; + animationCaller = "AinvPknlMstpSlayWnonDnon_medic"; + animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; + animationCallerSelf = ""; + animationCallerSelfProne = ""; + itemConsumed = 0; + litter[] = {}; + }; + }; + + class Advanced { + class FieldDressing { + displayName = ECSTRING(medical,Actions_FieldDressing); + displayNameProgress = ECSTRING(medical,Bandaging); + category = "bandage"; + // Which locations can this treatment action be used? Available: Field, MedicalFacility, MedicalVehicle, All. + treatmentLocations[] = {"All"}; + allowedSelections[] = {"All"}; + allowSelfTreatment = 1; + // What is the level of medical skill required for this treatment action? 0 = all soldiers, 1 = medic, 2 = doctor + requiredMedic = 0; + // The time it takes for a treatment action to complete. Time is in seconds. + treatmentTime = 8; + // Item required for the action. Leave empty for no item required. + items[] = {"ACE_fieldDressing"}; + condition = ""; + patientStateCondition = 0; + // Callbacks + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_bandage)); + callbackFailure = ""; + callbackProgress = ""; + itemConsumed = 1; + animationPatient = ""; + animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; + animationPatientUnconsciousExcludeOn[] = {"ainjppnemstpsnonwrfldnon"}; + animationCaller = "AinvPknlMstpSlayWrflDnon_medicOther"; + animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther"; + animationCallerSelf = "AinvPknlMstpSlayW[wpn]Dnon_medic"; + animationCallerSelfProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; + litter[] = { + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection <= 0", {"ACE_MedicalLitter_clean"}} + }; + }; + class PackingBandage: fieldDressing { + displayName = ECSTRING(medical,Actions_PackingBandage); + items[] = {"ACE_packingBandage"}; + litter[] = { + {"All", "", {"ACE_MedicalLitter_packingBandage"}}, + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection <= 0", {"ACE_MedicalLitter_clean"}} + }; + }; + class ElasticBandage: fieldDressing { + displayName = ECSTRING(medical,Actions_ElasticBandage); + items[] = {"ACE_elasticBandage"}; + }; + class QuikClot: fieldDressing { + displayName = ECSTRING(medical,Actions_QuikClot); + items[] = {"ACE_quikclot"}; + litter[] = { + {"All", "", {"ACE_MedicalLitter_QuickClot"}}, + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection <= 0", {"ACE_MedicalLitter_clean"}} + }; + }; + class Tourniquet: fieldDressing { + displayName = ECSTRING(medical,Apply_Tourniquet); + displayNameProgress = ECSTRING(medical,Applying_Tourniquet); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + items[] = {"ACE_tourniquet"}; + treatmentTime = 4; + callbackSuccess = QUOTE(DFUNC(treatmentTourniquet)); + condition = QUOTE(!([ARR_2(_this select 1, _this select 2)] call EFUNC(medical,hasTourniquetAppliedTo))); + litter[] = {}; + }; + class Morphine: fieldDressing { + displayName = ECSTRING(medical,Inject_Morphine); + displayNameProgress = ECSTRING(medical,Injecting_Morphine); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + category = "medication"; + items[] = {"ACE_morphine"}; + treatmentTime = 3; + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_medication)); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = { {"All", "", {"ACE_MedicalLitter_morphine"}} }; + }; + class Adenosine: Morphine { + displayName = ECSTRING(medical,Inject_Adenosine); + displayNameProgress = ECSTRING(medical,Injecting_Adenosine); + items[] = {"ACE_adenosine"}; + litter[] = { {"All", "", {"ACE_MedicalLitter_adenosine"}} }; + }; + class Atropine: Morphine { + displayName = ECSTRING(medical,Inject_Atropine); + displayNameProgress = ECSTRING(medical,Injecting_Atropine); + items[] = {"ACE_atropine"}; + litter[] = { {"All", "", {"ACE_MedicalLitter_atropine"}} }; + }; + class Epinephrine: Morphine { + displayName = ECSTRING(medical,Inject_Epinephrine); + displayNameProgress = ECSTRING(medical,Injecting_Epinephrine); + items[] = {"ACE_epinephrine"}; + litter[] = { {"All", "", {"ACE_MedicalLitter_epinephrine"}} }; + }; + class BloodIV: fieldDressing { + displayName = ECSTRING(medical,Actions_Blood4_1000); + displayNameProgress = ECSTRING(medical,Transfusing_Blood); + allowedSelections[] = {"hand_l", "hand_r", "leg_l", "leg_r"}; + allowSelfTreatment = 0; + category = "advanced"; + items[] = {"ACE_bloodIV"}; + requiredMedic = 1; + treatmentTime = 7; + callbackSuccess = QUOTE(DFUNC(treatmentIV)); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = {}; + }; + class BloodIV_500: BloodIV { + displayName = ECSTRING(medical,Actions_Blood4_500); + items[] = {"ACE_bloodIV_500"}; + }; + class BloodIV_250: BloodIV { + displayName = ECSTRING(medical,Actions_Blood4_250); + items[] = {"ACE_bloodIV_250"}; + }; + class PlasmaIV: BloodIV { + displayName = ECSTRING(medical,Actions_Plasma4_1000); + displayNameProgress = ECSTRING(medical,Transfusing_Plasma); + items[] = {"ACE_plasmaIV"}; + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + }; + class PlasmaIV_500: PlasmaIV { + displayName = ECSTRING(medical,Actions_Plasma4_500); + items[] = {"ACE_plasmaIV_500"}; + }; + class PlasmaIV_250: PlasmaIV { + displayName = ECSTRING(medical,Actions_Plasma4_250); + items[] = {"ACE_plasmaIV_250"}; + }; + class SalineIV: BloodIV { + displayName = ECSTRING(medical,Actions_Saline4_1000); + displayNameProgress = ECSTRING(medical,Transfusing_Saline); + items[] = {"ACE_salineIV"}; + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + }; + class SalineIV_500: SalineIV { + displayName = ECSTRING(medical,Actions_Saline4_500); + items[] = {"ACE_salineIV_500"}; + }; + class SalineIV_250: SalineIV { + displayName = ECSTRING(medical,Actions_Saline4_250); + items[] = {"ACE_salineIV_250"}; + }; + class SurgicalKit: fieldDressing { + displayName = ECSTRING(medical,Use_SurgicalKit); + displayNameProgress = ECSTRING(medical,Stitching); + category = "advanced"; + items[] = {"ACE_surgicalKit"}; + treatmentLocations[] = {QEGVAR(medical,useLocation_SurgicalKit)}; + allowSelfTreatment = 0; + requiredMedic = QEGVAR(medical,medicSetting_SurgicalKit); + patientStateCondition = QEGVAR(medical,useCondition_SurgicalKit); + treatmentTime = "(count ((_this select 1) getVariable ['ACE_Medical_bandagedWounds', []]) * 5)"; + callbackSuccess = ""; + callbackProgress = QUOTE(DFUNC(treatmentAdvanced_surgicalKit_onProgress)); + itemConsumed = QEGVAR(medical,consumeItem_SurgicalKit); + animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; + litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"} }}; + }; + class PersonalAidKit: fieldDressing { + displayName = ECSTRING(medical,Use_Aid_Kit); + displayNameProgress = ECSTRING(medical,TreatmentAction); + category = "advanced"; + items[] = {"ACE_personalAidKit"}; + treatmentLocations[] = {QEGVAR(medical,useLocation_PAK)}; + allowSelfTreatment = 0; + requiredMedic = QEGVAR(medical,medicSetting_PAK); + patientStateCondition = QEGVAR(medical,useCondition_PAK); + treatmentTime = QUOTE((_this select 1) call FUNC(treatmentAdvanced_fullHealTreatmentTime)); + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_fullHeal)); + itemConsumed = QEGVAR(medical,consumeItem_PAK); + animationPatient = ""; + animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; + animationCaller = "AinvPknlMstpSlayWnonDnon_medicOther"; + animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther"; + animationCallerSelf = ""; + animationCallerSelfProne = ""; + litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"}}, + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}}, + {"All", "_bloodLossOnSelection <= 0", {"ACE_MedicalLitter_clean"}} + }; + }; + class CheckPulse: fieldDressing { + displayName = ECSTRING(medical,Actions_CheckPulse); + displayNameProgress = ECSTRING(medical,Check_Pulse_Content); + category = "examine"; + treatmentLocations[] = {"All"}; + requiredMedic = 0; + treatmentTime = 2; + items[] = {}; + callbackSuccess = QUOTE(DFUNC(actionCheckPulse)); + callbackFailure = ""; + callbackProgress = ""; + animationPatient = ""; + animationCaller = ""; // TODO + animationCallerProne = ""; + animationCallerSelfProne = ""; + itemConsumed = 0; + litter[] = {}; + }; + class CheckBloodPressure: CheckPulse { + displayName = ECSTRING(medical,Actions_CheckBloodPressure); + callbackSuccess = QUOTE(DFUNC(actionCheckBloodPressure)); + displayNameProgress = ECSTRING(medical,Check_Bloodpressure_Content); + }; + class CheckResponse: CheckPulse { + displayName = ECSTRING(medical,Check_Response); + callbackSuccess = QUOTE(DFUNC(actionCheckResponse)); + displayNameProgress = ECSTRING(medical,Check_Response_Content); + allowSelfTreatment = 0; + }; + class RemoveTourniquet: Tourniquet { + displayName = ECSTRING(medical,Actions_RemoveTourniquet); + items[] = {}; + treatmentTime = 2.5; + callbackSuccess = QUOTE(DFUNC(actionRemoveTourniquet)); + condition = QUOTE([ARR_2(_this select 1, _this select 2)] call EFUNC(medical,hasTourniquetAppliedTo)); + displayNameProgress = ECSTRING(medical,RemovingTourniquet); + litter[] = {}; + }; + class CPR: fieldDressing { + displayName = ECSTRING(medical,Actions_CPR); + displayNameProgress = ECSTRING(medical,Actions_PerformingCPR); + category = "advanced"; + treatmentLocations[] = {"All"}; + allowedSelections[] = {"body"}; + allowSelfTreatment = 0; + requiredMedic = 0; + treatmentTime = 15; + items[] = {}; + condition = "!([(_this select 1)] call ace_common_fnc_isAwake)"; + callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_CPR)); + callbackFailure = ""; + callbackProgress = "!([((_this select 0) select 1)] call ace_common_fnc_isAwake)"; + animationPatient = ""; + animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; + animationCaller = "AinvPknlMstpSlayWnonDnon_medic"; + animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medic"; + animationCallerSelf = ""; + animationCallerSelfProne = ""; + itemConsumed = 0; + litter[] = {}; + }; + class BodyBag: fieldDressing { + displayName = ECSTRING(medical,PlaceInBodyBag); + displayNameProgress = ECSTRING(medical,PlacingInBodyBag); + category = "advanced"; + treatmentLocations[] = {"All"}; + allowSelfTreatment = 0; + requiredMedic = 0; + treatmentTime = 15; + items[] = {"ACE_bodyBag"}; + condition = "!alive (_this select 1);"; + callbackSuccess = QUOTE(DFUNC(actionPlaceInBodyBag)); + callbackFailure = ""; + callbackProgress = ""; + animationPatient = ""; + animationPatientUnconscious = ""; + itemConsumed = 1; + litter[] = {}; + }; + }; +}; + +class ACE_Medical_Treatment { + class Bandaging { + // Field dressing is normal average treatment + // packing bandage is average treatment, higher reopen change, longer reopening delay + // elastic bandage is higher treatment, higher reopen change, shorter reopen delay + // quickclot is lower treatment, lower reopen change, longer reopening delay + class Bandage { // basic bandage + effectiveness = 5; + reopeningChance = 0; + reopeningMinDelay = 0; + reopeningMaxDelay = 0; + }; + + class FieldDressing { + // How effect is the bandage for treating one wounds type injury + effectiveness = 1; + // What is the chance and delays (in seconds) of the treated default injury reopening + reopeningChance = 0.1; + reopeningMinDelay = 120; + reopeningMaxDelay = 200; + + class Abrasion { + effectiveness = 3; + reopeningChance = 0.3; + reopeningMinDelay = 200; + reopeningMaxDelay = 1000; + }; + class AbrasionMinor: Abrasion { + effectiveness = 3; + }; + class AbrasionMedium: Abrasion { + effectiveness = 2.5; + reopeningChance = 0.7; + }; + class AbrasionLarge: Abrasion { + effectiveness = 2; + reopeningChance = 0.9; + }; + + class Avulsions: Abrasion { + effectiveness = 1; + reopeningChance = 0.5; + reopeningMinDelay = 120; + reopeningMaxDelay = 200; + }; + class AvulsionsMinor: Avulsions { + effectiveness = 1; + }; + class AvulsionsMedium: Avulsions { + effectiveness = 0.9; + }; + class AvulsionsLarge: Avulsions { + effectiveness = 0.75; + }; + + class Contusion: Abrasion { + effectiveness = 1; + reopeningChance = 0; + reopeningMinDelay = 0; + reopeningMaxDelay = 0; + }; + class ContusionMinor: Contusion {}; + class ContusionMedium: Contusion {}; + class ContusionLarge: Contusion {}; + + class CrushWound: Abrasion { + effectiveness = 1; + reopeningChance = 0.2; + reopeningMinDelay = 20; + reopeningMaxDelay = 1000; + }; + class CrushWoundMinor: CrushWound { + effectiveness = 1; + reopeningChance = 0.2; + }; + class CrushWoundMedium: CrushWound { + effectiveness = 0.7; + reopeningChance = 0.3; + }; + class CrushWoundLarge: CrushWound { + effectiveness = 0.6; + reopeningChance = 0.4; + }; + + class Cut: Abrasion { + effectiveness = 4; + reopeningChance = 0.1; + reopeningMinDelay = 300; + reopeningMaxDelay = 1000; + }; + class CutMinor: Cut { + effectiveness = 4; + reopeningChance = 0.1; + }; + class CutMedium: Cut { + effectiveness = 3; + reopeningChance = 0.3; + }; + class CutLarge: Cut { + effectiveness = 1; + reopeningChance = 0.5; + }; + + class Laceration: Abrasion { + effectiveness = 0.95; + reopeningChance = 0.3; + reopeningMinDelay = 100; + reopeningMaxDelay = 800; + }; + class LacerationMinor: Laceration { + effectiveness = 0.95; + reopeningChance = 0.3; + }; + class LacerationMedium: Laceration { + effectiveness = 0.7; + reopeningChance = 0.5; + }; + class LacerationLarge: Laceration { + effectiveness = 0.5; + reopeningChance = 0.6; + }; + + class velocityWound: Abrasion { + effectiveness = 2; + reopeningChance = 0.7; + reopeningMinDelay = 100; + reopeningMaxDelay = 500; + }; + class velocityWoundMinor: velocityWound { + effectiveness = 2; + }; + class velocityWoundMedium: velocityWound { + effectiveness = 1.5; + }; + class velocityWoundLarge: velocityWound { + effectiveness = 1; + }; + + class punctureWound: Abrasion { + effectiveness = 2; + reopeningChance = 0.5; + reopeningMinDelay = 200; + reopeningMaxDelay = 850; + }; + class punctureWoundMinor: punctureWound { + effectiveness = 2; + }; + class punctureWoundMedium: punctureWound { + effectiveness = 1.3; + }; + class punctureWoundLarge: punctureWound { + effectiveness = 0.9; + }; + }; + + class PackingBandage: fieldDressing { + class Abrasion { + effectiveness = 3; + reopeningChance = 0.6; + reopeningMinDelay = 800; + reopeningMaxDelay = 1500; + }; + class AbrasionMinor: Abrasion { + effectiveness = 3; + }; + class AbrasionMedium: Abrasion { + effectiveness = 2.5; + reopeningChance = 0.9; + }; + class AbrasionLarge: Abrasion { + effectiveness = 2; + reopeningChance = 1; + }; + + class Avulsions: Abrasion { + effectiveness = 1; + reopeningChance = 0.7; + reopeningMinDelay = 1000; + reopeningMaxDelay = 1600; + }; + class AvulsionsMinor: Avulsions { + effectiveness = 1; + }; + class AvulsionsMedium: Avulsions { + effectiveness = 0.9; + }; + class AvulsionsLarge: Avulsions { + effectiveness = 0.75; + }; + + class Contusion: Abrasion { + effectiveness = 1; + reopeningChance = 0; + reopeningMinDelay = 0; + reopeningMaxDelay = 0; + }; + class ContusionMinor: Contusion {}; + class ContusionMedium: Contusion {}; + class ContusionLarge: Contusion {}; + + class CrushWound: Abrasion { + effectiveness = 1; + reopeningChance = 0.5; + reopeningMinDelay = 600; + reopeningMaxDelay = 1000; + }; + class CrushWoundMinor: CrushWound { + effectiveness = 1; + reopeningChance = 0.6; + }; + class CrushWoundMedium: CrushWound { + effectiveness = 0.7; + reopeningChance = 0.7; + }; + class CrushWoundLarge: CrushWound { + effectiveness = 0.6; + reopeningChance = 0.8; + }; + + class Cut: Abrasion { + effectiveness = 4; + reopeningChance = 0.4; + reopeningMinDelay = 700; + reopeningMaxDelay = 1000; + }; + class CutMinor: Cut { + effectiveness = 4; + reopeningChance = 0.6; + }; + class CutMedium: Cut { + effectiveness = 3; + reopeningChance = 0.7; + }; + class CutLarge: Cut { + effectiveness = 1; + reopeningChance = 0.8; + }; + + class Laceration: Abrasion { + effectiveness = 0.95; + reopeningChance = 0.65; + reopeningMinDelay = 500; + reopeningMaxDelay = 2000; + }; + class LacerationMinor: Laceration { + effectiveness = 0.95; + reopeningChance = 0.65; + }; + class LacerationMedium: Laceration { + effectiveness = 0.7; + reopeningChance = 0.8; + }; + class LacerationLarge: Laceration { + effectiveness = 0.5; + reopeningChance = 0.9; + }; + + class velocityWound: Abrasion { + effectiveness = 2; + reopeningChance = 1; + reopeningMinDelay = 800; + reopeningMaxDelay = 2000; + }; + class velocityWoundMinor: velocityWound { + effectiveness = 2; + }; + class velocityWoundMedium: velocityWound { + effectiveness = 1.5; + }; + class velocityWoundLarge: velocityWound { + effectiveness = 1; + }; + + class punctureWound: Abrasion { + effectiveness = 2; + reopeningChance = 1; + reopeningMinDelay = 1000; + reopeningMaxDelay = 3000; + }; + class punctureWoundMinor: punctureWound { + effectiveness = 2; + }; + class punctureWoundMedium: punctureWound { + effectiveness = 1.3; + }; + class punctureWoundLarge: punctureWound { + effectiveness = 0.9; + }; + }; + + class ElasticBandage: fieldDressing { + class Abrasion { + effectiveness = 4; + reopeningChance = 0.6; + reopeningMinDelay = 80; + reopeningMaxDelay = 150; + }; + class AbrasionMinor: Abrasion { + effectiveness = 43; + }; + class AbrasionMedium: Abrasion { + effectiveness = 3; + reopeningChance = 0.9; + }; + class AbrasionLarge: Abrasion { + effectiveness = 2.5; + reopeningChance = 1; + }; + + class Avulsions: Abrasion { + effectiveness = 2; + reopeningChance = 0.7; + reopeningMinDelay = 100; + reopeningMaxDelay = 160; + }; + class AvulsionsMinor: Avulsions { + effectiveness = 2; + }; + class AvulsionsMedium: Avulsions { + effectiveness = 1.4; + }; + class AvulsionsLarge: Avulsions { + effectiveness = 1; + }; + + class Contusion: Abrasion { + effectiveness = 2; + reopeningChance = 0; + reopeningMinDelay = 0; + reopeningMaxDelay = 0; + }; + class ContusionMinor: Contusion {}; + class ContusionMedium: Contusion {}; + class ContusionLarge: Contusion {}; + + class CrushWound: Abrasion { + effectiveness = 2; + reopeningChance = 0.5; + reopeningMinDelay = 60; + reopeningMaxDelay = 100; + }; + class CrushWoundMinor: CrushWound { + effectiveness = 2; + reopeningChance = 0.6; + }; + class CrushWoundMedium: CrushWound { + effectiveness = 1.7; + reopeningChance = 0.7; + }; + class CrushWoundLarge: CrushWound { + effectiveness = 1.6; + reopeningChance = 0.8; + }; + + class Cut: Abrasion { + effectiveness = 5; + reopeningChance = 0.4; + reopeningMinDelay = 70; + reopeningMaxDelay = 100; + }; + class CutMinor: Cut { + effectiveness = 5; + reopeningChance = 0.6; + }; + class CutMedium: Cut { + effectiveness = 3.5; + reopeningChance = 0.7; + }; + class CutLarge: Cut { + effectiveness = 2; + reopeningChance = 0.8; + }; + + class Laceration: Abrasion { + effectiveness = 2; + reopeningChance = 0.65; + reopeningMinDelay = 50; + reopeningMaxDelay = 200; + }; + class LacerationMinor: Laceration { + effectiveness = 2; + reopeningChance = 0.65; + }; + class LacerationMedium: Laceration { + effectiveness = 1.5; + reopeningChance = 0.8; + }; + class LacerationLarge: Laceration { + effectiveness = 1; + reopeningChance = 0.9; + }; + + class velocityWound: Abrasion { + effectiveness = 2.2; + reopeningChance = 1; + reopeningMinDelay = 80; + reopeningMaxDelay = 200; + }; + class velocityWoundMinor: velocityWound { + effectiveness = 2.2; + }; + class velocityWoundMedium: velocityWound { + effectiveness = 1.75; + }; + class velocityWoundLarge: velocityWound { + effectiveness = 1.5; + }; + + class punctureWound: Abrasion { + effectiveness = 2.5; + reopeningChance = 1; + reopeningMinDelay = 100; + reopeningMaxDelay = 300; + }; + class punctureWoundMinor: punctureWound { + effectiveness = 2.5; + }; + class punctureWoundMedium: punctureWound { + effectiveness = 2; + }; + class punctureWoundLarge: punctureWound { + effectiveness = 1.5; + }; + }; + + class QuikClot: fieldDressing { + class Abrasion { + effectiveness = 2; + reopeningChance = 0.3; + reopeningMinDelay = 800; + reopeningMaxDelay = 1500; + }; + class AbrasionMinor: Abrasion { + effectiveness = 2; + }; + class AbrasionMedium: Abrasion { + effectiveness = 1; + reopeningChance = 0.4; + }; + class AbrasionLarge: Abrasion { + effectiveness = 0.7; + reopeningChance = 5; + }; + + class Avulsions: Abrasion { + effectiveness = 0.7; + reopeningChance = 0.2; + reopeningMinDelay = 1000; + reopeningMaxDelay = 1600; + }; + class AvulsionsMinor: Avulsions { + effectiveness = 0.7; + }; + class AvulsionsMedium: Avulsions { + effectiveness = 0.65; + }; + class AvulsionsLarge: Avulsions { + effectiveness = 0.5; + }; + + class Contusion: Abrasion { + effectiveness = 1; + reopeningChance = 0; + reopeningMinDelay = 0; + reopeningMaxDelay = 0; + }; + class ContusionMinor: Contusion {}; + class ContusionMedium: Contusion {}; + class ContusionLarge: Contusion {}; + + class CrushWound: Abrasion { + effectiveness = 0.6; + reopeningChance = 0.5; + reopeningMinDelay = 600; + reopeningMaxDelay = 1000; + }; + class CrushWoundMinor: CrushWound { + effectiveness = 0.6; + reopeningChance = 0.3; + }; + class CrushWoundMedium: CrushWound { + effectiveness = 0.5; + }; + class CrushWoundLarge: CrushWound { + effectiveness = 0.4; + }; + + class Cut: Abrasion { + effectiveness = 2; + reopeningChance = 0.2; + reopeningMinDelay = 700; + reopeningMaxDelay = 1000; + }; + class CutMinor: Cut { + effectiveness = 2; + reopeningChance = 0.3; + }; + class CutMedium: Cut { + effectiveness = 1; + }; + class CutLarge: Cut { + effectiveness = 0.6; + }; + + class Laceration: Abrasion { + effectiveness = 0.7; + reopeningChance = 0.4; + reopeningMinDelay = 500; + reopeningMaxDelay = 2000; + }; + class LacerationMinor: Laceration { + effectiveness = 0.7; + reopeningChance = 0.4; + }; + class LacerationMedium: Laceration { + effectiveness = 0.7; + }; + class LacerationLarge: Laceration { + effectiveness = 0.5; + }; + + class velocityWound: Abrasion { + effectiveness = 1; + reopeningChance = 0.5; + reopeningMinDelay = 800; + reopeningMaxDelay = 2000; + }; + class velocityWoundMinor: velocityWound { + effectiveness = 1; + }; + class velocityWoundMedium: velocityWound { + effectiveness = 0.75; + }; + class velocityWoundLarge: velocityWound { + effectiveness = 0.5; + }; + + class punctureWound: Abrasion { + effectiveness = 1; + reopeningChance = 0.5; + reopeningMinDelay = 1000; + reopeningMaxDelay = 3000; + }; + class punctureWoundMinor: punctureWound { + effectiveness = 1; + }; + class punctureWoundMedium: punctureWound { + effectiveness = 0.7; + }; + class punctureWoundLarge: punctureWound { + effectiveness = 0.4; + }; + }; + }; + + class Medication { + // How much does the pain get reduced? + painReduce = 0; + // How much will the heart rate be increased when the HR is low (below 55)? {minIncrease, maxIncrease, seconds} + hrIncreaseLow[] = {0, 0, 0}; + hrIncreaseNormal[] = {0, 0, 0}; + hrIncreaseHigh[] = {0, 0, 0}; + // Callback once the heart rate values have been added. + hrCallback = ""; + + // How long until this medication has disappeared + timeInSystem = 120; + // How many of this type of medication can be in the system before the patient overdoses? + maxDose = 4; + // Function to execute upon overdose. Arguments passed to call back are 0: unit , 1: medicationClassName + onOverDose = ""; + // The viscosity of a fluid is a measure of its resistance to gradual deformation by shear stress or tensile stress. For liquids, it corresponds to the informal concept of "thickness". This value will increase/decrease the viscoty of the blood with the percentage given. Where 100 = max. Using the minus will decrease viscosity + viscosityChange = 0; + + // specific details for the ACE_Morphine treatment action + class Morphine { + painReduce = 15; + hrIncreaseLow[] = {-10, -20, 35}; + hrIncreaseNormal[] = {-10, -30, 35}; + hrIncreaseHigh[] = {-10, -35, 50}; + timeInSystem = 900; + maxDose = 4; + inCompatableMedication[] = {}; + viscosityChange = -10; + }; + class Epinephrine { + painReduce = 0; + hrIncreaseLow[] = {10, 20, 15}; + hrIncreaseNormal[] = {10, 50, 10}; + hrIncreaseHigh[] = {10, 40, 5}; + timeInSystem = 120; + maxDose = 10; + inCompatableMedication[] = {}; + }; + class Adenosine { + painReduce = 0; + hrIncreaseLow[] = {-7, -10, 15}; + hrIncreaseNormal[] = {-15, -30, 20}; + hrIncreaseHigh[] = {-15, -35, 10}; + timeInSystem = 120; + maxDose = 6; + inCompatableMedication[] = {}; + }; + class Atropine { + painReduce = 0; + hrIncreaseLow[] = {-2, -5, 15}; + hrIncreaseNormal[] = {-10, -15, 20}; + hrIncreaseHigh[] = {-5, -20, 10}; + timeInSystem = 120; + maxDose = 6; + inCompatableMedication[] = {}; + }; + class PainKillers { + painReduce = 0.7; + timeInSystem = 120; + maxDose = 10; + inCompatableMedication[] = {}; + viscosityChange = 5; + }; + }; + class IV { + // volume is in millileters + volume = 1000; + ratio[] = {}; + type = "Blood"; + class BloodIV { + volume = 1000; + ratio[] = {"Plasma", 1}; + }; + class BloodIV_500: BloodIV { + volume = 500; + }; + class BloodIV_250: BloodIV { + volume = 250; + }; + class PlasmaIV: BloodIV { + volume = 1000; + ratio[] = {"Blood", 1}; + type = "Plasma"; + }; + class PlasmaIV_500: PlasmaIV { + volume = 500; + }; + class PlasmaIV_250: PlasmaIV { + volume = 250; + }; + class SalineIV: BloodIV { + volume = 1000; + type = "Saline"; + ratio[] = {}; + }; + class SalineIV_500: SalineIV { + volume = 500; + }; + class SalineIV_250: SalineIV { + volume = 250; + }; + }; +}; diff --git a/addons/medical_treatment/XEH_PREP.hpp b/addons/medical_treatment/XEH_PREP.hpp index e69de29bb2..485e9f5c06 100644 --- a/addons/medical_treatment/XEH_PREP.hpp +++ b/addons/medical_treatment/XEH_PREP.hpp @@ -0,0 +1,52 @@ +PREP(actionCheckBloodPressure); +PREP(actionCheckBloodPressureLocal); +PREP(actionCheckPulse); +PREP(actionCheckPulseLocal); +PREP(actionCheckResponse); +PREP(actionDiagnose); +PREP(actionLoadUnit); +PREP(actionPlaceInBodyBag); +PREP(actionRemoveTourniquet); +PREP(actionUnloadUnit); +PREP(addToLog); +PREP(addToTriageCard); +PREP(addUnloadPatientActions); +PREP(canAccessMedicalEquipment); +PREP(canTreat); +PREP(canTreatCached); +PREP(displayPatientInformation); +PREP(displayTriageCard); +PREP(dropDownTriageCard); +PREP(getTriageStatus); +PREP(handleBandageOpening); +PREP(hasItem); +PREP(hasItems); +PREP(isBeingCarried); +PREP(isBeingDragged); +PREP(medicationEffectLoop); +PREP(modifyMedicalAction); +PREP(onMedicationUsage); +PREP(treatment); +PREP(treatmentAdvanced_CPR); +PREP(treatmentAdvanced_CPRLocal); +PREP(treatmentAdvanced_bandage); +PREP(treatmentAdvanced_bandageLocal); +PREP(treatmentAdvanced_fullHeal); +PREP(treatmentAdvanced_fullHealLocal); +PREP(treatmentAdvanced_fullHealTreatmentTime); +PREP(treatmentAdvanced_medication); +PREP(treatmentAdvanced_medicationLocal); +PREP(treatmentAdvanced_surgicalKit_onProgress); +PREP(treatmentBasic_bloodbag); +PREP(treatmentBasic_bloodbagLocal); +PREP(treatmentBasic_epipen); +PREP(treatmentBasic_morphine); +PREP(treatmentBasic_morphineLocal); +PREP(treatmentIV); +PREP(treatmentIVLocal); +PREP(treatmentTourniquet); +PREP(treatmentTourniquetLocal); +PREP(treatment_failure); +PREP(treatment_success); +PREP(useItem); +PREP(useItems); diff --git a/addons/medical_treatment/functions/fnc_actionCheckBloodPressure.sqf b/addons/medical_treatment/functions/fnc_actionCheckBloodPressure.sqf new file mode 100644 index 0000000000..9e66eda263 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionCheckBloodPressure.sqf @@ -0,0 +1,22 @@ +/* +* Author: Glowbal +* Action for checking the blood pressure of the patient +* +* Arguments: +* 0: The medic +* 1: The patient +* +* Return Value: +* None +* +* Public: No +*/ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName"]; +if (local _target) then { + [QGVAR(actionCheckBloodPressureLocal), [_caller, _target, _selectionName]] call CBA_fnc_localEvent; +} else { + [QGVAR(actionCheckBloodPressureLocal), [_caller, _target, _selectionName], _target] call CBA_fnc_targetEvent; +}; diff --git a/addons/medical_treatment/functions/fnc_actionCheckBloodPressureLocal.sqf b/addons/medical_treatment/functions/fnc_actionCheckBloodPressureLocal.sqf new file mode 100644 index 0000000000..d952a0dd84 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionCheckBloodPressureLocal.sqf @@ -0,0 +1,64 @@ +/* + * Author: Glowbal + * Local callback for checking the blood pressure of a patient + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName"]; + +private _bloodPressure = if (!alive _target) then { + [0,0] +} else { + [_target] call EFUNC(medical,getBloodPressure) +}; +_bloodPressure params [ "_bloodPressureLow", "_bloodPressureHigh"]; +private _output = ""; +private _logOutPut = ""; +if ([_caller] call EFUNC(medical,isMedic)) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_1); + _logOutPut = format["%1/%2",round(_bloodPressureHigh),round(_bloodPressureLow)]; +} else { + if (_bloodPressureHigh > 20) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_2); + _logOutPut = ELSTRING(medical,Check_Bloodpressure_Low); + if (_bloodPressureHigh > 100) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_3); + _logOutPut = ELSTRING(medical,Check_Bloodpressure_Normal); + if (_bloodPressureHigh > 160) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_4); + _logOutPut = ELSTRING(medical,Check_Bloodpressure_High); + }; + + }; + } else { + if (random(10) > 3) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_5); + _logOutPut = ELSTRING(medical,Check_Bloodpressure_NoBloodpressure); + } else { + _output = ELSTRING(medical,Check_Bloodpressure_Output_6); + //Fail to find pressure, no logoutput + }; + }; +}; + +if (_selectionName in ["hand_l","hand_r"] && {[_unit, _selectionName] call EFUNC(medical,hasTourniquetAppliedTo)}) then { + _output = ELSTRING(medical,Check_Bloodpressure_Output_6); + _logOutPut = ""; +}; + +[QEGVAR(common,displayTextStructured), [[_output, [_target] call EFUNC(common,getName), round(_bloodPressureHigh),round(_bloodPressureLow)], 1.75, _caller], [_caller]] call CBA_fnc_targetEvent; + +if (_logOutPut != "") then { + [_target,"activity", ELSTRING(medical,Check_Bloodpressure_Log), [[_caller, false, true] call EFUNC(common,getName), _logOutPut]] call FUNC(addToLog); + [_target,"quick_view", ELSTRING(medical,Check_Bloodpressure_Log), [[_caller, false, true] call EFUNC(common,getName), _logOutPut]] call FUNC(addToLog); +}; diff --git a/addons/medical_treatment/functions/fnc_actionCheckPulse.sqf b/addons/medical_treatment/functions/fnc_actionCheckPulse.sqf new file mode 100644 index 0000000000..39f196a0a5 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionCheckPulse.sqf @@ -0,0 +1,22 @@ +/* +* Author: Glowbal +* Action for checking the pulse or heart rate of the patient +* +* Arguments: +* 0: The medic +* 1: The patient +* +* Return Value: +* None +* +* Public: No +*/ + +#include "script_component.hpp" + +params ["_caller","_target", "_selectionName"]; +if (local _target) then { + [QGVAR(actionCheckPulseLocal), [_caller, _target, _selectionName]] call CBA_fnc_localEvent; +} else { + [QGVAR(actionCheckPulseLocal), [_caller, _target, _selectionName], _target] call CBA_fnc_targetEvent; +}; diff --git a/addons/medical_treatment/functions/fnc_actionCheckPulseLocal.sqf b/addons/medical_treatment/functions/fnc_actionCheckPulseLocal.sqf new file mode 100644 index 0000000000..9a05bd30a6 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionCheckPulseLocal.sqf @@ -0,0 +1,56 @@ +/* + * Author: Glowbal + * Local callback for checking the pulse of a patient + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_unit", "_selectionName"]; + +private _heartRate = _unit getVariable [QEGVAR(medical,heartRate), 80]; +if (!alive _unit) then { + _heartRate = 0; +}; +private _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_5); +private _logOutPut = ELSTRING(medical,Check_Pulse_None); + +if (_heartRate > 1.0) then { + if ([_caller] call EFUNC(medical,isMedic)) then { + _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_1); + _logOutPut = format["%1",round(_heartRate)]; + } else { + // non medical personel will only find a pulse/HR + _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_2); + _logOutPut = ELSTRING(medical,Check_Pulse_Weak); + if (_heartRate > 60) then { + if (_heartRate > 100) then { + _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_3); + _logOutPut = ELSTRING(medical,Check_Pulse_Strong); + } else { + _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_4); + _logOutPut = ELSTRING(medical,Check_Pulse_Normal); + }; + }; + }; +}; + +if (_selectionName in ["hand_l","hand_r"] && {[_unit, _selectionName] call EFUNC(medical,hasTourniquetAppliedTo)}) then { + _heartRateOutput = ELSTRING(medical,Check_Pulse_Output_5); + _logOutPut = ELSTRING(medical,Check_Pulse_None); +}; + +[QEGVAR(common,displayTextStructured), [[_heartRateOutput, [_unit] call EFUNC(common,getName), round(_heartRate)], 1.5, _caller], [_caller]] call CBA_fnc_targetEvent; + +if (_logOutPut != "") then { + [_unit,"activity", ELSTRING(medical,Check_Pulse_Log),[[_caller] call EFUNC(common,getName),_logOutPut]] call FUNC(addToLog); + [_unit,"quick_view", ELSTRING(medical,Check_Pulse_Log),[[_caller] call EFUNC(common,getName),_logOutPut]] call FUNC(addToLog); +}; diff --git a/addons/medical_treatment/functions/fnc_actionCheckResponse.sqf b/addons/medical_treatment/functions/fnc_actionCheckResponse.sqf new file mode 100644 index 0000000000..9cd4b572dd --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionCheckResponse.sqf @@ -0,0 +1,24 @@ +/* + * Author: Glowbal + * Action for checking the response status of the patient + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_target"]; + +private _output = [ELSTRING(medical,Check_Response_Unresponsive), ELSTRING(medical,Check_Response_Responsive)] select ([_target] call EFUNC(common,isAwake)); + +[QEGVAR(common,displayTextStructured), [[_output, [_target] call EFUNC(common,getName)], 2, _caller], [_caller]] call CBA_fnc_targetEvent; + +[_target ,"activity", _output, [[_target, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); +[_target, "quick_view", _output, [[_target, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); diff --git a/addons/medical_treatment/functions/fnc_actionDiagnose.sqf b/addons/medical_treatment/functions/fnc_actionDiagnose.sqf new file mode 100644 index 0000000000..22ab98b490 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionDiagnose.sqf @@ -0,0 +1,46 @@ +/* +* Author: Glowbal +* Action for diagnosing in basic medical +* +* Arguments: +* 0: The medic +* 1: The patient +* +* Return Value: +* None +* +* Public: No +*/ + +#include "script_component.hpp" + +private "_genericMessages"; +params ["_caller", "_target"]; + +private _genericMessages = [ELSTRING(medical,diagnoseMessage), [_target] call EFUNC(common,getName)]; + +if (alive _target) then { + _genericMessages pushBack ELSTRING(medical,diagnoseAlive); +} else { + _genericMessages pushBack ELSTRING(medical,diagnoseDead); +}; + +if (_target getVariable[QEGVAR(medical,hasLostBlood), 0] > 0) then { + if (_target getVariable[QEGVAR(medical,hasLostBlood), 0] > 1) then { + _genericMessages pushBack ELSTRING(medical,lostBloodALot); + } else { + _genericMessages pushBack ELSTRING(medical,lostBlood); + }; +} else { + _genericMessages pushBack ELSTRING(medical,noBloodloss); +}; + +if (alive _target) then { + if (_target getVariable[QEGVAR(medical,hasPain), false]) then { + _genericMessages pushBack ELSTRING(medical,inPain); + } else { + _genericMessages pushBack ELSTRING(medical,noPain); + }; +}; + +[QEGVAR(common,displayTextStructured), [_genericMessages, 3.0, _caller], [_caller]] call CBA_fnc_targetEvent; diff --git a/addons/medical_treatment/functions/fnc_actionLoadUnit.sqf b/addons/medical_treatment/functions/fnc_actionLoadUnit.sqf new file mode 100644 index 0000000000..1fc6149d8c --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionLoadUnit.sqf @@ -0,0 +1,30 @@ +/* + * Author: Glowbal + * Action for loading an unconscious or dead unit in the nearest vechile + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +private "_vehicle"; +params ["_caller", "_target"]; + +if ([_target] call EFUNC(common,isAwake)) exitWith { + [QEGVAR(common,displayTextStructured), [[ELSTRING(medical,CanNotLoaded), [_target] call EFUNC(common,getName)], 1.5, _caller], [_caller]] call CBA_fnc_targetEvent; +}; +if ([_target] call FUNC(isBeingCarried)) then { + [_caller, _target] call EFUNC(dragging,dropObject_carry); +}; +if ([_target] call FUNC(isBeingDragged)) then { + [_caller, _target] call EFUNC(dragging,dropObject); +}; + +_vehicle = [_caller, _target] call EFUNC(common,loadPerson); diff --git a/addons/medical_treatment/functions/fnc_actionPlaceInBodyBag.sqf b/addons/medical_treatment/functions/fnc_actionPlaceInBodyBag.sqf new file mode 100644 index 0000000000..c878a27ae8 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionPlaceInBodyBag.sqf @@ -0,0 +1,52 @@ +/* + * Author: Glowbal + * Replace a (dead) body by a body bag + * + * Arguments: + * 0: The actor + * 1: The patient + * + * Return Value: + * body bag (will return objNull when run where target is not local) + * + * Example: + * [player, cursorTarget] call ace_medical_fnc_actionPlaceInBodyBag + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller", "_target"]; +TRACE_2("params",_caller,_target); + +if (!local _target) exitWith { + TRACE_1("running where local",local _target); + [QGVAR(actionPlaceInBodyBag), [_caller, _target], [_target]] call CBA_fnc_targetEvent; + objNull +}; + +if (alive _target) then { + TRACE_1("manually killing with setDead",_target); + [_target, true] call EFUNC(medical,setDead); +}; + +private _position = (getPosASL _target) vectorAdd [0, 0, 0.2]; + +private _headPos = _target modelToWorldVisual (_target selectionPosition "head"); +private _spinePos = _target modelToWorldVisual (_target selectionPosition "Spine3"); +private _dirVect = _headPos vectorFromTo _spinePos; +private _direction = _dirVect call CBA_fnc_vectDir; + +//move the body away now, so it won't physX the bodyBag object (this setPos seems to need to be called where object is local) +_target setPosASL [-5000, -5000, 0]; + +private _bodyBag = createVehicle ["ACE_bodyBagObject", _position, [], 0, ""]; + +// prevent body bag from flipping +_bodyBag setPosASL _position; +_bodyBag setDir _direction; + +["ace_placedInBodyBag", [_target, _bodyBag]] call CBA_fnc_globalEvent; //hide and delete body on server + +_bodyBag diff --git a/addons/medical_treatment/functions/fnc_actionRemoveTourniquet.sqf b/addons/medical_treatment/functions/fnc_actionRemoveTourniquet.sqf new file mode 100644 index 0000000000..0a905a6c54 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionRemoveTourniquet.sqf @@ -0,0 +1,54 @@ +/* + * Author: Glowbal + * Action for removing the tourniquet on specified selection + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName"]; +TRACE_3("params",_caller,_target,_selectionName); + +// grab the required data +private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber); +private _tourniquets = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; + +// Check if there is a tourniquet on this bodypart +if ((_tourniquets select _part) == 0) exitWith { + [QEGVAR(common,displayTextStructured), [ELSTRING(medical,noTourniquetOnBodyPart), 1.5, _caller], [_caller]] call CBA_fnc_targetEvent; +}; + +// Removing the tourniquet +_tourniquets set [_part, 0]; +_target setVariable [QEGVAR(medical,tourniquets), _tourniquets, true]; + +// Adding the tourniquet item to the caller +_caller addItem "ACE_tourniquet"; + +//Handle all injected medications now that blood is flowing: +private _delayedMedications = _target getVariable [QGVAR(occludedMedications), []]; +private _updatedArray = false; +TRACE_2("meds",_part,_delayedMedications); +{ + _x params ["", "", "_medPartNum"]; + if (_part == _medPartNum) then { + TRACE_1("delayed medication call after tourniquet removeal",_x); + [QGVAR(treatmentAdvanced_medicationLocal), _x, [_target]] call CBA_fnc_targetEvent; + _delayedMedications set [_forEachIndex, -1]; + _updatedArray = true; + }; +} forEach _delayedMedications; + +if (_updatedArray) then { + _delayedMedications = _delayedMedications - [-1]; + _target setVariable [QGVAR(occludedMedications), _delayedMedications, true]; +}; diff --git a/addons/medical_treatment/functions/fnc_actionUnloadUnit.sqf b/addons/medical_treatment/functions/fnc_actionUnloadUnit.sqf new file mode 100644 index 0000000000..75fe76bce9 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_actionUnloadUnit.sqf @@ -0,0 +1,24 @@ +/* + * Author: Glowbal + * Action for unloading an unconscious or dead unit from a vechile + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: Drag after unload (default: false) + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_target", ["_drag", false]]; + +// cannot unload a unit not in a vehicle. +if (vehicle _target == _target) exitWith {}; +if (([_target] call EFUNC(common,isAwake))) exitWith {}; + +["ace_unloadPersonEvent", [_target, vehicle _target, _caller], _target] call CBA_fnc_targetEvent; diff --git a/addons/medical_treatment/functions/fnc_addToLog.sqf b/addons/medical_treatment/functions/fnc_addToLog.sqf new file mode 100644 index 0000000000..894a61b2ef --- /dev/null +++ b/addons/medical_treatment/functions/fnc_addToLog.sqf @@ -0,0 +1,50 @@ +/* + * Author: Glowbal + * Add an entry to the specified log + * + * Arguments: + * 0: The patient + * 1: The log type + * 2: The message + * 3: The arguments for localization + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_unit", "_type", "_message", "_arguments"]; + +if (!local _unit) exitWith { + [QGVAR(addToMedicalLog), _this, _unit] call CBA_fnc_targetEvent; +}; + +date params ["", "", "", "_hour", "_minute"]; + +private _moment = format [ (["%1:%2", "%1:0%2"] select (_minute < 10)), _hour, _minute]; +private _logVarName = format[QEGVAR(medical,logFile_%1), _type]; + +private _log = _unit getVariable [_logVarName, []]; +if (count _log >= 8) then { + private _newLog = []; + { + // ensure the first element will not be added + if (_forEachIndex > 0) then { + _newLog pushBack _x; + }; + } forEach _log; + _log = _newLog; +}; +_log pushBack [_message, _moment, _type, _arguments]; + +_unit setVariable [_logVarName, _log, true]; +["ace_medicalLogEntryAdded", [_unit, _type, _message, _arguments]] call CBA_fnc_localEvent; + +private _logs = _unit getVariable [QEGVAR(medical,allLogs), []]; +if !(_logVarName in _logs) then { + _logs pushBack _logVarName; + _unit setVariable [QEGVAR(medical,allLogs), _logs, true]; +}; diff --git a/addons/medical_treatment/functions/fnc_addToTriageCard.sqf b/addons/medical_treatment/functions/fnc_addToTriageCard.sqf new file mode 100644 index 0000000000..ddbbee7d38 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_addToTriageCard.sqf @@ -0,0 +1,43 @@ +/* + * Author: Glowbal + * Add an entry to the triage card + * + * Arguments: + * 0: The patient + * 1: The new item classname + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_unit", "_newItem"]; + +if (!local _unit) exitWith { + [QGVAR(addToTriageCard), _this, _unit] call CBA_fnc_targetEvent; +}; + +private _log = _unit getVariable [QEGVAR(medical,triageCard), []]; +private _inList = false; +private _amount = 1; +{ + if ((_x select 0) == _newItem) exitWith { + private _info = _log select _forEachIndex; + _info set [1,(_info select 1) + 1]; + _info set [2, CBA_missionTime]; + _log set [_forEachIndex, _info]; + + _amount = (_info select 1); + _inList = true; + }; +} forEach _log; + +if (!_inList) then { + _log pushBack [_newItem, 1, CBA_missionTime]; +}; + +_unit setVariable [QEGVAR(medical,triageCard), _log, true]; +["ace_triageCardItemAdded", [_unit, _newItem, _amount]] call CBA_fnc_localEvent; diff --git a/addons/medical_treatment/functions/fnc_addUnloadPatientActions.sqf b/addons/medical_treatment/functions/fnc_addUnloadPatientActions.sqf new file mode 100644 index 0000000000..2725365bc1 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_addUnloadPatientActions.sqf @@ -0,0 +1,40 @@ +/* + * Author: esteldunedain + * Create one unload action per unconscious passenger + * + * Argument: + * 0: Vehicle + * 1: Player + * 3: Parameters + * + * Return value: + * Children actions + * + * Public: No + */ +#include "script_component.hpp" +params ["_vehicle", "_player", "_parameters"]; + +private _actions = []; + +{ + private _unit = _x; + if (_unit != _player && {(alive _unit) && {_unit getVariable ["ACE_isUnconscious", false]}}) then { + _actions pushBack + [ + [ + str(_unit), + [_unit, true] call EFUNC(common,getName), + "", + {[_player, (_this select 2) select 0] call FUNC(actionUnloadUnit);}, + {true}, + {}, + [_unit] + ] call EFUNC(interact_menu,createAction), + [], + _unit + ]; + }; +} forEach crew _vehicle; + +_actions diff --git a/addons/medical_treatment/functions/fnc_canTreat.sqf b/addons/medical_treatment/functions/fnc_canTreat.sqf index 1c78eb1e43..242b51ead5 100644 --- a/addons/medical_treatment/functions/fnc_canTreat.sqf +++ b/addons/medical_treatment/functions/fnc_canTreat.sqf @@ -23,7 +23,7 @@ params ["_caller", "_target", "_selectionName", "_className"]; if !(_target isKindOf "CAManBase") exitWith { false }; -private _config = (ConfigFile >> "ACE_Medical_Actions" >> (["Basic", "Advanced"] select (GVAR(level)>=2)) >> _className); +private _config = (ConfigFile >> "ACE_Medical_Treatments" >> (["Basic", "Advanced"] select (GVAR(level)>=2)) >> _className); if !(isClass _config) exitwith {false}; diff --git a/addons/medical_treatment/functions/fnc_displayPatientInformation.sqf b/addons/medical_treatment/functions/fnc_displayPatientInformation.sqf new file mode 100644 index 0000000000..58224ac5b9 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_displayPatientInformation.sqf @@ -0,0 +1,193 @@ +/* + * Author: Glowbal + * Displays the patient information for given unit. + * + * Arguments: + * 0: The Unit + * 1: Show (default: true) + * 2: Selection (default: 0) + * + * ReturnValue: + * None + * + * Public: No + */ + +#include "script_component.hpp" +#define MAX_DISTANCE 10 + +// Exit for basic medical +if (EGVAR(medical,level) < 2) exitWith {}; + +params ["_target", ["_show", true], ["_selectionN", 0]]; + +GVAR(currentSelectedSelectionN) = [0, _selectionN] select (IS_SCALAR(_selectionN)); +GVAR(displayPatientInformationTarget) = [ObjNull, _target] select _show; + +if (_show) then { + ("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutRsc [QGVAR(DisplayInformation),"PLAIN"]; + + [{ + private ["_target", "_display", "_alphaLevel", "_damaged", "_availableSelections", "_openWounds", "_selectionBloodLoss", "_red", "_green", "_blue", "_alphaLevel", "_allInjuryTexts", "_lbCtrl", "_genericMessages"]; + params ["_args", "_idPFH"]; + _args params ["_target", "_selectionN"]; + + if (GVAR(displayPatientInformationTarget) != _target || GVAR(currentSelectedSelectionN) != _selectionN) exitwith { + [_idPFH] call CBA_fnc_removePerFrameHandler; + }; + if (ACE_player distance _target > MAX_DISTANCE) exitwith { + ("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutText ["","PLAIN"]; + [_idPFH] call CBA_fnc_removePerFrameHandler; + [QEGVAR(common,displayTextStructured), [[ELSTRING(medical,DistanceToFar), [_target] call EFUNC(common,getName)], 1.75, ACE_player], [ACE_player]] call CBA_fnc_targetEvent; + }; + + disableSerialization; + private _display = uiNamespace getVariable QGVAR(DisplayInformation); + if (isnil "_display") exitwith { + [_idPFH] call CBA_fnc_removePerFrameHandler; + }; + + private _allInjuryTexts = []; + private _genericMessages = []; + + private _partText = [ELSTRING(medical,Head), ELSTRING(medical,Torso), ELSTRING(medical,LeftArm) ,ELSTRING(medical,RightArm) ,ELSTRING(medical,LeftLeg), ELSTRING(medical,RightLeg)] select _selectionN; + _genericMessages pushback [localize _partText, [1, 1, 1, 1]]; + + if (_target getVariable[QEGVAR(medical,isBleeding), false]) then { + _genericMessages pushback [localize ELSTRING(medical,Status_Bleeding), [1, 0.1, 0.1, 1]]; + }; + if (_target getVariable[QEGVAR(medical,hasLostBlood), 0] > 1) then { + _genericMessages pushback [localize ELSTRING(medical,Status_Lost_Blood), [1, 0.1, 0.1, 1]]; + }; + + if (((_target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]) select _selectionN) > 0) then { + _genericMessages pushback [localize ELSTRING(medical,Status_Tourniquet_Applied), [0.77, 0.51, 0.08, 1]]; + }; + if (_target getVariable[QEGVAR(medical,hasPain), false]) then { + _genericMessages pushback [localize ELSTRING(medical,Status_Pain), [1, 1, 1, 1]]; + }; + + private _totalIvVolume = 0; + { + private _value = _target getVariable _x; + if !(isnil "_value") then { + _totalIvVolume = _totalIvVolume + (_target getVariable [_x, 0]); + }; + } foreach EGVAR(medical,IVBags); + + if (_totalIvVolume >= 1) then { + _genericMessages pushback [format[localize ELSTRING(medical,receivingIvVolume), floor _totalIvVolume], [1, 1, 1, 1]]; + }; + + private _damaged = [false, false, false, false, false, false]; + private _selectionBloodLoss = [0,0,0,0,0,0]; + + private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; + { + _x params ["", "_x1", "_selectionX", "_amountOf", "_x4"]; + // Find how much this bodypart is bleeding + if (_amountOf > 0) then { + _damaged set [_selectionX, true]; + _selectionBloodLoss set [_selectionX, (_selectionBloodLoss select _selectionX) + (20 * (_x4 * _amountOf))]; + + if (_selectionN == _selectionX) then { + // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] + if (_amountOf >= 1) then { + // TODO localization + _allInjuryTexts pushback [format["%2x %1", (EGVAR(medical,AllWoundInjuryTypes) select _x1) select 6, ceil _amountOf], [1,1,1,1]]; + } else { + // TODO localization + _allInjuryTexts pushback [format["Partial %1", (EGVAR(medical,AllWoundInjuryTypes) select _x1) select 6], [1,1,1,1]]; + }; + }; + }; + } foreach _openWounds; + + private _bandagedwounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; + { + _x params ["", "", "_selectionX", "_amountOf", "_x4"]; + // Find how much this bodypart is bleeding + if !(_damaged select _selectionX) then { + _selectionBloodLoss set [_selectionX, (_selectionBloodLoss select _selectionX) + (20 * (_x4 * _amountOf))]; + }; + if (_selectionN == _selectionX) then { + // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] + if (_amountOf > 0) then { + if (_amountOf >= 1) then { + // TODO localization + _allInjuryTexts pushback [format["[B] %2x %1", (EGVAR(medical,AllWoundInjuryTypes) select (_x select 1)) select 6, ceil _amountOf], [0.88,0.7,0.65,1]]; + } else { + // TODO localization + _allInjuryTexts pushback [format["[B] Partial %1", (EGVAR(medical,AllWoundInjuryTypes) select (_x select 1)) select 6], [0.88,0.7,0.65,1]]; + }; + }; + }; + } foreach _bandagedwounds; + + // Handle the body image coloring + private _availableSelections = [50,51,52,53,54,55]; + { + private _total = _x; + private _red = 1; + private _green = 1; + private _blue = 1; + + if (_total > 0) then { + if (_damaged select _forEachIndex) then { + _green = (0.9 - _total) max 0; + _blue = _green; + } else { + _green = (0.9 - _total) max 0; + _red = _green; + //_blue = _green; + }; + }; + (_display displayCtrl (_availableSelections select _foreachIndex)) ctrlSetTextColor [_red, _green, _blue, 1.0]; + } foreach _selectionBloodLoss; + + private _lbCtrl = (_display displayCtrl 200); + lbClear _lbCtrl; + { + _x params ["_add", "_color"]; + _lbCtrl lbAdd _add; + _lbCtrl lbSetColor [_foreachIndex, _color]; + } foreach _genericMessages; + + private _amountOfGeneric = count _genericMessages; + { + _x params ["_add", "_color"]; + _lbCtrl lbAdd _add; + _lbCtrl lbSetColor [_foreachIndex + _amountOfGeneric, _color]; + } foreach _allInjuryTexts; + if (count _allInjuryTexts == 0) then { + _lbCtrl lbAdd (localize ELSTRING(medical,NoInjuriesBodypart)); + }; + + private _logCtrl = (_display displayCtrl 302); + lbClear _logCtrl; + + private _logs = _target getVariable [QGVAR(logFile_Activity), []]; + { + _x params ["_message", "_moment", "_type", "_arguments"]; + if (isLocalized _message) then { + _message = localize _message; + }; + + { + if (_x isEqualType "" && {isLocalized _x}) then { + _arguments set [_foreachIndex, localize _x]; + }; + } foreach _arguments; + _message = format([_message] + _arguments); + _logCtrl lbAdd format["%1 %2", _moment, _message]; + } foreach _logs; + + private _triageStatus = [_target] call FUNC(getTriageStatus); + (_display displayCtrl 303) ctrlSetText (_triageStatus select 0); + (_display displayCtrl 303) ctrlSetBackgroundColor (_triageStatus select 2); + + }, 0, [_target, GVAR(currentSelectedSelectionN)]] call CBA_fnc_addPerFrameHandler; + +} else { + ("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutText ["","PLAIN"]; +}; diff --git a/addons/medical_treatment/functions/fnc_displayTriageCard.sqf b/addons/medical_treatment/functions/fnc_displayTriageCard.sqf new file mode 100644 index 0000000000..a8d2643b3e --- /dev/null +++ b/addons/medical_treatment/functions/fnc_displayTriageCard.sqf @@ -0,0 +1,76 @@ +/* + * Author: Glowbal + * Display triage card for a unit + * + * Arguments: + * 0: The unit + * 1: Show (default: true) + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_target", ["_show", true]]; + +GVAR(TriageCardTarget) = if (_show) then {_target} else {ObjNull}; + +if (_show) then { + //("ACE_MedicalTriageCard" call BIS_fnc_rscLayer) cutRsc [QGVAR(triageCard),"PLAIN"]; + createDialog QGVAR(triageCard); + + [{ + params ["_args", "_idPFH"]; + _args params ["_target"]; + if (GVAR(TriageCardTarget) != _target) exitWith { + [_idPFH] call CBA_fnc_removePerFrameHandler; + }; + + disableSerialization; + private _display = uiNamespace getVariable QGVAR(triageCard); + if (isNil "_display") exitWith { + [_idPFH] call CBA_fnc_removePerFrameHandler; + }; + + private _triageCardTexts = []; + + // TODO fill the lb with the appropiate information for the patient + private _lbCtrl = (_display displayCtrl 200); + lbClear _lbCtrl; + + private _log = _target getVariable [QGVAR(triageCard), []]; + { + _x params ["_item", "_amount"]; + private _message = _item; + if (isClass(configFile >> "CfgWeapons" >> _item)) then { + _message = getText(configFile >> "CfgWeapons" >> _item >> "DisplayName"); + } else { + if (isLocalized _message) then { + _message = localize _message; + }; + }; + _triageCardTexts pushBack format["%1x - %2", _amount, _message]; + } forEach _log; + + if (count _triageCardTexts == 0) then { + _lbCtrl lbAdd (localize ELSTRING(medical,TriageCard_NoEntry)); + }; + { + _lbCtrl lbAdd _x; + } forEach _triageCardTexts; + + private _triageStatus = [_target] call FUNC(getTriageStatus); + _triageStatus params ["_text", "", "_color"]; + + (_display displayCtrl 2000) ctrlSetText _text; + (_display displayCtrl 2000) ctrlSetBackgroundColor _color; + + }, 0, [_target]] call CBA_fnc_addPerFrameHandler; + +} else { + //("ACE_MedicalTriageCard" call BIS_fnc_rscLayer) cutText ["","PLAIN"]; + closeDialog 7010; +}; diff --git a/addons/medical_treatment/functions/fnc_dropDownTriageCard.sqf b/addons/medical_treatment/functions/fnc_dropDownTriageCard.sqf new file mode 100644 index 0000000000..c499283446 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_dropDownTriageCard.sqf @@ -0,0 +1,31 @@ +/* + * Author: Glowbal + * Display triage card for a unit + * + * Arguments: + * 0: Show + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_show"]; + +disableSerialization; +private _display = uiNamespace getVariable QGVAR(triageCard); +if (isNil "_display") exitWith {}; + +private _pos = [0,0,0,0]; +if (_show) then { + _pos = ctrlPosition (_display displayCtrl 2001); +}; +for "_idc" from 2002 to 2006 step 1 do { + _pos set [1, (_pos select 1) + (_pos select 3)]; + private _ctrl = (_display displayCtrl _idc); + _ctrl ctrlSetPosition _pos; + _ctrl ctrlCommit 0; +}; diff --git a/addons/medical_treatment/functions/fnc_getTriageStatus.sqf b/addons/medical_treatment/functions/fnc_getTriageStatus.sqf new file mode 100644 index 0000000000..f0fdb5e9ac --- /dev/null +++ b/addons/medical_treatment/functions/fnc_getTriageStatus.sqf @@ -0,0 +1,28 @@ +/* + * Author: Glowbal + * Get the triage status and information from a unit + * + * Arguments: + * 0: The unit + * + * Return Value: + * 0: Name + * 1: Status ID + * 2: Color > + * + * Public: Yes + */ + +#include "script_component.hpp" + +private ["_unit","_return","_status"]; +params ["_unit"]; +_status = _unit getVariable [QEGVAR(medical,triageLevel), -1]; +_return = switch (_status) do { + case 1: {[localize ELSTRING(medical,Triage_Status_Minor), 1, [0, 0.5, 0, 0.9]]}; + case 2: {[localize ELSTRING(medical,Triage_Status_Delayed), 2, [0.7, 0.5, 0, 0.9]]}; + case 3: {[localize ELSTRING(medical,Triage_Status_Immediate), 3, [0.4, 0.07, 0.07, 0.9]]}; + case 4: {[localize ELSTRING(medical,Triage_Status_Deceased), 4, [0, 0, 0, 0.9]]}; + default {[localize ELSTRING(medical,Triage_Status_None), 0, [0, 0, 0, 0.9]]}; +}; +_return diff --git a/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf b/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf new file mode 100644 index 0000000000..e13bdf1ea9 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf @@ -0,0 +1,120 @@ +/* + * Author: Glowbal + * Handles the bandage of a patient. + * + * Arguments: + * 0: The target + * 1: The impact + * 2: Selection part number + * 3: Injury index + * 4: Injury + * 5: Used Bandage type + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +private ["_className", "_reopeningChance", "_reopeningMinDelay", "_reopeningMaxDelay", "_config", "_woundTreatmentConfig", "_bandagedWounds", "_exist", "_injuryId", "_existingInjury", "_delay", "_openWounds", "_selectedInjury", "_bandagedInjury"]; +params ["_target", "_impact", "_part", "_injuryIndex", "_injury", "_bandage"]; + +private _classID = _injury select 1; +private _className = EGVAR(medical,woundClassNames) select _classID; + +// default, just in case.. +private _reopeningChance = 0.1; +private _reopeningMinDelay = 120; +private _reopeningMaxDelay = 200; + +// Get the default values for the used bandage +private _config = (ConfigFile >> "ace_medical_treatment" >> "Bandaging"); +if (isClass (_config >> _bandage)) then { + _config = (_config >> _bandage); + _reopeningChance = getNumber (_config >> "reopeningChance"); + _reopeningMinDelay = getNumber (_config >> "reopeningMinDelay"); + _reopeningMaxDelay = getNumber (_config >> "reopeningMaxDelay") max _reopeningMinDelay; +} else { + ACE_LOGWARNING_2("No config for bandage [%1] config base [%2]", _bandage, _config); +}; + +if (isClass (_config >> _className)) then { + private _woundTreatmentConfig = (_config >> _className); + if (isNumber (_woundTreatmentConfig >> "reopeningChance")) then { + _reopeningChance = getNumber (_woundTreatmentConfig >> "reopeningChance"); + }; + if (isNumber (_woundTreatmentConfig >> "reopeningMinDelay")) then { + _reopeningMinDelay = getNumber (_woundTreatmentConfig >> "reopeningMinDelay"); + }; + if (isNumber (_woundTreatmentConfig >> "reopeningMaxDelay")) then { + _reopeningMaxDelay = getNumber (_woundTreatmentConfig >> "reopeningMaxDelay") max _reopeningMinDelay; + }; +} else { + ACE_LOGWARNING_2("No config for wound type [%1] config base [%2]", _className, _config); +}; +TRACE_5("configs",_bandage,_className,_reopeningChance,_reopeningMinDelay,_reopeningMaxDelay); + +private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; +private _injuryType = _injury select 1; +private _exist = false; +private _bandagedInjury = []; +{ + if ((_x select 1) == _injuryType && (_x select 2) == (_injury select 2)) exitwith { + _exist = true; + _existingInjury = _x; + _existingInjury set [3, (_existingInjury select 3) + _impact]; + _bandagedWounds set [_foreachIndex, _existingInjury]; + + _bandagedInjury = _existingInjury; + }; +} foreach _bandagedWounds; + +if !(_exist) then { + // [ID, classID, bodypart, percentage treated, bloodloss rate] + _bandagedInjury = [_injury select 0, _injury select 1, _injury select 2, _impact, _injury select 4]; + _bandagedWounds pushback _bandagedInjury; +}; + +_target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; + +TRACE_1("",_reopeningChance); +// Check if we are ever going to reopen this +if (random(1) <= _reopeningChance) then { + _delay = _reopeningMinDelay + random(_reopeningMaxDelay - _reopeningMinDelay); + TRACE_1("Will open",_delay); + [{ + params ["_target", "_impact", "_part", "_injuryIndex", "_injury"]; + TRACE_5("params",_target,_impact,_part,_injuryIndex,_injury); + + //if (alive _target) then { + private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; + if ((count _openWounds) - 1 < _injuryIndex) exitwith {}; + private _selectedInjury = _openWounds select _injuryIndex; + if (_selectedInjury select 1 == _injury select 1 && (_selectedInjury select 2) == (_injury select 2)) then { // matching the IDs + + private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; + private _exist = false; + private _injuryId = _injury select 1; + { + if ((_x select 1) == _injuryId && (_x select 2) == (_injury select 2)) exitwith { + _exist = true; + _existingInjury = _x; + _existingInjury set [3, ((_existingInjury select 3) - _impact) max 0]; + _bandagedWounds set [_foreachIndex, _existingInjury]; + }; + } foreach _bandagedWounds; + + if (_exist) then { + TRACE_2("Reopening Wound",_bandagedWounds,_openWounds); + _selectedInjury set [3, (_selectedInjury select 3) + _impact]; + _openWounds set [_injuryIndex, _selectedInjury]; + _target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; + _target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; + }; + }; + // Otherwise something went wrong, we we don't reopen them.. + //}; + }, [_target, _impact, _part, _injuryIndex, +_injury], _delay] call CBA_fnc_waitAndExecute; +}; diff --git a/addons/medical_treatment/functions/fnc_hasItem.sqf b/addons/medical_treatment/functions/fnc_hasItem.sqf new file mode 100644 index 0000000000..49951bb485 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_hasItem.sqf @@ -0,0 +1,41 @@ +/* + * Author: Glowbal + * Check if the item is present between the patient and the medic + * + * Arguments: + * 0: Medic + * 1: Patient + * 2: Item + * + * ReturnValue: + * + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_medic", "_patient", "_item"]; + +if (isNil QEGVAR(medical,setting_allowSharedEquipment)) then { + EGVAR(medical,setting_allowSharedEquipment) = true; +}; +if (EGVAR(medical,setting_allowSharedEquipment) && {[_patient, _item] call EFUNC(common,hasItem)}) exitWith { + true +}; + +if ([_medic, _item] call EFUNC(common,hasItem)) exitWith { + true +}; + +private _return = false; +if ((vehicle _medic != _medic) && {[vehicle _medic] call FUNC(isMedicalVehicle)}) then { + private _crew = crew vehicle _medic; + { + if ([_medic, _x] call FUNC(canAccessMedicalEquipment) && {([_x, _item] call EFUNC(common,hasItem))}) exitWith { + _return = true; + }; + } forEach _crew; +}; + +_return diff --git a/addons/medical_treatment/functions/fnc_hasItems.sqf b/addons/medical_treatment/functions/fnc_hasItems.sqf new file mode 100644 index 0000000000..d3e79c0a54 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_hasItems.sqf @@ -0,0 +1,31 @@ +/* + * Author: Glowbal + * Check if all items are present between the patient and the medic. + * + * Arguments: + * 0: Medic + * 1: Patient + * 2: Items > + * + * ReturnValue: + * Has the items + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_medic", "_patient", "_items"]; + +private _return = true; +{ + // + if (_x isEqualType [] && {({[_medic, _patient, _x] call FUNC(hasItem)}count _x == 0)}) exitwith { + _return = false; + }; + if (_x isEqualType "" && {!([_medic, _patient, _x] call FUNC(hasItem))}) exitwith { + _return = false; + }; +}foreach _items; + +_return diff --git a/addons/medical_treatment/functions/fnc_isBeingCarried.sqf b/addons/medical_treatment/functions/fnc_isBeingCarried.sqf new file mode 100644 index 0000000000..b47c5e475f --- /dev/null +++ b/addons/medical_treatment/functions/fnc_isBeingCarried.sqf @@ -0,0 +1,26 @@ +/* + * Author: PabstMirror + * Returns if a target is being carried. (from ace_dragging) + * + * Arguments: + * 0: Target Unit + * + * Return Value: + * Is being carried + * + * Example: + * [bob] call ace_medical_fnc_isBeingCarried + * + * Public: No + */ +#include "script_component.hpp" + +params ["_target"]; + +private "_owner"; + +_owner = _target getVariable [QEGVAR(common,owner), objNull]; + +if (isNull _owner) exitWith {false}; + +(_owner getVariable [QEGVAR(dragging,carriedObject), objNull]) == _target diff --git a/addons/medical_treatment/functions/fnc_isBeingDragged.sqf b/addons/medical_treatment/functions/fnc_isBeingDragged.sqf new file mode 100644 index 0000000000..929b48ccb7 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_isBeingDragged.sqf @@ -0,0 +1,26 @@ +/* + * Author: PabstMirror + * Returns if a target is being dragged. (from ace_dragging) + * + * Arguments: + * 0: Target Unit + * + * Return Value: + * Is being dragged + * + * Example: + * [bob] call ace_medical_fnc_isBeingDragged + * + * Public: No + */ +#include "script_component.hpp" + +params ["_target"]; + +private "_owner"; + +_owner = _target getVariable [QEGVAR(common,owner), objNull]; + +if (isNull _owner) exitWith {false}; + +(_owner getVariable [QEGVAR(dragging,draggedObject), objNull]) == _target diff --git a/addons/medical_treatment/functions/fnc_medicationEffectLoop.sqf b/addons/medical_treatment/functions/fnc_medicationEffectLoop.sqf new file mode 100644 index 0000000000..f7cdfdad07 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_medicationEffectLoop.sqf @@ -0,0 +1,42 @@ +/* + * Author: Glowbal, esteldunedain + * Medication effect loop for an injection. + * + * Arguments: + * 0: Unit + * 1: Name of the Variable that is affected + * 2: Proportion of the effect applied + * 3: Rate at which the effect is applied + * 4: Viscosity adjustment rate + * 5: Pain reduction rate + * + * ReturnValue: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_unit", "_variableName", "_amountDecreased","_decreaseRate", "_viscosityAdjustmentRate", "_painReduceRate"]; + +// If the unit died the loop is finished +if (!alive _unit) exitWith {}; + +// If locality changed finish the local loop +if (!local _unit) exitWith {}; + +// Apply medicinal effect +private _usedMeds = (_unit getVariable [_variableName, 0]) - _decreaseRate; +_unit setVariable [_variableName, _usedMeds]; + +// Restore the viscosity while the medication is leaving the system +_unit setVariable [QEGVAR(medical,peripheralResistance), ((_unit getVariable [QEGVAR(medical,peripheralResistance), 100]) - _viscosityAdjustmentRate) max 0]; +_unit setVariable [QEGVAR(medical,painSuppress), ((_unit getVariable [QEGVAR(medical,painSuppress), 0]) - _painReduceRate) max 0]; + +// Exit if the medication has finished it's effect +_amountDecreased = _amountDecreased + _decreaseRate; +if (_amountDecreased >= 1 || (_usedMeds <= 0) || !alive _unit) exitWith {}; + +// Schedule the loop to be executed again 1 sec later +[DFUNC(medicationEffectLoop), [_unit, _variableName, _amountDecreased, _decreaseRate, _viscosityAdjustmentRate, _painReduceRate], 1] call CBA_fnc_waitAndExecute; diff --git a/addons/medical_treatment/functions/fnc_modifyMedicalAction.sqf b/addons/medical_treatment/functions/fnc_modifyMedicalAction.sqf new file mode 100644 index 0000000000..6017ed9122 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_modifyMedicalAction.sqf @@ -0,0 +1,37 @@ +/* + * Author: esteldunedain + * Modify the visuals of a medical action point. + * On Basic medical: modify the icon color based on damage on that body part. + * + * Arguments: + * 0: The Patient Unit + * 1: The Diagnosing Unit + * 2: Selection Number + * 3: The action to modify + * + * ReturnValue: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_target", "_player", "_partNumber", "_actionData"]; + +private _bloodLossOnSelection = 0; +// Add all bleeding from wounds on selection +{ + _x params ["", "", "_selectionX", "_amountOf", "_percentageOpen"]; + if (_selectionX == _partNumber) then { + _bloodLossOnSelection = _bloodLossOnSelection + (_amountOf * _percentageOpen); + }; +} forEach (_target getvariable [QEGVAR(medical,openWounds), []]); + +if (_bloodLossOnSelection >=1 ) then { + _actionData set [2, QPATHTOEF(medical,UI\icons\medical_crossRed.paa)]; +} else { + if (_bloodLossOnSelection > 0 ) then { + _actionData set [2, QPATHTOEF(medical,UI\icons\medical_crossYellow.paa)]; + }; +}; diff --git a/addons/medical_treatment/functions/fnc_onMedicationUsage.sqf b/addons/medical_treatment/functions/fnc_onMedicationUsage.sqf new file mode 100644 index 0000000000..5683eb7486 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_onMedicationUsage.sqf @@ -0,0 +1,80 @@ +/* + * Author: Glowbal + * Handles the medication given to a patient. + * + * Arguments: + * 0: The patient + * 1: Medication Treatment classname + * 2: The medication treatment variablename + * 3: Max dosage + * 4: The time in the system + * 5: Incompatable medication > + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_target", "_className", "_variable", "_maxDosage", "_timeInSystem", "_incompatabileMeds", "_viscosityChange", "_painReduce"]; +TRACE_8("params",_target,_className,_variable,_maxDosage,_timeInSystem,_incompatabileMeds,_viscosityChange,_painReduce); + +private _foundEntry = false; +private _allUsedMedication = _target getVariable [QEGVAR(medical,allUsedMedication), []]; +{ + _x params ["_variableX", "_allMedsFromClassname"]; + if (_variableX== _variable) exitWith { + if !(_className in _allMedsFromClassname) then { + _allMedsFromClassname pushBack _className; + _x set [1, _allMedsFromClassname]; + _allUsedMedication set [_forEachIndex, _x]; + _target setVariable [QEGVAR(medical,allUsedMedication), _allUsedMedication]; + }; + _foundEntry = true; + }; +} forEach _allUsedMedication; + +if (!_foundEntry) then { + _allUsedMedication pushBack [_variable, [_className]]; + _target setVariable [QEGVAR(medical,allUsedMedication), _allUsedMedication]; +}; + + +private _usedMeds = _target getVariable [_variable, 0]; +if (_usedMeds >= floor (_maxDosage + round(random(2))) && _maxDosage >= 1 && GVAR(enableOverdosing)) then { + [_target] call EFUNC(medical,setDead); +}; + +private _hasOverDosed = 0; +{ + _x params ["_med", "_limit"]; + { + _x params ["", "_classNamesUsed"]; + if ({_x == _med} count _classNamesUsed > _limit) then { + _hasOverDosed = _hasOverDosed + 1; + }; + } forEach _allUsedMedication; +} forEach _incompatabileMeds; + +if (_hasOverDosed > 0 && GVAR(enableOverdosing)) then { + private _medicationConfig = (configFile >> "ace_medical_treatment" >> "Medication"); + private _onOverDose = getText (_medicationConfig >> "onOverDose"); + if (isClass (_medicationConfig >> _className)) then { + _medicationConfig = (_medicationConfig >> _className); + if (isText (_medicationConfig >> "onOverDose")) then { _onOverDose = getText (_medicationConfig >> "onOverDose"); }; + }; + if (isNil _onOverDose) then { + _onOverDose = compile _onOverDose; + } else { + _onOverDose = missionNamespace getVariable _onOverDose; + }; + [_target, _className] call _onOverDose; +}; + +private _decreaseAmount = 1 / _timeInSystem; +private _viscosityAdjustment = _viscosityChange / _timeInSystem; + +// Run the loop that computes the effect of the medication over time +[_target, _variable, 0, _decreaseAmount, _viscosityAdjustment, _painReduce / _timeInSystem] call FUNC(medicationEffectLoop); diff --git a/addons/medical_treatment/functions/fnc_treatment.sqf b/addons/medical_treatment/functions/fnc_treatment.sqf index 453d074f98..7322f8eba3 100644 --- a/addons/medical_treatment/functions/fnc_treatment.sqf +++ b/addons/medical_treatment/functions/fnc_treatment.sqf @@ -25,9 +25,9 @@ if (uiNamespace getVariable [QEGVAR(interact_menu,cursorMenuOpened),false]) exit if !(_target isKindOf "CAManBase") exitWith {false}; -private _config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className); +private _config = (configFile >> "ACE_Medical_Treatments" >> "Basic" >> _className); if (GVAR(level) >= 2) then { - _config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className); + _config = (configFile >> "ACE_Medical_Treatments" >> "Advanced" >> _className); }; if !(isClass _config) exitwith {false}; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPR.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPR.sqf new file mode 100644 index 0000000000..a634aa55a5 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPR.sqf @@ -0,0 +1,30 @@ +/* + * Author: Glowbal + * Callback for the CPR treatment action on success. + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * 3: Treatment classname + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName", "_className", "_items"]; + +if (alive _target && {(_target getVariable [QEGVAR(medical,inCardiacArrest), false] || _target getVariable [QEGVAR(medical,inReviveState), false])}) then { + [_target, "activity_view", ELSTRING(medical,Activity_cpr), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); + + if (local _target) then { + [QGVAR(treatmentAdvanced_CPRLocal), [_caller, _target]] call CBA_fnc_localEvent; + } else { + [QGVAR(treatmentAdvanced_CPRLocal), [_caller, _target], _target] call CBA_fnc_targetEvent; + }; +}; +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPRLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPRLocal.sqf new file mode 100644 index 0000000000..4e9ce5929f --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_CPRLocal.sqf @@ -0,0 +1,35 @@ +/* + * Author: Glowbal + * local Callback for the CPR treatment action on success. + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller","_target"]; + +if (_target getVariable [QEGVAR(medical,inReviveState), false]) then { + private _reviveStartTime = _target getVariable [QEGVAR(medical,reviveStartTime),0]; + if (_reviveStartTime > 0) then { + _target setVariable [QEGVAR(medical,reviveStartTime), (_reviveStartTime + random(20)) min CBA_missionTime]; + }; +}; + +if (EGVAR(medical,level) > 1 && {(random 1) >= 0.6}) then { + _target setVariable [QEGVAR(medical,inCardiacArrest), nil,true]; + _target setVariable [QEGVAR(medical,heartRate), 40]; + _target setVariable [QEGVAR(medical,bloodPressure), [50,70]]; +}; + +[_target, "activity", ELSTRING(medical,Activity_CPR), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); +[_target, "activity_view", ELSTRING(medical,Activity_CPR), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); // TODO expand message + +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandage.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandage.sqf new file mode 100644 index 0000000000..d0bf3ef2fe --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandage.sqf @@ -0,0 +1,38 @@ +/* + * Author: Glowbal + * IV Treatment callback + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * 3: Treatment classname + * 4: Item + * 5: specific Spot (default: -1) + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName", "_className", "_items", "", ["_specificSpot", -1]]; + +[_target, "activity", ELSTRING(medical,Activity_bandagedPatient), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); +[_target, "activity_view", ELSTRING(medical,Activity_bandagedPatient), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); // TODO expand message + +if (local _target) then { + [QGVAR(treatmentAdvanced_bandageLocal), [_target, _className, _selectionName, _specificSpot]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentAdvanced_bandageLocal), [_target, _className, _selectionName, _specificSpot], _target] call CBA_fnc_targetEvent; +}; + +/* { + if (_x != "") then { + [_target, _x] call FUNC(addToTriageCard); + }; +}forEach _items;*/ + +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandageLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandageLocal.sqf new file mode 100644 index 0000000000..7b879134cb --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_bandageLocal.sqf @@ -0,0 +1,173 @@ +/* + * Author: Glowbal + * Handles the bandage of a patient. + * + * Arguments: + * 0: The patient + * 1: Treatment classname + * + * + * Return Value: + * Succesful treatment started + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_target", "_bandage", "_selectionName", ["_specificClass", -1]]; + +// Ensure it is a valid bodypart +private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber); +if (_part < 0) exitWith {false}; + +// Get the open wounds for this unit +private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; +if (count _openWounds == 0) exitWith {false}; // nothing to do here! + +// Get the default effectiveness for the used bandage +private _config = (configFile >> "ace_medical_treatment" >> "Bandaging"); +private _effectiveness = getNumber (_config >> "effectiveness"); +if (isClass (_config >> _bandage)) then { + systemchat "using class: " + _bandage; + _config = (_config >> _bandage); + if (isNumber (_config >> "effectiveness")) then { _effectiveness = getNumber (_config >> "effectiveness");}; +} else { + systemChat format["No bandage avialable"]; +}; + +// Figure out which injury for this bodypart is the best choice to bandage +// TODO also use up the remainder on left over injuries +private _mostEffectiveSpot = 0; +private _effectivenessFound = -1; +private _mostEffectiveInjury = _openWounds select 0; +private _exit = false; +{ + _x params ["", "_classID", "_partX"]; + TRACE_2("OPENWOUND: ", _target, _x); + // Only parse injuries that are for the selected bodypart. + if (_partX == _part) then { + private _woundEffectiveness = _effectiveness; + + // Select the classname from the wound classname storage + private _className = EGVAR(medical,woundClassNames) select _classID; + + // Check if this wound type has attributes specified for the used bandage + if (isClass (_config >> _className)) then { + // Collect the effectiveness from the used bandage for this wound type + private _woundTreatmentConfig = (_config >> _className); + if (isNumber (_woundTreatmentConfig >> "effectiveness")) then { + _woundEffectiveness = getNumber (_woundTreatmentConfig >> "effectiveness"); + }; + } else { + ACE_LOGWARNING_2("No config for wound type [%1] config base [%2]", _className, _config); + }; + + TRACE_2("Wound classes: ", _specificClass, _classID); + if (_specificClass == _classID) exitWith { + _effectivenessFound = _woundEffectiveness; + _mostEffectiveSpot = _forEachIndex; + _mostEffectiveInjury = _x; + _exit = true; + }; + + // Check if this is the currently most effective found. + if (_woundEffectiveness * ((_x select 4) * (_x select 3)) > _effectivenessFound * ((_mostEffectiveInjury select 4) * (_mostEffectiveInjury select 3))) then { + _effectivenessFound = _woundEffectiveness; + _mostEffectiveSpot = _forEachIndex; + _mostEffectiveInjury = _x; + }; + }; + if (_exit) exitWith {}; +} forEach _openWounds; + +if (_effectivenessFound == -1) exitWith {}; // Seems everything is patched up on this body part already.. + + +// TODO refactor this part +// Find the impact this bandage has and reduce the amount this injury is present +private _impact = if ((_mostEffectiveInjury select 3) >= _effectivenessFound) then {_effectivenessFound} else { (_mostEffectiveInjury select 3) }; +_mostEffectiveInjury set [ 3, ((_mostEffectiveInjury select 3) - _impact) max 0]; +_openWounds set [_mostEffectiveSpot, _mostEffectiveInjury]; + +_target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; + +// Handle the reopening of bandaged wounds +if (_impact > 0 && {EGVAR(medical,level) >= 2} && {EGVAR(medical,enableAdvancedWounds)}) then { + [_target, _impact, _part, _mostEffectiveSpot, _mostEffectiveInjury, _bandage] call FUNC(handleBandageOpening); +}; + +// If all wounds to a body part have been bandaged, reset damage to that body part to zero +// so that the body part functions normally and blood is removed from the uniform. +// Arma combines left and right arms into a single body part (HitHands), same with left and right legs (HitLegs). +// Arms are actually hands. +if (EGVAR(medical,healHitPointAfterAdvBandage) || {EGVAR(medical,level) < 2}) then { + // Get the list of the wounds the target is currently suffering from. + private _currentWounds = _target getVariable [QEGVAR(medical,openWounds), []]; + + // Tally of unbandaged wounds to each body part. + private _headWounds = 0; + private _bodyWounds = 0; + private _legsWounds = 0; + private _armWounds = 0; + + // Loop through all current wounds and add up the number of unbandaged wounds on each body part. + { + _x params ["", "", "_bodyPart", "_numOpenWounds", "_bloodLoss"]; + + // Use switch/case for early termination if wounded limb is found before all six are checked. + // Number of wounds multiplied by blood loss will return zero for a fully + // bandaged body part, not incrementing the wound counter; or it will return + // some other number which will increment the wound counter. + switch (_bodyPart) do { + // Head + case 0: { + _headWounds = _headWounds + (_numOpenWounds * _bloodLoss); + }; + + // Body + case 1: { + _bodyWounds = _bodyWounds + (_numOpenWounds * _bloodLoss); + }; + + // Left Arm + case 2: { + _armWounds = _armWounds + (_numOpenWounds * _bloodLoss); + }; + + // Right Arm + case 3: { + _armWounds = _armWounds + (_numOpenWounds * _bloodLoss); + }; + + // Left Leg + case 4: { + _legsWounds = _legsWounds + (_numOpenWounds * _bloodLoss); + }; + + // Right Leg + case 5: { + _legsWounds = _legsWounds + (_numOpenWounds * _bloodLoss); + }; + }; + } forEach _currentWounds; + + // Any body part that has no wounds is healed to full health + if (_headWounds == 0) then { + _target setHitPointDamage ["hitHead", 0.0]; + }; + + if (_bodyWounds == 0) then { + _target setHitPointDamage ["hitBody", 0.0]; + }; + + if (_armWounds == 0) then { + _target setHitPointDamage ["hitHands", 0.0]; + }; + + if (_legsWounds == 0) then { + _target setHitPointDamage ["hitLegs", 0.0]; + }; +}; + +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHeal.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHeal.sqf new file mode 100644 index 0000000000..18bd0468d2 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHeal.sqf @@ -0,0 +1,21 @@ +/** + * fn_heal.sqf + * @Descr: N/A + * @Author: Glowbal + * + * @Arguments: [] + * @Return: + * @PublicAPI: false + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName", "_className", "_items"]; + +if (local _target) then { + [QGVAR(treatmentAdvanced_fullHealLocal), [_caller, _target]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentAdvanced_fullHealLocal), [_caller, _target], _target] call CBA_fnc_targetEvent; +}; + +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealLocal.sqf new file mode 100644 index 0000000000..2f60d47470 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealLocal.sqf @@ -0,0 +1,72 @@ +/** + * fn_healLocal.sqf + * @Descr: N/A + * @Author: Glowbal + * + * @Arguments: [] + * @Return: + * @PublicAPI: false + */ + +#include "script_component.hpp" + +params ["_caller", "_target"]; + +if (alive _target) exitWith { + + _target setVariable [QEGVAR(medical,pain), 0, true]; + _target setVariable [QEGVAR(medical,morphine), 0, true]; + _target setVariable [QEGVAR(medical,bloodVolume), 100, true]; + + // tourniquets + _target setVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0], true]; + + // wounds and injuries + _target setVariable [QEGVAR(medical,openWounds), [], true]; + _target setVariable [QEGVAR(medical,bandagedWounds), [], true]; + _target setVariable [QEGVAR(medical,internalWounds), [], true]; + + // vitals + _target setVariable [QEGVAR(medical,heartRate), 80]; + _target setVariable [QEGVAR(medical,heartRateAdjustments), []]; + _target setVariable [QEGVAR(medical,bloodPressure), [80, 120]]; + _target setVariable [QEGVAR(medical,peripheralResistance), 100]; + + // fractures + _target setVariable [QEGVAR(medical,fractures), []]; + + // IVs + _target setVariable [QEGVAR(medical,salineIVVolume), 0]; + _target setVariable [QEGVAR(medical,plasmaIVVolume), 0]; + _target setVariable [QEGVAR(medical,bloodIVVolume), 0]; + + // damage storage + _target setVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0], true]; + + // airway + _target setVariable [QEGVAR(medical,airwayStatus), 100, true]; + _target setVariable [QEGVAR(medical,airwayOccluded), false, true]; + _target setVariable [QEGVAR(medical,airwayCollapsed), false, true]; + + // generic medical admin + _target setVariable [QEGVAR(medical,addedToUnitLoop), false, true]; + _target setVariable [QEGVAR(medical,inCardiacArrest), false, true]; + _target setVariable [QEGVAR(medical,inReviveState), false, true]; + _target setVariable ["ACE_isUnconscious", false, true]; + _target setVariable [QEGVAR(medical,hasLostBlood), 0, true]; + _target setVariable [QEGVAR(medical,isBleeding), false, true]; + _target setVariable [QEGVAR(medical,hasPain), false, true]; + _target setVariable [QEGVAR(medical,painSuppress), 0, true]; + + // medication + private _allUsedMedication = _target getVariable [QEGVAR(medical,allUsedMedication), []]; + { + _target setVariable [_x select 0, nil]; + } forEach _allUsedMedication; + + // Resetting damage + _target setDamage 0; + + [_target, "activity", ELSTRING(medical,Activity_fullHeal), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); + [_target, "activity_view", ELSTRING(medical,Activity_fullHeal), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); // TODO expand message +}; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealTreatmentTime.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealTreatmentTime.sqf new file mode 100644 index 0000000000..9e55a5c9db --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_fullHealTreatmentTime.sqf @@ -0,0 +1,24 @@ +/* + * Author: Ruthberg + * Calculates the personal aid kit treatment time based on amount of damage to heal + * + * Arguments: + * unit + * + * Return Value: + * treatment time + * + * Example: + * [_target] call ace_medical_fnc_treatmentAdvanced_fullHealTreatmentTime + * + * Public: No + */ +#include "script_component.hpp" + +private _totalDamage = 0; + +{ + _totalDamage = _totalDamage + _x; +} forEach (_this getVariable [QEGVAR(medical,bodyPartStatus), []]); + +(10 max (_totalDamage * 10) min 120) diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_medication.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_medication.sqf new file mode 100644 index 0000000000..b9b236f1dc --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_medication.sqf @@ -0,0 +1,36 @@ +/* + * Author: Glowbal + * IV Treatment callback + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * 3: Treatment classname + * 4: Items Used + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName", "_className", "_items"]; +TRACE_5("params",_caller,_target,_selectionName,_className,_items); + +private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber); + +[QGVAR(treatmentAdvanced_medicationLocal), [_target, _className, _part], [_target]] call CBA_fnc_targetEvent; + +{ + if (_x != "") then { + [_target, _x] call FUNC(addToTriageCard); + [_target, "activity", ELSTRING(medical,Activity_usedItem), [[_caller, false, true] call EFUNC(common,getName), getText (configFile >> "CfgWeapons" >> _x >> "displayName")]] call FUNC(addToLog); + [_target, "activity_view", ELSTRING(medical,Activity_usedItem), [[_caller, false, true] call EFUNC(common,getName), getText (configFile >> "CfgWeapons" >> _x >> "displayName")]] call FUNC(addToLog); + }; +} forEach _items; + + +true; diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_medicationLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_medicationLocal.sqf new file mode 100644 index 0000000000..85b5505544 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_medicationLocal.sqf @@ -0,0 +1,98 @@ +/* + * Author: Glowbal + * Handles the medication given to a patient. + * + * Arguments: + * 0: The patient + * 1: Treatment classname + * 2: Injection Site Part Number + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_target", "_className", "_partNumber"]; +TRACE_3("params",_target,_className,_partNumber); + +private _tourniquets = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; +if ((_tourniquets select _partNumber) > 0) exitWith { + TRACE_1("unit has tourniquets blocking blood flow on injection site",_tourniquets); + private _delayedMedications = _target getVariable [QGVAR(occludedMedications), []]; + _delayedMedications pushBack _this; + _target setVariable [QGVAR(occludedMedications), _delayedMedications, true]; + true +}; + +// We have added a new dose of this medication to our system, so let's increase it +private _varName = format[QGVAR(%1_inSystem), _className]; +private _currentInSystem = _target getVariable [_varName, 0]; +_target setVariable [_varName, _currentInSystem + 1]; + +// Find the proper attributes for the used medication +private _medicationConfig = (configFile >> "ace_medical_treatment" >> "Medication"); +private _painReduce = getNumber (_medicationConfig >> "painReduce"); +private _hrIncreaseLow = getArray (_medicationConfig >> "hrIncreaseLow"); +private _hrIncreaseNorm = getArray (_medicationConfig >> "hrIncreaseNormal"); +private _hrIncreaseHigh = getArray (_medicationConfig >> "hrIncreaseHigh"); +private _timeInSystem = getNumber (_medicationConfig >> "timeInSystem"); +private _maxDose = getNumber (_medicationConfig >> "maxDose"); +private _viscosityChange = getNumber (_medicationConfig >> "viscosityChange"); +private _hrCallback = getText (_medicationConfig >> "hrCallback"); + +private _inCompatableMedication = []; +if (isClass (_medicationConfig >> _className)) then { + _medicationConfig = (_medicationConfig >> _className); + if (isNumber (_medicationConfig >> "painReduce")) then { _painReduce = getNumber (_medicationConfig >> "painReduce");}; + if (isArray (_medicationConfig >> "hrIncreaseLow")) then { _hrIncreaseLow = getArray (_medicationConfig >> "hrIncreaseLow"); }; + if (isArray (_medicationConfig >> "hrIncreaseNormal")) then { _hrIncreaseNorm = getArray (_medicationConfig >> "hrIncreaseNormal"); }; + if (isArray (_medicationConfig >> "hrIncreaseHigh")) then { _hrIncreaseHigh = getArray (_medicationConfig >> "hrIncreaseHigh"); }; + if (isNumber (_medicationConfig >> "timeInSystem")) then { _timeInSystem = getNumber (_medicationConfig >> "timeInSystem"); }; + if (isNumber (_medicationConfig >> "maxDose")) then { _maxDose = getNumber (_medicationConfig >> "maxDose"); }; + if (isArray (_medicationConfig >> "inCompatableMedication")) then { _inCompatableMedication = getArray (_medicationConfig >> "inCompatableMedication"); }; + if (isNumber (_medicationConfig >> "viscosityChange")) then { _viscosityChange = getNumber (_medicationConfig >> "viscosityChange"); }; + if (isText (_medicationConfig >> "hrCallback")) then { _hrCallback = getText (_medicationConfig >> "hrCallback"); }; +}; +if (isNil _hrCallback) then { + _hrCallback = compile _hrCallback; +} else { + _hrCallback = missionNamespace getVariable _hrCallback; +}; +if (!(_hrCallback isEqualType {})) then {_hrCallback = {TRACE_1("callback was NOT code",_hrCallback)};}; + +// Adjust the heart rate based upon config entry +private _heartRate = _target getVariable [QEGVAR(medical,heartRate), 70]; +if (alive _target) then { + if (_heartRate > 0) then { + if (_heartRate <= 45) then { + [_target, ((_hrIncreaseLow select 0) + random ((_hrIncreaseLow select 1) - (_hrIncreaseLow select 0))), (_hrIncreaseLow select 2), _hrCallback] call FUNC(addHeartRateAdjustment); + } else { + if (_heartRate > 120) then { + [_target, ((_hrIncreaseHigh select 0) + random ((_hrIncreaseHigh select 1) - (_hrIncreaseHigh select 0))), (_hrIncreaseHigh select 2), _hrCallback] call FUNC(addHeartRateAdjustment); + } else { + [_target, ((_hrIncreaseNorm select 0) + random ((_hrIncreaseNorm select 1) - (_hrIncreaseNorm select 0))), (_hrIncreaseNorm select 2), _hrCallback] call FUNC(addHeartRateAdjustment); + }; + }; + }; +}; + +if (_painReduce > 0) then { + // Reduce pain + private _painSuppress = _target getVariable [QEGVAR(medical,painSuppress), 0]; + _target setVariable [QEGVAR(medical,painSuppress), (_painSuppress + _painReduce) max 0]; + if (!GVAR(painIsOnlySuppressed)) then { + _pain = _target getVariable [QEGVAR(medical,pain), 0]; + _target setVariable [QEGVAR(medical,pain), (_pain - _painReduce) max 0, true]; + }; +}; + +private _resistance = _target getVariable [QEGVAR(medical,peripheralResistance), 100]; +_target setVariable [QEGVAR(medical,peripheralResistance), (_resistance + _viscosityChange) max 0]; + +// Call back to ensure that the medication is decreased over time +[_target, _classname, _varName, _maxDose, _timeInSystem, _inCompatableMedication, _viscosityChange, _painReduce] call FUNC(onMedicationUsage); + +true diff --git a/addons/medical_treatment/functions/fnc_treatmentAdvanced_surgicalKit_onProgress.sqf b/addons/medical_treatment/functions/fnc_treatmentAdvanced_surgicalKit_onProgress.sqf new file mode 100644 index 0000000000..94702ee9c3 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentAdvanced_surgicalKit_onProgress.sqf @@ -0,0 +1,35 @@ +/* + * Author: BaerMitUmlaut + * Handles treatment via surgical kit per frame + * + * Arguments: + * 0: Arguments + * 0: Caller + * 1: Target + * 1: Elapsed Time + * 2: Total Time + * + * Return Value: + * Succesful treatment started + * + * Public: No + */ +#include "script_component.hpp" + + +private "_bandagedWounds"; +params ["_args", "_elapsedTime", "_totalTime"]; +_args params ["_caller", "_target"]; + +_bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; + +//In case two people stitch up one patient and the last wound has already been closed we can stop already +if (count _bandagedWounds == 0) exitWith { false }; + +//Has enough time elapsed that we can close another wound? +if ((_totalTime - _elapsedTime) <= (((count _bandagedWounds) - 1) * 5)) then { + _bandagedWounds deleteAt 0; + _target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; +}; + +true diff --git a/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbag.sqf b/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbag.sqf new file mode 100644 index 0000000000..6989ac14b8 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbag.sqf @@ -0,0 +1,25 @@ +/* + * Author: KoffeinFlummi + * Callback when the bloodbag treatment is complete + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: Selection Name + * 3: Treatment classname + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_treatmentClassname"]; + +if (local _target) then { + [QGVAR(treatmentBasic_bloodbagLocal), [_target, _treatmentClassname]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentBasic_bloodbagLocal), [_target, _treatmentClassname], _target] call CBA_fnc_targetEvent; +}; diff --git a/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbagLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbagLocal.sqf new file mode 100644 index 0000000000..144e386f3a --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentBasic_bloodbagLocal.sqf @@ -0,0 +1,27 @@ +/* + * Author: KoffeinFlummi + * Local callback when the bloodbag treatment is complete + * + * Arguments: + * 0: The patient + * 1: Treatment Classname + * + * Return Value: + * nil + * + * Public: No + */ + +#include "script_component.hpp" +#define BLOODBAGHEAL 70 + +params ["_target", "_treatmentClassname"]; + +private _bloodAdded = switch (true) do { + case (_treatmentClassname == "BloodIV_250"): {0.25 * BLOODBAGHEAL}; + case (_treatmentClassname == "BloodIV_500"): {0.5 * BLOODBAGHEAL}; + default {BLOODBAGHEAL}; +}; + +private _blood = ((_target getVariable [QEGVAR(medical,bloodVolume), 100]) + _bloodAdded) min 100; +_target setVariable [QEGVAR(medical,bloodVolume), _blood, true]; diff --git a/addons/medical_treatment/functions/fnc_treatmentBasic_epipen.sqf b/addons/medical_treatment/functions/fnc_treatmentBasic_epipen.sqf new file mode 100644 index 0000000000..1c75beb10d --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentBasic_epipen.sqf @@ -0,0 +1,24 @@ +/* + * Author: KoffeinFlummi + * Callback when the epipen treatment is complete + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: Selection Name + * 3: Treatment classname + * + * Return Value: + * None + * + * Public: No + */ +#include "script_component.hpp" + +params ["_caller", "_target","_className"]; + +[_target, false] call FUNC(setUnconscious); + +if (_target getVariable [QEGVAR(medical,inReviveState), false]) then { + _target setVariable [QEGVAR(medical,inReviveState), nil, true]; +}; diff --git a/addons/medical_treatment/functions/fnc_treatmentBasic_morphine.sqf b/addons/medical_treatment/functions/fnc_treatmentBasic_morphine.sqf new file mode 100644 index 0000000000..f704a67042 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentBasic_morphine.sqf @@ -0,0 +1,26 @@ +/* + * Author: KoffeinFlummi + * Callback when the morphine treatment is complete + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: Selection Name + * 3: Treatment classname + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" +#define MORPHINEHEAL 0.4 + +params ["_caller", "_target"]; + +if (local _target) then { + [QGVAR(treatmentBasic_morphineLocal), [_target]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentBasic_morphineLocal), [_target], _target] call CBA_fnc_targetEvent; +}; diff --git a/addons/medical_treatment/functions/fnc_treatmentBasic_morphineLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentBasic_morphineLocal.sqf new file mode 100644 index 0000000000..89429d4247 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentBasic_morphineLocal.sqf @@ -0,0 +1,27 @@ +/* + * Author: KoffeinFlummi + * Local callback when the morphine treatment is complete + * + * Arguments: + * 0: The medic + * 1: The patient + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" +#define MORPHINEHEAL 0.4 + +params ["_target"]; + +// reduce pain, pain sensitivity +private _morphine = ((_target getVariable [QEGVAR(medical,morphine), 0]) + MORPHINEHEAL) min 1; +_target setVariable [QEGVAR(medical,morphine), _morphine, true]; + +private _pain = ((_target getVariable [QEGVAR(medical,pain), 0]) - MORPHINEHEAL) max 0; +_target setVariable [QEGVAR(medical,pain), _pain, true]; + +// @todo overdose diff --git a/addons/medical_treatment/functions/fnc_treatmentIV.sqf b/addons/medical_treatment/functions/fnc_treatmentIV.sqf new file mode 100644 index 0000000000..2378f2bfca --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentIV.sqf @@ -0,0 +1,35 @@ +/* + * Author: Glowbal + * Patient IV Treatment callback + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * 3: Treatment classname + * + * Return Value: + * Succesful treatment started + * + * Public: Yes + */ + +#include "script_component.hpp" + +private "_removeItem"; +params ["_caller", "_target", "_selectionName", "_className", "_items"]; + +if (count _items == 0) exitWith {false}; + +_removeItem = _items select 0; +if (local _target) then { + [QGVAR(treatmentIVLocal), [_target, _className]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentIVLocal), [_target, _className], _target] call CBA_fnc_targetEvent; +}; + +[_target, _removeItem] call FUNC(addToTriageCard); +[_target, "activity", ELSTRING(medical,Activity_gaveIV), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); +[_target, "activity_view", ELSTRING(medical,Activity_gaveIV), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); // TODO expand message + +true diff --git a/addons/medical_treatment/functions/fnc_treatmentIVLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentIVLocal.sqf new file mode 100644 index 0000000000..e00200b33e --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentIVLocal.sqf @@ -0,0 +1,42 @@ +/* + * Author: Glowbal + * IV Treatment local callback + * + * Arguments: + * 0: The medic + * 1: Treatment classname + * + * + * Return Value: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_target", "_treatmentClassname"]; + +private _bloodVolume = _target getVariable [QEGVAR(medical,bloodVolume), 100]; +if (_bloodVolume >= 100) exitWith {}; + +// Find the proper attributes for the used IV +private _config = (configFile >> "ace_medical_treatment" >> "IV"); +private _volumeAdded = getNumber (_config >> "volume"); +private _typeOf = getText (_config >> "type"); + +if (isClass (_config >> _treatmentClassname)) then { + _config = (_config >> _treatmentClassname); + if (isNumber (_config >> "volume")) then { _volumeAdded = getNumber (_config >> "volume");}; + if (isText (_config >> "type")) then { _typeOf = getText (_config >> "type"); }; +} else { + ERROR("IV Treatment Classname not found"); +}; + +private _varName = format["ACE_Medical_IVVolume_%1",_typeOf]; +_target setVariable [_varName, (_target getVariable [_varName, 0]) + _volumeAdded, true]; + +if !(_varName in EGVAR(medical,IVBags)) then { + EGVAR(medical,IVBags) pushBack _varName; + publicVariable QEGVAR(medical,IVBags) +}; diff --git a/addons/medical_treatment/functions/fnc_treatmentTourniquet.sqf b/addons/medical_treatment/functions/fnc_treatmentTourniquet.sqf new file mode 100644 index 0000000000..89b94375c4 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentTourniquet.sqf @@ -0,0 +1,48 @@ +/* + * Author: Glowbal + * Apply a tourniquet to the patient + * + * Arguments: + * 0: The medic + * 1: The patient + * 2: SelectionName + * 3: Treatment classname + * + * + * Return Value: + * Succesful treatment started + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_caller", "_target", "_selectionName", "_className", "_items"]; + +if (count _items == 0) exitWith {false}; + +private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber); +if (_part == 0 || _part == 1) exitWith { + // [QEGVAR(common,displayTextStructured), ["You cannot apply a CAT on this body part!"], [_caller]] call CBA_fnc_targetEvent; + false; +}; + +private _tourniquets = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; +if ((_tourniquets select _part) > 0) exitWith { + _output = "There is already a tourniquet on this body part!"; // TODO localization + [QEGVAR(common,displayTextStructured), [_output, 1.5, _caller], [_caller]] call CBA_fnc_targetEvent; + false; +}; + +private _removeItem = _items select 0; +if (local _target) then { + [QGVAR(treatmentTourniquetLocal), [_target, _removeItem, _selectionName]] call CBA_fnc_localEvent; +} else { + [QGVAR(treatmentTourniquetLocal), [_target, _removeItem, _selectionName], _target] call CBA_fnc_targetEvent; +}; + +[_target, _removeItem] call FUNC(addToTriageCard); +[_target, "activity", ELSTRING(medical,Activity_appliedTourniquet), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); +[_target, "activity_view", ELSTRING(medical,Activity_appliedTourniquet), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); // TODO expand message + +true diff --git a/addons/medical_treatment/functions/fnc_treatmentTourniquetLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentTourniquetLocal.sqf new file mode 100644 index 0000000000..cf886b292a --- /dev/null +++ b/addons/medical_treatment/functions/fnc_treatmentTourniquetLocal.sqf @@ -0,0 +1,26 @@ +/* + * Author: Glowbal + * Apply a tourniquet to the patient, local callback. + * + * Arguments: + * 0: The patient + * 1: Item used classname + * + * Return Value: + * None + * + * Public: No + */ +#include "script_component.hpp" + +params ["_target", "_tourniquetItem", "_selectionName"]; + +//If we're not already tracking vitals, start: +[_target] call EFUNC(medical,addVitalLoop); + +private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber); + +// Place a tourniquet on the bodypart +private _tourniquets = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; +_tourniquets set [_part, CBA_missionTime]; +_target setVariable [QEGVAR(medical,tourniquets), _tourniquets, true]; diff --git a/addons/medical_treatment/functions/fnc_treatment_failure.sqf b/addons/medical_treatment/functions/fnc_treatment_failure.sqf index d81c576feb..4b7955c747 100644 --- a/addons/medical_treatment/functions/fnc_treatment_failure.sqf +++ b/addons/medical_treatment/functions/fnc_treatment_failure.sqf @@ -57,9 +57,9 @@ if ((_weaponSelect params [["_previousWeapon", ""]]) && {(_previousWeapon != "") } forEach _usersOfItems; // Record specific callback -private _config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className); +private _config = (configFile >> "ACE_Medical_Treatments" >> "Basic" >> _className); if (GVAR(level) >= 2) then { - _config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className); + _config = (configFile >> "ACE_Medical_Treatments" >> "Advanced" >> _className); }; private _callback = getText (_config >> "callbackFailure"); diff --git a/addons/medical_treatment/functions/fnc_treatment_success.sqf b/addons/medical_treatment/functions/fnc_treatment_success.sqf index eb52d20e3c..cb4311cd22 100644 --- a/addons/medical_treatment/functions/fnc_treatment_success.sqf +++ b/addons/medical_treatment/functions/fnc_treatment_success.sqf @@ -52,9 +52,9 @@ if ((_weaponSelect params [["_previousWeapon", ""]]) && {(_previousWeapon != "") }; // Record specific callback -private _config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className); +private _config = (configFile >> "ACE_Medical_Treatments" >> "Basic" >> _className); if (GVAR(level) >= 2) then { - _config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className); + _config = (configFile >> "ACE_Medical_Treatments" >> "Advanced" >> _className); }; private _callback = getText (_config >> "callbackSuccess"); diff --git a/addons/medical_treatment/functions/fnc_useItem.sqf b/addons/medical_treatment/functions/fnc_useItem.sqf new file mode 100644 index 0000000000..9f00d530d8 --- /dev/null +++ b/addons/medical_treatment/functions/fnc_useItem.sqf @@ -0,0 +1,58 @@ +/* + * Author: Glowbal + * Use Equipment if any is available. Priority: 1) Medic, 2) Patient. If in vehicle: 3) Crew + * + * Arguments: + * 0: Medic + * 1: Patient + * 2: Item + * + * ReturnValue: + * 0: success + * 1: Unit + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_medic", "_patient", "_item"]; + +if (isNil QEGVAR(medical,setting_allowSharedEquipment)) then { + EGVAR(medical,setting_allowSharedEquipment)= true; +}; + +if (EGVAR(medical,setting_allowSharedEquipment) && {[_patient, _item] call EFUNC(common,hasItem)}) exitWith { + if (local _patient) then { + ["ace_useItem", [_patient, _item]] call CBA_fnc_localEvent; + } else { + ["ace_useItem", [_patient, _item], _patient] call CBA_fnc_targetEvent; + }; + [true, _patient]; +}; + +if ([_medic, _item] call EFUNC(common,hasItem)) exitWith { + if (local _medic) then { + ["ace_useItem", [_medic, _item]] call CBA_fnc_localEvent; + } else { + ["ace_useItem", [_medic, _item], _medic] call CBA_fnc_targetEvent; + }; + [true, _medic]; +}; + +private _return = [false, objNull]; +if ([vehicle _medic] call FUNC(isMedicalVehicle) && {vehicle _medic != _medic}) then { + private _crew = crew vehicle _medic; + { + if ([_medic, _x] call FUNC(canAccessMedicalEquipment) && {([_x, _item] call EFUNC(common,hasItem))}) exitWith { + _return = [true, _x]; + if (local _x) then { + ["ace_useItem", [_x, _item]] call CBA_fnc_localEvent; + } else { + ["ace_useItem", [_x, _item], _x] call CBA_fnc_targetEvent; + }; + }; + } forEach _crew; +}; + +_return diff --git a/addons/medical_treatment/functions/fnc_useItems.sqf b/addons/medical_treatment/functions/fnc_useItems.sqf new file mode 100644 index 0000000000..aac7b0623a --- /dev/null +++ b/addons/medical_treatment/functions/fnc_useItems.sqf @@ -0,0 +1,37 @@ +/* + * Author: Glowbal + * Use Equipment items if any is available. Priority: 1) Medic, 2) Patient. If in vehicle: 3) Crew + * + * Arguments: + * 0: Medic + * 1: Patient + * 2: Items > + * + * ReturnValue: + * None + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_medic", "_patient", "_items"]; + +private _itemsUsedBy = []; +{ + // handle a one of type use item + if (_x isEqualType []) then { + { + private _itemUsedInfo = [_medic, _patient, _x] call FUNC(useItem); + if (_itemUsedInfo select 0) exitWith { _itemsUsedBy pushBack [(_itemUsedInfo select 1), _x]}; + } forEach _x; + }; + + // handle required item + if (_x isEqualType "") then { + private _itemUsedInfo = [_medic, _patient, _x] call FUNC(useItem); + if (_itemUsedInfo select 0) exitWith { _itemsUsedBy pushBack [(_itemUsedInfo select 1), _x]}; + }; +} forEach _items; + +[count _items == count _itemsUsedBy, _itemsUsedBy]; diff --git a/addons/medical_treatment/stringtable.xml b/addons/medical_treatment/stringtable.xml new file mode 100644 index 0000000000..789a83cd99 --- /dev/null +++ b/addons/medical_treatment/stringtable.xml @@ -0,0 +1,5 @@ + + + + +