Merge pull request #172 from KoffeinFlummi/Medical_Improvements

Medical improvements
This commit is contained in:
Glowbal 2015-03-09 23:29:55 +01:00
commit 9709fa17c0
51 changed files with 2321 additions and 251 deletions

View File

@ -11,7 +11,7 @@ class ACE_Medical_Actions {
treatmentTime = 5;
treatmentTimeSelfCoef = 1;
items[] = {{QGVAR(fieldDressing), QGVAR(packingBandage), QGVAR(elasticBandage), QGVAR(quikClot)}};
condition = "";
itemConsumed = 1;
callbackSuccess = QUOTE(DFUNC(treatmentBasic_bandage));
@ -53,8 +53,6 @@ class ACE_Medical_Actions {
};
class Advanced {
// cse_surgical_kit cse_bandage_basic cse_packing_bandage cse_bandageElastic cse_tourniquet cse_splint cse_morphine cse_atropine cse_epinephrine cse_plasma_iv cse_plasma_iv_500 cse_plasma_iv250 cse_blood_iv cse_blood_iv_500 cse_blood_iv_250 cse_saline_iv cse_saline_iv_500 cse_saline_iv_250 cse_quikclot cse_nasopharyngeal_tube cse_opa cse_liquidSkin cse_chestseal cse_personal_aid_kit
class FieldDressing {
// Which locations can this treatment action be used? Available: Field, MedicalFacility, MedicalVehicle, All.
treatmentLocations[] = {"All"};
@ -64,13 +62,17 @@ class ACE_Medical_Actions {
treatmentTime = 5;
// Item required for the action. Leave empty for no item required.
items[] = {QGVAR(fieldDressing)};
condition = "";
// Callbacks
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_bandage));
callbackFailure = "";
callbackProgress = "";
animationPatient = "";
animationCaller = ""; // TODO
itemConsumed = 1;
animationPatient = "";
animationCaller = "AinvPknlMstpSnonWnonDnon_medic4";
animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medic";
animationCallerSelf = "AinvPknlMstpSlayW[wpn]Dnon_medic";
animationCallerSelfProne = "AinvPpneMstpSlayW[wpn]Dnon_medic";
};
class PackingBandage: fieldDressing {
items[] = {QGVAR(packingBandage)};
@ -85,16 +87,18 @@ class ACE_Medical_Actions {
items[] = {QGVAR(tourniquet)};
treatmentTime = 6;
callbackSuccess = QUOTE(DFUNC(treatmentTourniquet));
condition = QUOTE(!([ARR_2(_this select 1, _this select 2)] call FUNC(hasTourniquetAppliedTo)));
};
class Morphine: fieldDressing {
items[] = {QGVAR(morphine)};
treatmentTime = 3;
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_medication));
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class Atropine: fieldDressing {
class Atropine: Morphine {
items[] = {QGVAR(atropine)};
};
class Epinephrine: fieldDressing {
class Epinephrine: Morphine {
items[] = {QGVAR(epinephrine)};
};
class BloodIV: fieldDressing {
@ -102,6 +106,7 @@ class ACE_Medical_Actions {
requiredMedic = 1;
treatmentTime = 7;
callbackSuccess = QUOTE(DFUNC(treatmentIV));
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class BloodIV_500: BloodIV {
items[] = {QGVAR(bloodIV_500)};
@ -111,6 +116,7 @@ class ACE_Medical_Actions {
};
class PlasmaIV: BloodIV {
items[] = {QGVAR(plasmaIV)};
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class PlasmaIV_500: PlasmaIV {
items[] = {QGVAR(plasmaIV_500)};
@ -120,6 +126,7 @@ class ACE_Medical_Actions {
};
class SalineIV: BloodIV {
items[] = {QGVAR(salineIV)};
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class SalineIV_500: SalineIV {
items[] = {QGVAR(salineIV_500)};
@ -134,6 +141,7 @@ class ACE_Medical_Actions {
treatmentTime = 15;
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_surgicalKit));
itemConsumed = 0;
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class PersonalAidKit: fieldDressing {
items[] = {QGVAR(personalAidKit)};
@ -142,6 +150,7 @@ class ACE_Medical_Actions {
treatmentTime = 15;
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_fullHeal));
itemConsumed = 0;
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
};
class CheckPulse: fieldDressing {
treatmentLocations[] = {"All"};
@ -164,12 +173,14 @@ class ACE_Medical_Actions {
class RemoveTourniquet: CheckPulse {
treatmentTime = 2.5;
callbackSuccess = QUOTE(DFUNC(actionRemoveTourniquet));
condition = QUOTE([ARR_2(_this select 1, _this select 2)] call FUNC(hasTourniquetAppliedTo));
};
class CPR: fieldDressing {
treatmentLocations[] = {"All"};
requiredMedic = 0;
treatmentTime = 25;
items[] = {};
condition = ""; // unconscious?
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_CPR));
callbackFailure = "";
callbackProgress = "";
@ -177,6 +188,18 @@ class ACE_Medical_Actions {
animationCaller = ""; // TODO
itemConsumed = 0;
};
class BodyBag: fieldDressing {
treatmentLocations[] = {"All"};
requiredMedic = 0;
treatmentTime = 7.5;
items[] = {QVAR(bodyBag)};
condition = "!alive (_this select 1);";
callbackSuccess = QUOTE(DFUNC(actionPlaceInBodyBag));
callbackFailure = "";
callbackProgress = "";
animationPatient = "";
itemConsumed = 0;
};
};
};
@ -193,7 +216,7 @@ class ACE_Medical_Advanced {
name = "Scrape";
selections[] = {"All"};
bleedingRate = 0.0001;
pain = 0.1;
pain = 0.01;
causes[] = {"falling", "ropeburn", "vehiclecrash"};
minDamage = 0.01;
class Minor {
@ -215,7 +238,7 @@ class ACE_Medical_Advanced {
name = "Avulsion";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.3;
causes[] = {"explosive", "vehiclecrash", "grenade", "shell", "bullet", "backblast", "bite"};
minDamage = 0.2;
class Minor {
@ -237,7 +260,7 @@ class ACE_Medical_Advanced {
name = "Bruise";
selections[] = {"All"};
bleedingRate = 0.0;
pain = 1;
pain = 0.05;
causes[] = {"bullet", "backblast", "punch","vehiclecrash","falling"};
minDamage = 0.01;
class Minor {
@ -256,7 +279,7 @@ class ACE_Medical_Advanced {
name = "Crushed tissue";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.1;
causes[] = {"falling", "vehiclecrash", "punch"};
minDamage = 0.1;
class Minor {
@ -278,7 +301,7 @@ class ACE_Medical_Advanced {
name = "Cut";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.075;
causes[] = {"vehiclecrash", "grenade", "explosive", "shell", "backblast", "stab"};
minDamage = 0.1;
class Minor {
@ -300,7 +323,7 @@ class ACE_Medical_Advanced {
name = "Tear";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.075;
causes[] = {"vehiclecrash", "punch"};
minDamage = 0.01;
class Minor {
@ -322,7 +345,7 @@ class ACE_Medical_Advanced {
name = "Velocity Wound";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.2;
causes[] = {"bullet", "grenade","explosive", "shell"};
minDamage = 0.15;
class Minor {
@ -344,7 +367,7 @@ class ACE_Medical_Advanced {
name = "Puncture Wound";
selections[] = {"All"};
bleedingRate = 0.01;
pain = 1;
pain = 0.075;
causes[] = {"stab", "grenade"};
minDamage = 0.01;
class Minor {
@ -365,7 +388,7 @@ class ACE_Medical_Advanced {
class Femur {
name = "Broken Femur";
selections[] = {"Head", "Torso"};
pain = 20;
pain = 0.2;
causes[] = {"Bullet", "VehicleCrash", "Backblast", "Explosive", "Shell", "Grenade"};
minDamage = 0.5;
};

View File

@ -0,0 +1,71 @@
class ACE_Settings {
class GVAR(level) {
value = 1;
typeName = "SCALAR";
values[] = {"Disabled", "Basic", "Advanced"};
};
class GVAR(medicSetting) {
value = 1;
typeName = "SCALAR";
values[] = {"Disabled", "Normal", "Advanced"};
};
class GVAR(enableFor) {
value = 0;
typeName = "SCALAR";
values[] = {"Players only", "Players and AI"};
};
class GVAR(maxRevives) {
typeName = "NUMBER";
value = 1;
};
class GVAR(enableOverdosing) {
typeName = "BOOL";
value = true;
};
class GVAR(bleedingCoefficient) {
typeName = "NUMBER";
value = 1;
};
class GVAR(enableAirway) {
typeName = "BOOL";
value = false;
};
class GVAR(enableFractures) {
typeName = "BOOL";
value = false;
};
class GVAR(enableAdvancedWounds) {
typeName = "BOOL";
value = false;
};
class GVAR(enableVehicleCrashes) {
typeName = "BOOL";
value = true;
};
class GVAR(enableScreams) {
typeName = "BOOL";
value = true;
};
class GVAR(playerDamageThreshold) {
typeName = "NUMBER";
value = 1;
};
class GVAR(AIDamageThreshold) {
typeName = "NUMBER";
value = 1;
};
class GVAR(enableUnsconsiousnessAI) {
value = 1;
typeName = "NUMBER";
values[] = {"Disabled", "Enabled", "50/50"};
};
class GVAR(preventInstaDeath) {
typeName = "BOOL";
value = false;
};
class GVAR(maxReviveTime) {
typeName = "NUMBER";
value = 120;
};
};

View File

@ -26,3 +26,19 @@ class Extended_Respawn_EventHandlers {
};
};
};
class Extended_Killed_EventHandlers {
class CAManBase {
class ADDON {
killed = QUOTE(call FUNC(handleKilled));
};
};
};
class Extended_Local_EventHandlers {
class CAManBase {
class ADDON {
local = QUOTE(call FUNC(handleLocal));
};
};
};

View File

@ -0,0 +1,6 @@
class CfgFactionClasses {
class NO_CATEGORY;
class ADDON: NO_CATEGORY {
displayName = "ACE Medical";
};
};

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
#include "script_component.hpp"
if (!hasInterface) exitwith{};
GVAR(enabledFor) = 1; // TODO remove this once we implement settings. Just here to get the vitals working.
GVAR(heartBeatSounds_Fast) = ["ACE_heartbeat_fast_1", "ACE_heartbeat_fast_2", "ACE_heartbeat_fast_3"];
GVAR(heartBeatSounds_Normal) = ["ACE_heartbeat_norm_1", "ACE_heartbeat_norm_2"];
@ -138,7 +139,7 @@ if (isNil QGVAR(level)) then {
// HEARTRATE BASED EFFECTS
[{
_heartRate = ACE_player getVariable [QGVAR(heartRate), 70];
if (GVAR(level) == 0) then {
if (GVAR(level) == 1) then {
_heartRate = 60 + 40 * (ACE_player getVariable [QGVAR(pain), 0]);
};
if (_heartRate <= 0) exitwith {};
@ -197,7 +198,7 @@ if (isNil QGVAR(level)) then {
};
};
if (GVAR(level) > 0 && {_heartRate > 0}) then {
if (GVAR(level) >= 2 && {_heartRate > 0}) then {
_minTime = 60 / _heartRate;
if (time - GVAR(lastHeartBeatSound) > _minTime) then {
GVAR(lastHeartBeatSound) = time;
@ -216,7 +217,7 @@ if (isNil QGVAR(level)) then {
}, 0, []] call CBA_fnc_addPerFrameHandler;
// broadcast injuries to JIP clients in a MP session
if (isMultiplayer && !isDedicated) then {
if (isMultiplayer) then {
[QGVAR(onPlayerConnected), "onPlayerConnected", {
if (isNil QGVAR(InjuredCollection)) then {
GVAR(InjuredCollection) = [];
@ -231,3 +232,13 @@ if (isMultiplayer && !isDedicated) then {
}foreach GVAR(InjuredCollection);
}, []] call BIS_fnc_addStackedEventHandler;
};
[
{(((_this select 0) getvariable [QGVAR(bloodVolume), 0]) < 65)},
{(((_this select 0) getvariable [QGVAR(pain), 0]) > 0.9)},
{(((_this select 0) call FUNC(getBloodLoss)) > 0.25)},
{((_this select 0) getvariable [QGVAR(inReviveState), false])},
{((_this select 0) getvariable ["ACE_isDead", false])},
{(((_this select 0) getvariable [QGVAR(airwayStatus), 100]) < 80)}
] call FUNC(addUnconsciousCondition);

View File

@ -24,6 +24,7 @@ PREP(getBloodPressure);
PREP(getBloodVolumeChange);
PREP(getCardiacOutput);
PREP(getTypeOfDamage);
PREP(getTriageStatus);
PREP(getUnconsciousCondition);
PREP(handleDamage);
PREP(handleDamage_advanced);
@ -35,6 +36,8 @@ PREP(handleDamage_fractures);
PREP(handleDamage_internalInjuries);
PREP(handleDamage_wounds);
PREP(handleUnitVitals);
PREP(handleKilled);
PREP(handleLocal);
PREP(hasItem);
PREP(hasItems);
PREP(hasMedicalEnabled);
@ -76,6 +79,11 @@ PREP(treatmentTourniquetLocal);
PREP(useItem);
PREP(useItems);
PREP(displayPatientInformation);
PREP(moduleMedicalSettings);
PREP(moduleAssignMedicRoles);
PREP(moduleAssignMedicalVehicle);
PREP(moduleAssignMedicalFacility);
PREP(moduleTreatmentConfiguration);
GVAR(injuredUnitCollection) = [];
call FUNC(parseConfigForInjuries);

View File

@ -2,8 +2,8 @@
class CfgPatches {
class ADDON {
units[] = {};
weapons[] = {};
units[] = {QGVAR(fieldDressingItem), QGVAR(packingBandageItem), QGVAR(elasticBandageItem), QGVAR(tourniquetItem), QGVAR(morphineItem), QGVAR(atropineItem), QGVAR(epinephrineItem), QGVAR(plasmaIVItem), QGVAR(bloodIVItem), QGVAR(salineIVItem), QGVAR(quikclotItem), QGVAR(personalAidKitItem), QGVAR(surgicalKitItem), QGVAR(bodyBagItem)};
weapons[] = {QGVAR(fieldDressing), QGVAR(packingBandage), QGVAR(elasticBandage), QGVAR(tourniquet), QGVAR(morphine), QGVAR(atropine), QGVAR(epinephrine), QGVAR(plasmaIV), QGVAR(plasmaIV_500), QGVAR(plasmaIV_250), QGVAR(bloodIV), QGVAR(bloodIV_500), QGVAR(bloodIV_250), QGVAR(salineIV), QGVAR(salineIV_500), QGVAR(salineIV_250), QGVAR(quikclot), QGVAR(personalAidKit), QGVAR(surgicalKit), QGVAR(bodyBag)};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {ace_common, ace_interaction};
author[] = {"Glowbal", "KoffienFlummi"};
@ -13,8 +13,10 @@ class CfgPatches {
};
#include "CfgEventHandlers.hpp"
#include "CfgFactionClasses.hpp"
#include "CfgVehicles.hpp"
#include "CfgWeapons.hpp"
#include "CFgSounds.hpp"
#include "ACE_Medical_Treatments.hpp"
#include "ACE_Settings.hpp"
#include "UI\RscTitles.hpp"

View File

@ -28,32 +28,32 @@ _bloodPressureLow = _bloodPressure select 0;
_output = "";
_logOutPut = "";
if ([_caller] call FUNC(isMedic)) then {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_1";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_1";
_logOutPut = format["%1/%2",round(_bloodPressureHigh),round(_bloodPressureLow)];
} else {
if (_bloodPressureHigh > 20) then {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_2";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_2";
_logOutPut = "Low";
if (_bloodPressureHigh > 100) then {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_3";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_3";
_logOutPut = "Normal";
if (_bloodPressureHigh > 160) then {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_4";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_4";
_logOutPut = "High";
};
};
} else {
if (random(10) > 3) then {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_5";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_5";
_logOutPut = "No Blood Pressure";
} else {
_output = "STR_ACE_CHECK_BLOODPRESSURE_OUTPUT_6";
_output = "STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_6";
};
};
};
["displayTextStructured", [_caller], [[_output, [_target] call EFUNC(common,getName), round(_bloodPressureHigh),round(_bloodPressureLow)], 1.5, _caller]] call EFUNC(common,targetEvent);
["displayTextStructured", [_caller], [[_output, [_target] call EFUNC(common,getName), round(_bloodPressureHigh),round(_bloodPressureLow)], 1.75, _caller]] call EFUNC(common,targetEvent);
if (_logOutPut != "") then {
[_target,"examine", format["%1 checked Blood Pressure: %2", [_caller] call EFUNC(common,getName), _logOutPut]] call FUNC(addToLog);

View File

@ -23,31 +23,30 @@ _heartRate = _unit getvariable [QGVAR(heartRate), 80];
if (!alive _unit) then {
_heartRate = 0;
};
_heartRateOutput = "STR_ACE_CHECK_PULSE_OUTPUT_5";
_heartRateOutput = "STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_5";
_logOutPut = "No heart rate";
if (_heartRate > 1.0) then {
if ([_caller] call FUNC(isMedic)) then {
_heartRateOutput = "STR_ACE_CHECK_PULSE_OUTPUT_1";
_heartRateOutput = "STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_1";
_logOutPut = format["%1",round(_heartRate)];
} else {
// non medical personel will only find a pulse/HR
_heartRateOutput = "STR_ACE_CHECK_PULSE_OUTPUT_2";
_heartRateOutput = "STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_2";
_logOutPut = "Weak";
if (_heartRate > 60) then {
if (_heartRate > 100) then {
_heartRateOutput = "STR_ACE_CHECK_PULSE_OUTPUT_3";
_heartRateOutput = "STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_3";
_logOutPut = "Strong";
} else {
_heartRateOutput = "STR_ACE_CHECK_PULSE_OUTPUT_4";
_heartRateOutput = "STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_4";
_logOutPut = "Normal";
};
};
};
};
_content = ["STR_ACE_CHECK_PULSE_CHECKED_MEDIC",_heartRateOutput];
["displayTextStructured", [_caller], [[_content, [_unit] call EFUNC(common,getName), round(_heartRate)], 1.5, _caller]] call EFUNC(common,targetEvent);
["displayTextStructured", [_caller], [[_heartRateOutput, [_unit] call EFUNC(common,getName), round(_heartRate)], 1.5, _caller]] call EFUNC(common,targetEvent);
if (_logOutPut != "") then {
[_unit,"examine",format["%1 checked Heart Rate: %2",[_caller] call EFUNC(common,getName),_logOutPut]] call FUNC(addToLog);

View File

@ -20,11 +20,11 @@ _target = _this select 1;
_output = "";
if ([_target] call EFUNC(common,isAwake)) then {
_output = ["STR_ACE_CHECK_REPONSE_RESPONSIVE",[_target] call EFUNC(common,getName)];
_output = ["STR_ACE_MEDICAL_CHECK_REPONSE_RESPONSIVE",[_target] call EFUNC(common,getName)];
} else {
_output = ["STR_ACE_CHECK_REPONSE_UNRESPONSIVE",[_target] call EFUNC(common,getName)];
_output = ["STR_ACE_MEDICAL_CHECK_REPONSE_UNRESPONSIVE",[_target] call EFUNC(common,getName)];
};
["displayTextStructured", [_caller], [_output, 1.5, _caller]] call EFUNC(common,targetEvent);
["displayTextStructured", [_caller], [_output, 2, _caller]] call EFUNC(common,targetEvent);
[_target,"examine",_output] call FUNC(addToLog);

View File

@ -21,7 +21,7 @@ _caller = _this select 0;
_target = _this select 1;
if ([_target] call EFUNC(common,isAwake)) exitwith {
// TODO localization
// TODO localization
["displayTextStructured", [_caller], [["This person (%1) is awake and cannot be loaded", [_target] call EFUNC(common,getName)], 1.5, _caller]] call EFUNC(common,targetEvent);
};

View File

@ -36,6 +36,6 @@ _tourniquets set[_part, 0];
_target setvariable [QGVAR(tourniquets), _tourniquets, true];
// Adding the tourniquet item to the caller
_caller addItem "ACE_tourniquet";
_caller addItem QGVAR(tourniquet);
// "AinvPknlMstpSlayWrflDnon_medic

View File

@ -15,36 +15,45 @@
private "_unit";
_unit = _this select 0;
if !(local _unit) exitwith{
[[_unit], QUOTE(DFUNC(addToInjuredCollection)), _unit] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
};
_force = if (count _this > 1) then {_this select 1} else {false};
if !(_unit getvariable[QGVAR(addedToUnitLoop),false]) then{
_unit setvariable [QGVAR(addedToUnitLoop),true, true];
};
if ([_unit] call FUNC(hasMedicalEnabled)) then {
[{
private "_unit";
_unit = (_this select 0) select 0;
if (!alive _unit || !local _unit) then {
[_this select 1] call CBA_fnc_removePerFrameHandler;
} else {
[_unit] call FUNC(handleUnitVitals);
private "_pain";
_pain = _unit getvariable [QGVAR(pain), 0];
if (_pain > 45) then {
if (random(1) > 0.6) then {
[_unit] call FUNC(setUnconscious);
};
[_unit] call FUNC(playInjuredSound);
};
};
}, 1, [_unit]] call CBA_fnc_addPerFrameHandler;
if ([_unit] call FUNC(hasMedicalEnabled) || _force) then {
if ((_unit getvariable[QGVAR(addedToUnitLoop),false] || !alive _unit) && !_force) exitwith{};
if !(local _unit) exitwith {
[[_unit, _force], QUOTE(DFUNC(addToInjuredCollection)), _unit] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
};
_unit setvariable [QGVAR(addedToUnitLoop), true, true];
if (isNil QGVAR(InjuredCollection)) then {
GVAR(InjuredCollection) = [];
};
GVAR(InjuredCollection) pushback _unit;
[{
private "_unit";
_unit = (_this select 0) select 0;
if (!alive _unit || !local _unit) then {
[_this select 1] call CBA_fnc_removePerFrameHandler;
if (!local _unit) then {
if (GVAR(level) >= 2) then {
_unit setvariable [QGVAR(heartRate), _unit getvariable [QGVAR(heartRate), 0], true];
_unit setvariable [QGVAR(bloodPressure), _unit getvariable [QGVAR(bloodPressure), [0, 0]], true];
};
_unit setvariable [QGVAR(bloodVolume), _unit getvariable [QGVAR(bloodVolume), 0], true];
};
GVAR(InjuredCollection) = GVAR(InjuredCollection) - [_unit];
} else {
[_unit] call FUNC(handleUnitVitals);
private "_pain";
_pain = _unit getvariable [QGVAR(pain), 0];
if (_pain > 0) then {
if (_pain > 0.7 && {random(1) > 0.6}) then {
[_unit] call FUNC(setUnconscious);
};
[_unit, _pain] call FUNC(playInjuredSound);
};
};
}, 1, [_unit]] call CBA_fnc_addPerFrameHandler;
};

View File

@ -16,29 +16,48 @@
#include "script_component.hpp"
private ["_caller", "_target", "_selectionName", "_className", "_config", "_availableLevels", "_medicRequired", "_items", "_locations", "_return"];
private ["_caller", "_target", "_selectionName", "_className", "_config", "_availableLevels", "_medicRequired", "_items", "_locations", "_return", "_condition"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
_className = _this select 3;
_config = (ConfigFile >> "ACE_Medical_Treatments" >> "Basic" >> _className);
if (GVAR(level)>=1) then {
_config = (ConfigFile >> "ACE_Medical_Treatments" >> "Advanced" >> _className);
if !(_target isKindOf "CAManBase") exitWith {false};
_config = (ConfigFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level)>=2) then {
_config = (ConfigFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};
if !(isClass _config) exitwith {false};
_medicRequired = getNumber (_config >> "requiredMedic");
if !([_caller, _medicRequired] call FUNC(isMedic) || [_target, _medicRequired] call FUNC(isMedic)) exitwith {false};
if !([_caller, _medicRequired] call FUNC(isMedic)) exitwith {false};
_items = getArray (_config >> "items");
if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exitwith {false};
_locations = getArray (_config >> "treatmentLocations");
_return = true;
if (isText (_config >> "Condition")) then {
_condition = getText(_config >> "condition");
if (_condition != "") then {
if (isnil _condition) then {
_condition = compile _condition;
} else {
_condition = missionNamespace getvariable _condition;
};
if (typeName _condition == "BOOL") then {
_return = _condition;
} else {
_return = [_caller, _target, _selectionName, _className] call _condition;
};
};
};
if (!_return) exitwith {false};
if ("All" in _locations) exitwith {true};
_return = false;
{
if (_x == "field") exitwith {_return = true;};
if (_x == "MedicalFacility" && {[_caller, _target] call FUNC(inMedicalFacility)}) exitwith {_return = true;};

View File

@ -17,58 +17,136 @@
private ["_target", "_show"];
_target = _this select 0;
_show = if (count _this > 1) then {_this select 1} else {true};
GVAR(currentSelectedSelectionN) = if (count _this > 2) then {_this select 2} else {0};
GVAR(displayPatientInformationTarget) = if (_show) then {_target} else {ObjNull};
if (_show) then {
("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutRsc [QGVAR(DisplayInformation),"PLAIN"];
("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"];
_target = (_this select 0) select 0;
if (GVAR(displayPatientInformationTarget) != _target) exitwith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
};
[{
private ["_target", "_display", "_alphaLevel", "_damaged", "_availableSelections", "_openWounds", "_selectionBloodLoss", "_red", "_green", "_blue", "_alphaLevel"];
_target = (_this select 0) select 0;
if (GVAR(displayPatientInformationTarget) != _target) exitwith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
};
disableSerialization;
_display = uiNamespace getvariable QGVAR(DisplayInformation);
if (isnil "_display") exitwith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
};
disableSerialization;
_display = uiNamespace getvariable QGVAR(DisplayInformation);
if (isnil "_display") exitwith {
[_this select 1] call CBA_fnc_removePerFrameHandler;
};
_allInjuryTexts = [];
_genericMessages = [];
if (_target getvariable[QGVAR(isBleeding), false]) then {
_genericMessages pushback [localize "STR_ACE_MEDICAL_STATUS_BLEEDING", [1, 0.1, 0.1, 1]];
};
if (_target getvariable[QGVAR(hasLostBlood), false]) then {
_genericMessages pushback [localize "STR_ACE_MEDICAL_STATUS_LOST_BLOOD", [1, 0.1, 0.1, 1]];
};
_alphaLevel = 1.0;
_damaged = [false, false, false, false, false, false];
_availableSelections = [50,51,52,53,54,55];
_openWounds = _target getvariable [QGVAR(openWounds), []];
if (((_target getvariable [QGVAR(tourniquets), [0,0,0,0,0,0]]) select GVAR(currentSelectedSelectionN)) > 0) then {
_genericMessages pushback [localize "STR_ACE_MEDICAL_STATUS_TOURNIQUET_APPLIED", [0.5, 0.5, 0, 1]];
};
if (_target getvariable[QGVAR(inPain), false]) then {
_genericMessages pushback [localize "STR_ACE_MEDICAL_STATUS_PAIN", [1, 1, 1, 1]];
};
_selectionBloodLoss = [0,0,0,0,0,0];
{
_selectionBloodLoss set [(_x select 2), (_selectionBloodLoss select (_x select 2)) + ((_x select 4) * (_x select 3))];
}foreach _openWounds;
_selectionBloodLoss = [0,0,0,0,0,0];
if (GVAR(level) >= 2) then {
_openWounds = _target getvariable [QGVAR(openWounds), []];
private "_amountOf";
{
_amountOf = _x select 3;
// Find how much this bodypart is bleeding
_selectionBloodLoss set [(_x select 2), (_selectionBloodLoss select (_x select 2)) + (15 * ((_x select 4) * _amountOf))];
if (GVAR(currentSelectedSelectionN) == (_x select 2)) 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["%2x %1", (GVAR(AllWoundInjuryTypes) select (_x select 1)) select 6, _amountOf];
} else {
// TODO localization
_allInjuryTexts pushback format["Partial %1", (GVAR(AllWoundInjuryTypes) select (_x select 1)) select 6];
};
};
};
}foreach _openWounds;
} else {
// TODO handle basic medical colors for body part selections here
{
private ["_red", "_green", "_blue"];
_total = _x;
_red = 1;
_green = 1;
_blue = 1;
if (_total >0) then {
_green = 0.9 - (15*(_total));
if (_green < 0.0) then {
_green = 0.0;
};
_blue = _green;
_damaged set[_foreachIndex, true];
};
(_display displayCtrl (_availableSelections select _foreachIndex)) ctrlSetTextColor [_red, _green, _blue, _alphaLevel];
}foreach _selectionBloodLoss;
};
// TODO fill the lb with the appropiate information for the patient
// Handle the body image coloring
_damaged = [false, false, false, false, false, false];
_availableSelections = [50,51,52,53,54,55];
{
private ["_red", "_green", "_blue"];
_total = _x;
}, 0, [_target]] call CBA_fnc_addPerFrameHandler;
_red = 1;
_green = 1;
_blue = 1;
if (_total >0) then {
_green = 0.9 - _total;
if (_green < 0.0) then {
_green = 0.0;
};
_blue = _green;
_damaged set[_foreachIndex, true];
};
(_display displayCtrl (_availableSelections select _foreachIndex)) ctrlSetTextColor [_red, _green, _blue, 1.0];
}foreach _selectionBloodLoss;
// TODO fill the lb with the appropiate information for the patient
_lbCtrl = (_display displayCtrl 200);
lbClear _lbCtrl;
{
_lbCtrl lbAdd (_x select 0);
_lbCtrl lbSetColor [_foreachIndex, _x select 1];
}foreach _genericMessages;
{
_lbCtrl lbAdd _x;
}foreach _allInjuryTexts;
if (count _genericMessages == 0 && {count _allInjuryTexts == 0}) then {
_lbCtrl lbAdd "No injuries on this bodypart..";
};
_logCtrl = (_display displayCtrl 302);
lbClear _logCtrl;
private ["_logs", "_log", "_message", "_moment", "_arguments", "_lbCtrl"];
_logs = _target getvariable [QGVAR(allLogs), []];
{
_log = _target getvariable [_x, []];
{
// [_message,_moment,_type, _arguments]
_message = _x select 0;
_moment = _x select 1;
_arguments = _x select 3;
if (isLocalized _message) then {
_message = localize _message;
};
{
if (typeName _x == "STRING" && {isLocalized _x}) then {
_arguments set [_foreachIndex, localize _x];
};
}foreach _arguments;
_message = format([_message] + _arguments);
_logCtrl lbAdd format["%1 %2", _moment, _message];
}foreach _log;
}foreach _logs;
_triageStatus = [_target] call FUNC(getTriageStatus);
(_display displayCtrl 303) ctrlSetText (_triageStatus select 0);
(_display displayCtrl 303) ctrlSetBackgroundColor (_triageStatus select 2);
}, 0, [_target]] call CBA_fnc_addPerFrameHandler;
} else {
("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutRsc ["","PLAIN"];
("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutText ["","PLAIN"];
};

View File

@ -18,13 +18,13 @@ private ["_totalBloodLoss","_tourniquets","_openWounds", "_value", "_cardiacOutp
_totalBloodLoss = 0;
// Advanced medical bloodloss handling
if (GVAR(level) >= 1) then {
if (GVAR(level) >= 2) then {
_tourniquets = _this getvariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
_openWounds = _this getvariable [QGVAR(openWounds), []];
//_cardiacOutput = [_this] call FUNC(getCardiacOutput);
{
if ((_tourniquets select (_x select 2)) < 1) then {
if ((_tourniquets select (_x select 2)) == 0) then {
// total bleeding ratio * percentage of injury left
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
@ -42,4 +42,4 @@ if (GVAR(level) >= 1) then {
} else {
// TODO basic medical
};
_totalBloodLoss;
_totalBloodLoss * GVAR(bleedingCoefficient);

View File

@ -0,0 +1,26 @@
/*
* Author: Glowbal
* Get the triage status and information from a unit
*
* Arguments:
* 0: The unit <OBJECT>
*
* Return Value:
* Triage status from the unit. Name, statusID, color <ARRAY <STRING><NUMBER><ARRAY>>
*
* Public: Yes
*/
#include "script_component.hpp"
private ["_unit","_return","_status"];
_unit = _this select 0;
_status = _unit getvariable [QGVAR(triageLevel), -1];
_return = switch (_status) do {
case 1: {[localize "STR_ACE_MEDICAL_TRIAGE_STATUS_MINOR", 1, [0, 0.5, 0, 0.9]]};
case 2: {[localize "STR_ACE_MEDICAL_TRIAGE_STATUS_DELAYED", 2, [0.7, 0.5, 0, 0.9]]};
case 3: {[localize "STR_ACE_MEDICAL_TRIAGE_STATUS_IMMEDIATE", 3, [0.4, 0.07, 0.07, 0.9]]};
case 4: {[localize "STR_ACE_MEDICAL_TRIAGE_STATUS_DECEASED", 4, [0, 0, 0, 0.9]]};
default {[localize "STR_ACE_MEDICAL_TRIAGE_STATUS_NONE", 0, [0, 0, 0, 0.9]]};
};
_return;

View File

@ -16,7 +16,7 @@
private ["_unit","_return"];
_unit = _this select 0;
if (GVAR(level) == 0) exitwith {true};
if (GVAR(level) == 1) exitwith {true};
if (isnil QGVAR(unconsciousConditions)) then {
GVAR(unconsciousConditions) = [];
};

View File

@ -38,11 +38,11 @@ _hitSelections = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"];
if !(_selection in (_hitSelections + [""])) exitWith {0};
_damageReturn = _damage;
if (GVAR(level) == 0) then {
if (GVAR(level) == 1) then {
_damageReturn = (_this + [_damageReturn]) call FUNC(handleDamage_basic);
};
if (GVAR(level) >= 1) then {
if (GVAR(level) >= 2) then {
[_unit, _selection, _damage, _source, _projectile, _damageReturn] call FUNC(handleDamage_caching);
if (_damageReturn > 0.9) then {
@ -60,6 +60,7 @@ if (GVAR(level) >= 1) then {
};
};
};
[_unit] call FUNC(addToInjuredCollection);
if (_unit getVariable [QGVAR(preventDeath), false] && {_damageReturn >= 0.9} && {_selection in ["", "head", "body"]}) exitWith {
if (vehicle _unit != _unit and {damage _vehicle >= 1}) then {

View File

@ -27,6 +27,11 @@ _sourceOfDamage = _this select 3;
_typeOfProjectile = _this select 4;
_returnDamage = _this select 5;
// Most likely taking exessive fire damage. Lets exit.
if (isNull _sourceOfDamage && (_selectionName == "head" || isBurning _unit) && _typeOfProjectile == "" && vehicle _unit == _unit) exitwith {
0
};
_typeOfDamage = [_typeOfProjectile] call FUNC(getTypeOfDamage);
_part = [_selectionName] call FUNC(selectionNameToNumber);
@ -52,6 +57,11 @@ if (GVAR(enableInternalBleeding)) then {
if (alive _unit && {!(_unit getvariable ["ACE_isUnconscious", false])}) then {
[_unit, _newDamage] call FUNC(reactionToDamage);
// If it reaches this, we can assume that the hit did not kill this unit, as this function is called 3 frames after the damage has been passed.
if ([_unit, _part, if (_part > 1) then {_newDamage * 1.3} else {_newDamage * 2}] call FUNC(determineIfFatal)) then {
[_unit] call FUNC(setUnconscious);
};
};
_returnDamage;

View File

@ -25,10 +25,9 @@ _sourceOfDamage = _this select 3;
_typeOfDamage = _this select 4;
_bodyPartn = [_selectionName] call FUNC(selectionNameToNumber);
// We process only the head for airway.
if (_bodyPartn != 0) exitwith {};
if (_bodyPartn > 1) exitwith {};
if (_amountOfDamage > 0.4) then {
if (_amountOfDamage > 0.5) then {
if (random(1) >= 0.8) then {
if !(_unit getvariable[QGVAR(airwayCollapsed), false]) then {
_unit setvariable [QGVAR(airwayCollapsed), true, true];

View File

@ -35,14 +35,24 @@ if (_selectionName in _hitSelections) then {
_newDamage = _damage - (_unit getHitPointDamage (_hitPoints select (_hitSelections find _selectionName)));
};
// we want to move damage to another selection; have to do it ourselves.
// this is only the case for limbs, so this will not impact the killed EH.
if (_selectionName != (_this select 1)) then {
_unit setHitPointDamage [_hitPoints select (_hitSelections find _selectionName), _damage + _newDamage];
_newDamage = 0;
};
// ??????
_damage = _damage + _newDamage;
// Check for vehicle crash
if (vehicle _unit != _unit && !(vehicle _unit isKindOf "StaticWeapon") && {isNull _source} && {_projectile == ""} && {_selectionName == ""}) then {
if (missionNamespace getvariable [QGVAR(allowVehicleCrashDamage), true]) then {
_selectionName = _hitSelections select (floor(random(count _hitSelections)));
_projectile = "vehiclecrash";
};
};
// From AGM medical:
// Exclude falling damage to everything other than legs; reduce structural damage.
if (((velocity _unit) select 2 < -5) && (vehicle _unit == _unit)) then {

View File

@ -36,13 +36,15 @@ _allInjuriesForDamageType = _injuryTypeInfo select 2;
// find the available injuries for this damage type and damage amount
_highestPossibleSpot = -1;
_highestPossibleDamage = 0;
_highestPossibleDamage = -1;
_allPossibleInjuries = [];
{
_minDamage = _x select 4;
_damageLevels = _x select 4;
_minDamage = _damageLevels select 0;
_maxDamage = _damageLevels select 1;
// Check if the damage is higher as the min damage for the specific injury
if (_damage >= _minDamage) then {
if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then {
_classType = _x select 0;
_selections = _x select 1;
_bloodLoss = _x select 2;
@ -71,7 +73,7 @@ if (_highestPossibleSpot < 0) exitwith {
};
};
// admin for open wounds and ids
// Administration for open wounds and ids
_openWounds = _unit getvariable[QGVAR(openWounds), []];
_woundID = _unit getvariable[QGVAR(lastUniqueWoundID), 1];
@ -81,16 +83,39 @@ _woundsCreated = [];
if (_x select 0 <= _damage) exitwith {
for "_i" from 0 to (1+ floor(random(_x select 1)-1)) /* step +1 */ do {
// Find the injury we are going to add. Format [ classType, allowdSelections, bloodloss, painOfInjury, minimalDamage]
_toAddInjury = _allPossibleInjuries select (floor(random (count _allPossibleInjuries)));
// Find the injury we are going to add. Format [ classID, allowdSelections, bloodloss, painOfInjury, minimalDamage]
_toAddInjury = if (random(1) >= 0.5) then {_allInjuriesForDamageType select _highestPossibleSpot} else {_allPossibleInjuries select (floor(random (count _allPossibleInjuries)));};
_toAddClassID = _toAddInjury select 0;
_foundIndex = -1;
// Create a new injury. Format [ID, classname, bodypart, percentage treated, bloodloss rate]
_injury = [_woundID, _toAddInjury select 0, if (_injuryTypeInfo select 1) then {_bodyPartn} else {floor(random(6))}, 1, _toAddInjury select 2];
_bodyPartNToAdd = if (_injuryTypeInfo select 1) then {_bodyPartn} else {floor(random(6))};
// If the injury type is selection part specific, we will check if one of those injury types already exists and find the spot for it..
if ((_injuryTypeInfo select 1)) then {
{
// Check if we have an id of the given class on the given bodypart already
if (_x select 1 == _toAddClassID && {_x select 2 == _bodyPartNToAdd}) exitwith {
_foundIndex = _foreachIndex;
};
}foreach _openWounds;
};
_injury = [];
if (_foundIndex < 0) then {
// Create a new injury. Format [ID, classID, bodypart, percentage treated, bloodloss rate]
_injury = [_woundID, _toAddInjury select 0, _bodyPartNToAdd, 1, _toAddInjury select 2];
// Since it is a new injury, we will have to add it to the open wounds array to store it
_openWounds pushback _injury;
// New injuries will also increase the wound ID
_woundID = _woundID + 1;
} else {
// We already have one of these, so we are just going to increase the number that we have of it with a new one.
_injury = _openWounds select _foundIndex;
_injury set [3, (_injury select 3) + 1];
};
// Store the injury so we can process it later correctly.
_openWounds pushback _injury;
_woundsCreated pushback _injury;
_woundID = _woundID + 1;
// Collect the pain that is caused by this injury
_painToAdd = _painToAdd + (_toAddInjury select 3);
@ -99,8 +124,13 @@ _woundsCreated = [];
}foreach (_injuryTypeInfo select 0);
_unit setvariable [QGVAR(openWounds), _openWounds];
_unit setvariable [QGVAR(lastUniqueWoundID), _woundID, true];
// Only update if new wounds have been created
if (count _woundsCreated > 0) then {
_unit setvariable [QGVAR(lastUniqueWoundID), _woundID, true];
};
// TODO Should this be done in a single broadcast?
// Broadcast the new injuries across the net in parts. One broadcast per injury. Prevents having to broadcast one massive array of injuries.
{
["medical_propagateWound", [_unit, _x]] call EFUNC(common,globalEvent);

View File

@ -0,0 +1,25 @@
/*
* Author: Glowbal
* Called when a unit is killed
*
* Arguments:
* 0: The Unit <OBJECT>
*
* ReturnValue:
* None
*
* Public: No
*/
#include "script_component.hpp"
private["_unit"];
_unit = _this select 0;
if (!local _unit) exitwith {};
_unit setvariable [QGVAR(pain), 0];
if (GVAR(level) >= 2) then {
_unit setvariable [QGVAR(heartRate), 0];
_unit setvariable [QGVAR(bloodPressure), [0, 0]];
_unit setvariable [QGVAR(airwayStatus), 0];
};

View File

@ -0,0 +1,25 @@
/*
* Author: Glowbal
* Called when a unit switched locality
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Is local <BOOL>
*
* ReturnValue:
* None
*
* Public: No
*/
#include "script_component.hpp"
private["_unit", "_local"];
_unit = _this select 0;
_local = _this select 1;
if (_local) then {
if (_unit getvariable[QGVAR(addedToUnitLoop),false]) then {
[_unit, true] call FUNC(addToInjuredCollection);
};
};

View File

@ -13,14 +13,20 @@
#include "script_component.hpp"
private ["_unit", "_heartRate","_bloodPressure","_bloodVolume","_painStatus"];
private ["_unit", "_heartRate","_bloodPressure","_bloodVolume","_painStatus", "_lastTimeValuesSynced", "_syncValues"];
_unit = _this select 0;
_lastTimeValuesSynced = _unit getvariable [QGVAR(lastMomentValuesSynced), 0];
_syncValues = time - _lastTimeValuesSynced >= (10 + floor(random(10)));
if (_syncValues) then {
_unit setvariable [QGVAR(lastMomentValuesSynced), time];
};
_bloodVolume = (_unit getvariable [QGVAR(bloodVolume), 0]) + ([_unit] call FUNC(getBloodVolumeChange));
if (_bloodVolume <= 0) then {
_bloodVolume = 0;
};
_unit setvariable [QGVAR(bloodVolume), _bloodVolume];
_unit setvariable [QGVAR(bloodVolume), _bloodVolume, _syncValues];
// Set variables for synchronizing information across the net
if (_bloodVolume < 90) then {
@ -68,29 +74,35 @@ if ([_unit] call EFUNC(common,isAwake)) then {
};
// handle advanced medical, with vitals
if ((missionNamespace getvariable[QGVAR(level), 0]) > 0) exitwith {
if (GVAR(level) >= 2) then {
// Set the vitals
_heartRate = (_unit getvariable [QGVAR(heartRate), 0]) + ([_unit] call FUNC(getHeartRateChange));
_unit setvariable [QGVAR(heartRate), _heartRate];
_unit setvariable [QGVAR(heartRate), _heartRate, _syncValues];
_bloodPressure = [_unit] call FUNC(getBloodPressure);
_unit setvariable [QGVAR(bloodPressure), _bloodPressure];
_unit setvariable [QGVAR(bloodPressure), _bloodPressure, _syncValues];
// Handle airway
if (GVAR(setting_allowAirwayInjuries)) then {
_airwayStatus = _unit getvariable [QGVAR(airwayStatus), 100];
if (((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) && !((_unit getvariable [QGVAR(airwaySecured), false]))) then {
if (_airwayStatus >= 0.5) then {
_unit setvariable [QGVAR(airwayStatus), _airwayStatus - 0.5];
_unit setvariable [QGVAR(airwayStatus), _airwayStatus - 0.5, _syncValues];
};
} else {
if !((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) then {
if (_airwayStatus <= 98.5) then {
_unit setvariable [QGVAR(airwayStatus), _airwayStatus + 1.5];
if (_airwayStatus < 100) then {
_unit setvariable [QGVAR(airwayStatus), (_airwayStatus + 1.5) min 100, _syncValues];
};
};
};
if (_airwayStatus < 80) then {
[_unit] call FUNC(setUnconscious);
if (_airwayStatus <= 0) then {
[_unit, true] call FUNC(setDead);
};
};
};
// Check vitals for medical status

View File

@ -15,7 +15,7 @@ _unit = _this select 0;
_medicalEnabled = _unit getvariable QGVAR(enableMedical);
if (isnil "_medicalEnabled") exitwith {
(((GVAR(setting_enableForUnits) == 0 && (isPlayer _unit || (_unit getvariable [QEGVAR(common,isDeadPlayer), false])))) || (GVAR(setting_enableForUnits) == 1));
(((GVAR(enabledFor) == 0 && (isPlayer _unit || (_unit getvariable [QEGVAR(common,isDeadPlayer), false])))) || (GVAR(enabledFor) == 1));
};
_medicalEnabled;

View File

@ -52,13 +52,13 @@ _unit setvariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true];
// airway
_unit setvariable [QGVAR(airwayStatus), 0, true];
_unit setVariable [QGVAR(airwayOccluded), false, true];
_unit setvariable [QGVAR(airwayCollapsed), true, true];
_unit setvariable [QGVAR(airwayCollapsed), false, true];
// generic medical admin
_unit setvariable [QGVAR(addedToUnitLoop), false, true];
_unit setvariable [QGVAR(inCardiacArrest), true, true];
_unit setvariable [QGVAR(inCardiacArrest), false, true];
_unit setVariable [QGVAR(isUnconscious), false, true];
_unit setvariable [QGVAR(hasLostBlood), true, true];
_unit setvariable [QGVAR(hasLostBlood), false, true];
_unit setvariable [QGVAR(isBleeding), false, true];
_unit setvariable [QGVAR(hasPain), false, true];

View File

@ -18,14 +18,15 @@ private ["_unit","_class","_return"];
_unit = _this select 0;
_medicN = if (count _this > 1) then {_this select 1} else {1};
if (isnil QGVAR(setting_advancedMedicRoles)) exitwith {
true;
};
if (GVAR(setting_advancedMedicRoles)) then {
_return = false;
if (GVAR(medicSetting) >= 1) then {
_class = _unit getvariable [QGVAR(medicClass), 0];
if (_class >= _medicN) then {
_return = true;
if (GVAR(medicSetting) == 1) then {
_return = _class > 0;
} else {
if (_class >= _medicN) then {
_return = true;
};
};
} else {
_return = true;

View File

@ -0,0 +1,63 @@
/*
* Author: Glowbal
* Assign a medical role to a unit
*
* Arguments:
* 0: The module logic <LOGIC>
* 1: units <ARRAY>
* 2: activated <BOOL>
*
* Return Value:
* None <NIL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_logic","_setting","_objects", "_list", "_splittedList", "_nilCheckPassedList", "_parsedList"];
_logic = [_this,0,objNull,[objNull]] call BIS_fnc_param;
if (!isNull _logic) then {
_list = _logic getvariable ["EnableList",""];
_splittedList = [_list, ","] call BIS_fnc_splitString;
_nilCheckPassedList = "";
{
_x = [_x] call EFUNC(common,stringRemoveWhiteSpace);
if !(isnil _x) then {
if (_nilCheckPassedList == "") then {
_nilCheckPassedList = _x;
} else {
_nilCheckPassedList = _nilCheckPassedList + ","+ _x;
};
};
}foreach _splittedList;
_list = "[" + _nilCheckPassedList + "]";
_parsedList = [] call compile _list;
_setting = _logic getvariable ["role",0];
_objects = synchronizedObjects _logic;
if (!(_objects isEqualTo []) && _parsedList isEqualTo []) then {
{
if (!isnil "_x") then {
if (typeName _x == typeName objNull) then {
if (local _x) then {
_x setvariable [QGVAR(medicClass), _setting, true];
};
};
};
}foreach _objects;
};
{
if (!isnil "_x") then {
if (typeName _x == typeName objNull) then {
if (local _x) then {
_x setvariable [QGVAR(medicClass), _setting, true];
};
};
};
}foreach _parsedList;
};
true

View File

@ -0,0 +1,30 @@
/*
* Author: Glowbal
* Register synchronized objects from passed object as a medical facility
*
* Arguments:
* 0: The module logic <LOGIC>
* 1: units <ARRAY>
* 2: activated <BOOL>
*
* Return Value:
* None <NIL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_logic","_setting","_objects"];
_logic = [_this,0,objNull,[objNull]] call BIS_fnc_param;
if (!isNull _logic) then {
_setting = _logic getvariable ["class",0];
_objects = synchronizedObjects _logic;
{
if (local _x) then {
_x setvariable[QGVAR(isMedicalFacility), true, true];
};
}foreach _objects;
};
true;

View File

@ -0,0 +1,64 @@
/*
* Author: Glowbal
* Assign vehicle as a medical vehicle
*
* Arguments:
* 0: The module logic <LOGIC>
* 1: units <ARRAY>
* 2: activated <BOOL>
*
* Return Value:
* None <NIL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_logic","_setting","_objects", "_list", "_splittedList", "_nilCheckPassedList", "_parsedList"];
_logic = [_this,0,objNull,[objNull]] call BIS_fnc_param;
if (!isNull _logic) then {
_list = _logic getvariable ["EnableList",""];
_splittedList = [_list, ","] call BIS_fnc_splitString;
_nilCheckPassedList = "";
{
_x = [_x] call EFUNC(common,stringRemoveWhiteSpace);
if !(isnil _x) then {
if (_nilCheckPassedList == "") then {
_nilCheckPassedList = _x;
} else {
_nilCheckPassedList = _nilCheckPassedList + ","+ _x;
};
};
}foreach _splittedList;
_list = "[" + _nilCheckPassedList + "]";
_parsedList = [] call compile _list;
_setting = _logic getvariable ["enabled", false];
_objects = synchronizedObjects _logic;
if (!(_objects isEqualTo []) && _parsedList isEqualTo []) then {
{
if (!isnil "_x") then {
if (typeName _x == typeName objNull) then {
if (local _x) then {
_x setvariable [QGVAR(isMedicalVehicle), _setting, true];
};
};
};
}foreach _objects;
};
{
if (!isnil "_x") then {
if (typeName _x == typeName objNull) then {
if (local _x) then {
_x setvariable [QGVAR(isMedicalVehicle), _setting, true];
};
};
};
}foreach _parsedList;
};
true;

View File

@ -0,0 +1,34 @@
/*
* Author: Glowbal
* Module for adjusting the medical damage settings
*
* Arguments:
* 0: The module logic <LOGIC>
* 1: units <ARRAY>
* 2: activated <BOOL>
*
* Return Value:
* None <NIL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_logic", "_units", "_activated"];
_logic = _this select 0;
_units = _this select 1;
_activated = _this select 2;
if !(_activated) exitWith {};
[_logic, QGVAR(level), "level"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableFor), "enableFor"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableAirway), "enableAirway"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableFractures), "enableFractures"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableAdvancedWounds), "enableAdvancedWounds"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableScreams), "enableScreams"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(playerDamageThreshold), "playerDamageThreshold"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(AIDamageThreshold), "AIDamageThreshold"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableUnsconsiousnessAI), "enableUnsconsiousnessAI"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(preventInstaDeath), "preventInstaDeath"] call EFUNC(common,readSettingFromModule);

View File

@ -0,0 +1,30 @@
/*
* Author: Glowbal
* Module for adjusting the medical treatment settings
*
* Arguments:
* 0: The module logic <LOGIC>
* 1: units <ARRAY>
* 2: activated <BOOL>
*
* Return Value:
* None <NIL>
*
* Public: No
*/
#include "script_component.hpp"
private ["_logic", "_units", "_activated"];
_logic = _this select 0;
_units = _this select 1;
_activated = _this select 2;
if !(_activated) exitWith {};
[_logic, QGVAR(medicSetting), "medicSetting"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(maxRevives), "maxRevives"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(enableOverdosing), "enableOverdosing"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(bleedingCoefficient), "bleedingCoefficient"] call EFUNC(common,readSettingFromModule);

View File

@ -19,19 +19,19 @@ _unit = _this select 0;
_injury = _this select 1;
if (!local _unit) then {
_openWounds = _unit getvariable[QGVAR(openWounds), []];
_injuryID = _injury select 0;
_openWounds = _unit getvariable[QGVAR(openWounds), []];
_injuryID = _injury select 0;
_exists = false;
{
if (_x select 0 == _injuryID) exitwith {
_exists = true;
_openWounds set [_foreachIndex, _injury];
};
}foreach _openWounds;
_exists = false;
{
if (_x select 0 == _injuryID) exitwith {
_exists = true;
_openWounds set [_foreachIndex, _injury];
};
}foreach _openWounds;
if (!_exists) then {
_openWounds pushback _injury;
};
_unit setvariable [GVAR(openWounds), _openWounds];
if (!_exists) then {
_openWounds pushback _injury;
};
_unit setvariable [GVAR(openWounds), _openWounds];
};

View File

@ -21,7 +21,7 @@ _originOfrequest = _this select 2;
_openWounds = _unit getvariable [QGVAR(openWounds), []];
if (count _openWounds > _lastId) then {
{
["medical_propagateWound", [_originOfrequest], [_unit, _x]] call EFUNC(common,targetEvent);
}foreach _openWounds;
{
["medical_propagateWound", [_originOfrequest], [_unit, _x]] call EFUNC(common,targetEvent);
}foreach _openWounds;
};

View File

@ -12,20 +12,27 @@
#include "script_component.hpp"
private ["_injuriesRootConfig", "_woundsConfig", "_allWoundClasses", "_amountOf", "_entry","_classType", "_selections", "_bloodLoss", "_pain","_minDamage","_causes", "_allTypes", "_damageTypesConfig", "_thresholds", "_typeThresholds", "_selectionSpecific", "_selectionSpecificType", "_classDisplayName", "_subClassDisplayName"];
private ["_injuriesRootConfig", "_woundsConfig", "_allWoundClasses", "_amountOf", "_entry","_classType", "_selections", "_bloodLoss", "_pain","_minDamage","_causes", "_allTypes", "_damageTypesConfig", "_thresholds", "_typeThresholds", "_selectionSpecific", "_selectionSpecificType", "_classDisplayName", "_subClassDisplayName", "_maxDamage", "_subClassmaxDamage"];
_injuriesRootConfig = (configFile >> "ACE_Medical_Advanced" >> "Injuries");
_allTypes = ["stab", "grenade", "bullet", "explosive", "shell", "punch", "vehiclecrash", "backblast", "falling", "bite", "ropeburn"];
// Collect all available damage types from the config
_allFoundDamageTypes = [];
_configDamageTypes = (_injuriesRootConfig >> "damageTypes");
for "_i" from 0 to (count _configDamageTypes -1) /* step +1 */ do {
// Only get the subclasses in damageType class
if (isClass(_configDamageTypes select _i)) then {
_allFoundDamageTypes pushback (configName (_configDamageTypes select _i));
};
};
GVAR(allAvailableDamageTypes) = _allFoundDamageTypes;
GVAR(woundClassNames) = [];
GVAR(fractureClassNames) = [];
// Parsing the wounds
// function for parsing a sublcass of an injury
_parseForSubClassWounds = {
_subClass = _this select 0;
if (isClass (_entry >> _subClass)) exitwith {
@ -35,10 +42,13 @@ _parseForSubClassWounds = {
_subClassbloodLoss = if (isNumber(_subClassConfig >> "bleedingRate")) then { getNumber(_subClassConfig >> "bleedingRate");} else { _bloodLoss };
_subClasspain = if (isNumber(_subClassConfig >> "pain")) then { getNumber(_subClassConfig >> "pain");} else { _pain };
_subClassminDamage = if (isNumber(_subClassConfig >> "minDamage")) then { getNumber(_subClassConfig >> "minDamage");} else { _minDamage };
_subClassmaxDamage = if (isNumber(_subClassConfig >> "maxDamage")) then { getNumber(_subClassConfig >> "maxDamage");} else { _maxDamage };
_subClasscauses = if (isArray(_subClassConfig >> "causes")) then { getArray(_subClassConfig >> "causes");} else { _causes };
_subClassDisplayName = if (isText(_entry >> "name")) then { getText(_entry >> "name");} else {_classDisplayName + " " + _subClass};
if (count _selections > 0 && count _causes > 0) then {
_allWoundClasses pushback [_subClasstype, _subClassselections, _subClassbloodLoss, _subClasspain, _subClassminDamage, _subClasscauses, _subClassDisplayName];
_subClassDisplayName = if (isText(_subClassConfig >> "name")) then { getText(_subClassConfig >> "name");} else {_classDisplayName + " " + _subClass};
if (count _selections > 0 && {count _causes > 0}) then {
GVAR(woundClassNames) pushback _subClasstype;
_allWoundClasses pushback [_classID, _subClassselections, _subClassbloodLoss, _subClasspain, [_subClassminDamage, _subClassmaxDamage], _subClasscauses, _subClassDisplayName];
_classID = _classID + 1;
};
true;
};
@ -48,6 +58,7 @@ _parseForSubClassWounds = {
// TODO classTypes are strings currently. Convert them to unqiue IDs instead.
_woundsConfig = (_injuriesRootConfig >> "wounds");
_allWoundClasses = [];
_classID = 0;
if (isClass _woundsConfig) then {
_amountOf = count _woundsConfig;
for "_i" from 0 to (_amountOf -1) /* step +1 */ do {
@ -58,13 +69,18 @@ if (isClass _woundsConfig) then {
_bloodLoss = if (isNumber(_entry >> "bleedingRate")) then { getNumber(_entry >> "bleedingRate");} else {0};
_pain = if (isNumber(_entry >> "pain")) then { getNumber(_entry >> "pain");} else {0};
_minDamage = if (isNumber(_entry >> "minDamage")) then { getNumber(_entry >> "minDamage");} else {0};
_maxDamage = if (isNumber(_entry >> "maxDamage")) then { getNumber(_entry >> "maxDamage");} else {-1};
_causes = if (isArray(_entry >> "causes")) then { getArray(_entry >> "causes");} else {[]};
_classDisplayName = if (isText(_entry >> "name")) then { getText(_entry >> "name");} else {_classType};
// TODO instead of hardcoding minor, medium and large just go through all sub classes recursively until none are found
if (["Minor"] call _parseForSubClassWounds || ["Medium"] call _parseForSubClassWounds || ["Large"] call _parseForSubClassWounds) exitwith {}; // continue to the next one
// There were no subclasses, so we will add this one instead.
if (count _selections > 0 && count _causes > 0) then {
_allWoundClasses pushback [_classType, _selections, _bloodLoss, _pain, _minDamage, _causes, _classDisplayName];
GVAR(woundClassNames) pushback _classType;
_allWoundClasses pushback [_classID, _selections, _bloodLoss, _pain, [_minDamage, _maxDamage], _causes, _classDisplayName];
_classID = _classID + 1;
};
true;
};
@ -72,10 +88,10 @@ if (isClass _woundsConfig) then {
};
GVAR(AllWoundInjuryTypes) = _allWoundClasses;
// Linking injuries to the woundInjuryType variables.
_damageTypesConfig = (configFile >> "ACE_Medical_Advanced" >> "Injuries" >> "damageTypes");
_thresholds = getArray(_damageTypesConfig >> "thresholds");
_selectionSpecific = getNumber(_damageTypesConfig >> "selectionSpecific");
{
_varName = format[QGVAR(woundInjuryType_%1),_x];
_woundTypes = [];
@ -93,4 +109,4 @@ _selectionSpecific = getNumber(_damageTypesConfig >> "selectionSpecific");
if (isNumber(_damageTypesConfig >> _x >> "selectionSpecific")) then { _selectionSpecificType = getNumber(_damageTypesConfig >> _x >> "selectionSpecific");};
};
missionNamespace setvariable [_varName, [_typeThresholds, _selectionSpecificType > 0, _woundTypes]];
}foreach _allTypes;
}foreach _allFoundDamageTypes;

View File

@ -17,55 +17,47 @@
private ["_unit","_amountOfDamage","_bodyPartStatus","_availableSounds_A","_availableSounds_B","_availableSounds_C","_sound"];
_unit = _this select 0;
if (!local _unit) exitwith{};
_pain = _this select 1;
if (!local _unit || !GVAR(enableScreams)) exitwith{};
// Lock if the unit is already playing a sound.
if ((_unit getvariable [QGVAR(playingInjuredSound),false])) exitwith {};
_unit setvariable [QGVAR(playingInjuredSound),true];
// Classnames of the available sounds.
_availableSounds_A = [
"WoundedGuyA_01",
"WoundedGuyA_02",
"WoundedGuyA_03",
"WoundedGuyA_04",
"WoundedGuyA_05",
"WoundedGuyA_06",
"WoundedGuyA_07",
"WoundedGuyA_08"
];
_availableSounds_B = [
"WoundedGuyB_01",
"WoundedGuyB_02",
"WoundedGuyB_03",
"WoundedGuyB_04",
"WoundedGuyB_05",
"WoundedGuyB_06",
"WoundedGuyB_07",
"WoundedGuyB_08"
];
_availableSounds_C = [
"WoundedGuyC_01",
"WoundedGuyC_02",
"WoundedGuyC_03",
"WoundedGuyC_04",
"WoundedGuyC_05"
];
// TODO Base this off hitpoint damage
// Find the amount of damage for this unit, based upon body part status.
//_bodyPartStatus = [_unit,QGVAR(bodyPartStatus)] call EFUNC(common,getDefinedVariable);
_amountOfDamage = 0;
/*{
_amountOfDamage = _amountOfDamage + _x;
}foreach _bodyPartStatus;*/
// Play the sound if there is any damage present.
if (_amountOfDamage > 0) exitwith {
if (_pain > 0 && {[_unit] call EFUNC(common,isAwake)}) exitwith {
// Classnames of the available sounds.
_availableSounds_A = [
"WoundedGuyA_01",
"WoundedGuyA_02",
"WoundedGuyA_03",
"WoundedGuyA_04",
"WoundedGuyA_05",
"WoundedGuyA_06",
"WoundedGuyA_07",
"WoundedGuyA_08"
];
_availableSounds_B = [
"WoundedGuyB_01",
"WoundedGuyB_02",
"WoundedGuyB_03",
"WoundedGuyB_04",
"WoundedGuyB_05",
"WoundedGuyB_06",
"WoundedGuyB_07",
"WoundedGuyB_08"
];
_availableSounds_C = [
"WoundedGuyC_01",
"WoundedGuyC_02",
"WoundedGuyC_03",
"WoundedGuyC_04",
"WoundedGuyC_05"
];
_sound = "";
// Select the to be played sound based upon damage amount.
if (_amountOfDamage > 1) then {
if (_pain > 0.5) then {
if (random(1) > 0.5) then {
_sound = _availableSounds_A select (round(random((count _availableSounds_A) - 1)));
} else {
@ -74,18 +66,12 @@ if (_amountOfDamage > 0) exitwith {
} else {
_sound = _availableSounds_B select (round(random((count _availableSounds_B) - 1)));
};
// Play the sound
playSound3D [((getArray(configFile >> "CfgSounds" >> _sound >> "sound") select 0)), _unit, false, getPos _unit, 2, 1, 15]; // +2db, 15 meters.
playSound3D [(getArray(configFile >> "CfgSounds" >> _sound >> "sound") select 0) + ".wss", objNull, false, getPos _unit, 15, 1, 25]; // +2db, 15 meters.
// Figure out what the delay will be before it is possible to play a sound again.
private "_delay";
_delay = 1;
if (_amountOfDamage < 1) then {
_delay = 10 + random(50);
} else {
_delay = (60 / _amountOfDamage);
};
_delay = (30 - (random(25) * _pain)) max (3.5 + random(2));
// Clean up the lock
[{

View File

@ -25,8 +25,27 @@ if (!local _unit) exitwith {
[[_unit, _force], QUOTE(DFUNC(setDead)), _unit, false] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
};
if (missionNamespace getVariable [QGVAR(enableRevive), false]) exitwith {
// TODO Implement the revive state
if (GVAR(preventInstaDeath) && !_force) exitwith {
if (_unit getvariable [QGVAR(inReviveState), false]) exitwith {}; // already in revive state
_unit setvariable [QGVAR(inReviveState), true, true];
[_unit] call FUNC(setUnconscious);
[{
private ["_args","_unit","_startTime"];
_args = _this select 0;
_unit = _args select 0;
_startTime = _args select 1;
if (time - _startTime > GVAR(maxReviveTime)) exitwith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
[_unit, true] call FUNC(setDead);
_unit setvariable [QGVAR(inReviveState), nil, true];
};
if !(_unit getvariable [QGVAR(inReviveState), false]) exitwith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
}, 1, [_unit, time] ] call CBA_fnc_addPerFrameHandler;
};
_unit setvariable ["ACE_isDead", true, true];

View File

@ -115,7 +115,7 @@ _minWaitingTime = (round(random(10)+5));
_unit setUnitPos _originalPos; // This is not position but stance (DOWN, MIDDLE, UP)
_unit setUnconscious false;
["medical_onUnconscious", [_unit], [_unit, false]] call EFUNC(common,targetEvent);
// ensure this statement runs only once
_args set [6, true];
};
@ -139,3 +139,4 @@ _minWaitingTime = (round(random(10)+5));
}, 0.1, [_unit,_animState, _captiveSwitch, _originalPos, _startingTime, _minWaitingTime, false] ] call CBA_fnc_addPerFrameHandler;
["medical_onUnconscious", [_unit], [_unit, true]] call EFUNC(common,targetEvent);

View File

@ -16,7 +16,7 @@
#include "script_component.hpp"
private ["_caller", "_target", "_selectionName", "_className", "_config", "_availableLevels", "_medicRequired", "_items", "_locations", "_return", "_callbackSuccess", "_callbackFailure", "_callbackProgress", "_treatmentTime", "_callerAnim", "_patientAnim", "_iconDisplayed"];
private ["_caller", "_target", "_selectionName", "_className", "_config", "_availableLevels", "_medicRequired", "_items", "_locations", "_return", "_callbackSuccess", "_callbackFailure", "_callbackProgress", "_treatmentTime", "_callerAnim", "_patientAnim", "_iconDisplayed", "_return"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
@ -25,14 +25,14 @@ _className = _this select 3;
if !(_target isKindOf "CAManBase") exitWith {false};
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
if (GVAR(level) >= 2) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};
if !(isClass _config) exitwith {false};
// Check for required class
_medicRequired = getNumber (_config >> "requiredMedic");
if !([_caller, _medicRequired] call FUNC(isMedic) || [_target, _medicRequired] call FUNC(isMedic)) exitwith {false};
if !([_caller, _medicRequired] call FUNC(isMedic)) exitwith {false};
// Check item
_items = getArray (_config >> "items");
@ -40,7 +40,25 @@ if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exi
// Check allowed locations
_locations = getArray (_config >> "treatmentLocations");
_return = false;
_return = true;
if (isText (_config >> "Condition")) then {
_condition = getText(_config >> "condition");
if (_condition != "") then {
if (isnil _condition) then {
_condition = compile _condition;
} else {
_condition = missionNamespace getvariable _condition;
};
if (typeName _condition == "BOOL") then {
_return = _condition;
} else {
_return = [_caller, _target, _selectionName, _className] call _condition;
};
};
};
if (!_return) exitwith {false};
if ("All" in _locations) then {
_return = true;
} else {
@ -50,8 +68,10 @@ if ("All" in _locations) then {
if (_x == "MedicalVehicle" && {([vehicle _caller] call FUNC(isMedicalVehicle)) || ([vehicle _target] call FUNC(isMedicalVehicle))}) exitwith {_return = true;};
}foreach _locations;
};
if !(_return) exitwith {false};
// Parse the config for the progress callback
_callbackProgress = getText (_config >> "callbackProgress");
if (_callbackProgress == "") then {

View File

@ -23,16 +23,17 @@ _target = _this select 1;
_selectionName = _this select 2;
_className = _this select 3;
_items = _this select 4;
_specificSpot = if (count _this > 5) then {_this select 5} else {-1};
if (count _items == 0) exitwith {};
if ([_caller, _target, _items] call FUNC(useItems)) then {
[[_target, _className], QUOTE(DFUNC(treatmentBandageLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
{
[[_target, _className, _selectionName, _specificSpot], QUOTE(DFUNC(treatmentAdvanced_bandageLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
/* {
if (_x != "") then {
[_target, _x] call FUNC(addToTriageCard);
};
}foreach _items;
}foreach _items;*/
["Medical_treatmentCompleted", [_caller, _target, _selectionName, _className, true]] call ace_common_fnc_localEvent;
[_target, "activity", "STR_ACE_HAS_BANDAGED_ACTIVITY", [[_caller] call EFUNC(common,getName)]] call FUNC(addToLog);

View File

@ -15,9 +15,11 @@
#include "script_component.hpp"
private ["_target", "_bandage", "_part", "_openWounds", "_config", "_effectiveness","_mostEffectiveInjury", "_mostEffectiveSpot", "_woundEffectivenss", "_mostEffectiveInjury", "_impact"];
private ["_target", "_bandage", "_part", "_selectionName", "_openWounds", "_config", "_effectiveness","_mostEffectiveInjury", "_mostEffectiveSpot", "_woundEffectivenss", "_mostEffectiveInjury", "_impact", "_exit"];
_target = _this select 0;
_bandage = _this select 1;
_selectionName = _this select 2;
_specificClass = if (count _this > 3) then {_this select 3} else { -1 };
// Ensure it is a valid bodypart
_part = [_selectionName] call FUNC(selectionNameToNumber);
@ -37,23 +39,33 @@ if (isClass (_config >> _bandage)) then {
// Figure out which injury for this bodypart is the best choice to bandage
_mostEffectiveSpot = 0;
_effectivenessFound = 0;
_effectivenessFound = -1;
_mostEffectiveInjury = _openWounds select 0;
_exit = false;
{
// Only parse injuries that are for the selected bodypart.
if (_x select 2 == _part) then {
_woundEffectivenss = _effectiveness;
_classID = (_x select 1);
// Select the classname from the wound classname storage
_className = GVAR(woundClassNames) select _classID;
// Check if this wound type has attributes specified for the used bandage
if (isClass (_config >> (_x select 1))) then {
if (isClass (_config >> _className)) then {
// Collect the effectiveness from the used bandage for this wound type
_woundTreatmentConfig = (_config >> (_x select 1));
_woundTreatmentConfig = (_config >> _className);
if (isNumber (_woundTreatmentConfig >> "effectiveness")) then {
_woundEffectivenss = getNumber (_woundTreatmentConfig >> "effectiveness");
};
};
if (_specificClass == _classID) exitwith {
_effectivenessFound = _woundEffectivenss;
_mostEffectiveSpot = _foreachIndex;
_mostEffectiveInjury = _x;
_exit = true;
};
// Check if this is the currently most effective found.
if (_woundEffectivenss * ((_x select 4) * (_x select 3)) > _effectivenessFound * ((_mostEffectiveInjury select 4) * (_mostEffectiveInjury select 3))) then {
_effectivenessFound = _woundEffectivenss;
@ -61,9 +73,11 @@ _mostEffectiveInjury = _openWounds select 0;
_mostEffectiveInjury = _x;
};
};
if (_exit) exitwith {};
}foreach _openWounds;
if (_effectivenessFound == 0) exitwith {}; // Seems everything is patched up on this body part already..
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

View File

@ -47,13 +47,13 @@ if (alive _unit) exitwith {
// airway
_unit setvariable [QGVAR(airwayStatus), 0, true];
_unit setVariable [QGVAR(airwayOccluded), false, true];
_unit setvariable [QGVAR(airwayCollapsed), true, true];
_unit setvariable [QGVAR(airwayCollapsed), false, true];
// generic medical admin
_unit setvariable [QGVAR(addedToUnitLoop), false, true];
_unit setvariable [QGVAR(inCardiacArrest), true, true];
_unit setvariable [QGVAR(inCardiacArrest), false, true];
_unit setVariable [QGVAR(isUnconscious), false, true];
_unit setvariable [QGVAR(hasLostBlood), true, true];
_unit setvariable [QGVAR(hasLostBlood), false, true];
_unit setvariable [QGVAR(isBleeding), false, true];
_unit setvariable [QGVAR(hasPain), false, true];

View File

@ -27,7 +27,7 @@ _items = _this select 4;
if (count _items == 0) exitwith {};
if ([_caller, _target, _items] call FUNC(useItems)) then {
[[_target, _className], QUOTE(DFUNC(treatmentMedicationLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
[[_target, _className], QUOTE(DFUNC(treatmentAdvanced_medicationLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
{
if (_x != "") then {
[_target, _x] call FUNC(addToTriageCard);

View File

@ -35,7 +35,7 @@ _caller setvariable [QGVAR(treatmentPrevAnimCaller), nil];
// Record specific callback
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
if (GVAR(level) >= 2) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};

View File

@ -35,7 +35,7 @@ _caller setvariable [QGVAR(treatmentPrevAnimCaller), nil];
// Record specific callback
_config = (configFile >> "ACE_Medical_Actions" >> "Basic" >> _className);
if (GVAR(level) >= 1) then {
if (GVAR(level) >= 2) then {
_config = (configFile >> "ACE_Medical_Actions" >> "Advanced" >> _className);
};

View File

@ -1,6 +1,79 @@
<?xml version="1.0"encoding="UTF-8"?>
<Project name="ACE">
<Package name="Medical">
<Container name="UI">
<Key ID="STR_ACE_MEDICAL_TRIAGE_STATUS_MINOR">
<Original>Minor</Original>
</Key>
<Key ID="STR_ACE_MEDICAL_TRIAGE_STATUS_DELAYED">
<Original>Delayed</Original>
</Key>
<Key ID="STR_ACE_MEDICAL_TRIAGE_STATUS_IMMEDIATE">
<Original>Immediate</Original>
</Key>
<Key ID="STR_ACE_MEDICAL_TRIAGE_STATUS_DECEASED">
<Original>Deceased</Original>
</Key>
<Key ID="STR_ACE_MEDICAL_TRIAGE_STATUS_NONE">
<Original>None</Original>
</Key>
<Key ID="STR_ACE_MEDICAL_NORMAL_BREATHING">
<Original>Normal breathing</Original>
<Russian>Дыхание в норме</Russian>
<Spanish>Respiración normal</Spanish>
<French>Respiration Normale</French>
<Polish>Normalny oddech</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_NO_BREATHING">
<Original>No breathing</Original>
<Russian>Дыхания нет</Russian>
<Spanish>No respira</Spanish>
<French>Apnée</French>
<Polish>Brak oddechu</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_DIFFICULT_BREATHING">
<Original>Difficult breathing</Original>
<Russian>Дыхание затруднено</Russian>
<Spanish>Dificultad para respirar</Spanish>
<French>Difficultée Respiratoire</French>
<Polish>Trudności z oddychaniem</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_ALMOST_NO_BREATHING">
<Original>Almost no breathing</Original>
<Russian>Дыхания почти нет</Russian>
<Spanish>Casi sin respirar</Spanish>
<French>Respiration Faible</French>
<Polish>Prawie brak oddechu</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_STATUS_BLEEDING">
<Original>Bleeding</Original>
<Russian>Кровотечение</Russian>
<Spanish>Sangrando</Spanish>
<French>Seignement</French>
<Polish>Krwawienie zewnętrzne</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_STATUS_PAIN">
<Original>In Pain</Original>
<Russian>Испытывает боль</Russian>
<Spanish>Con Dolor</Spanish>
<French>A De La Douleur</French>
<Polish>W bólu</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_STATUS_LOST_BLOOD">
<Original>Lost a lot of Blood</Original>
<Russian>Большая кровопотеря</Russian>
<Spanish>Mucha Sangre perdida</Spanish>
<French>A Perdu Bcp de Sang</French>
<Polish>Stracił dużo krwi</Polish>
</Key>
<Key ID="STR_ACE_MEDICAL_STATUS_TOURNIQUET_APPLIED">
<Original>Tourniquet [CAT]</Original>
<Russian>Жгут</Russian>
<Spanish>Torniquete [CAT]</Spanish>
<French>Garot [CAT]</French>
<Polish>Opaska uciskowa [CAT]</Polish>
</Key>
</Container>
<Container name="CfgWeapons">
<Key ID="STR_ACE_MEDICAL_BANDAGE_BASIC_DISPLAY">
<Original>Bandage (Basic)</Original>
@ -326,5 +399,164 @@
<Spanish>Bolsa para cadáveres</Spanish>
</Key>
</Container>
<Container name="Actions">
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE">
<Original>Blood Pressure</Original>
<Russian>Артериальное давление</Russian>
<Spanish>Presión Arterial</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_CONTENT">
<Original>Checking Blood Pressure..</Original>
<Russian>Проверка артериального давления...</Russian>
<Spanish>Comprobando Presión Arterial...</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_CHECKED_MEDIC">
<Original>You checked %1</Original>
<Russian>Вы осмотрели раненого %1</Russian>
<Spanish>Examinando a %1</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_1">
<Original>You find a blood pressure of %2/%3</Original>
<Russian>Артериальное давление %2/%3</Russian>
<Spanish>La Presión Arterial es %2/%3</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_2">
<Original>You find a low blood pressure</Original>
<Russian>Давление низкое</Russian>
<Spanish>La Presión Arterial es baja</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_3">
<Original>You find a normal blood pressure</Original>
<Russian>Давление нормальное</Russian>
<Spanish>La Presión Arterial es normal</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_4">
<Original>You find a high blood pressure</Original>
<Russian>Давление высокое</Russian>
<Spanish>La Presión Arterial es alta</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_5">
<Original>You find no blood pressure</Original>
<Russian>Давления нет</Russian>
<Spanish>No hay Presión Arterial</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_BLOODPRESSURE_OUTPUT_6">
<Original>You fail to find a blood pressure</Original>
<Russian>Артериальное давление не определяется</Russian>
<Spanish>No puedes encontrar Presión Arterial</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE">
<Original>Pulse</Original>
<Russian>Пульс</Russian>
<Spanish>Pulso</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_CONTENT">
<Original>Checking Heart Rate..</Original>
<Russian>Проверка пульса...</Russian>
<Spanish>Comprobando Pulso...</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_CHECKED_MEDIC">
<Original>You checked %1</Original>
<Russian>Вы осмотрели раненого %1</Russian>
<Spanish>Examinando a %1</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_1">
<Original>You find a Heart Rate of %2</Original>
<Russian>Пульс %2 уд./мин.</Russian>
<Spanish>El Pulso es %2</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_2">
<Original>You find a weak Heart Rate</Original>
<Russian>Пульс слабый</Russian>
<Spanish>El Pulso es débil</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_3">
<Original>You find a strong Heart Rate</Original>
<Russian>Пульс учащенный</Russian>
<Spanish>El Pulso está acelerado</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_4">
<Original>You find a normal Heart Rate</Original>
<Russian>Пульс в норме</Russian>
<Spanish>El Pulso es bueno</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_PULSE_OUTPUT_5">
<Original>You find no Heart Rate</Original>
<Russian>Пульс не прощупывается</Russian>
<Spanish>No tiene Pulso</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_RESPONSE">
<Original>Response</Original>
<Russian>Реакция</Russian>
<Spanish>Reacciona</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_RESPONSE_CONTENT">
<Original>You check response of patient</Original>
<Russian>Вы проверяете реакцию раненого</Russian>
<Spanish>Compruebas si el paciente reacciona</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_REPONSE_RESPONSIVE">
<Original>%1 is responsive</Original>
<Russian>%1 реагирует на раздражители</Russian>
<Spanish>%1 ha reaccionado</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_REPONSE_UNRESPONSIVE">
<Original>%1 is not responsive</Original>
<Russian>%1 не реагирует</Russian>
<Spanish>%1 no reacciona</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_CHECK_REPONSE_YOU_CHECKED">
<Original>You checked %1</Original>
<Russian>Вы осмотрели раненого %1</Russian>
<Spanish>Examinas a %1</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_BANDAGING">
<Original>Bandaging</Original>
<Russian>Перевязка...</Russian>
<Spanish>Vendando</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_BANDAGED">
<Original>Bandaged</Original>
<Russian>Повязка наложена</Russian>
<Spanish>Vendado</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_APPLY_BANDAGE">
<Original>You bandage %1 (%2)</Original>
<Russian>Вы перевязали раненого %1 (%2)</Russian>
<Spanish>Aplicas vendaje a %1 en %2</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_IS_BANDAGING_YOU">
<Original>%1 is bandaging you</Original>
<Russian>%1 перевязывает вас</Russian>
<Spanish>%1 te está vendando</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_START_STITCHING_INJURIES">
<Original>You start stitching injures from %1 (%2)</Original>
<Russian>Вы зашиваете ранения от %1 (%2)</Russian>
<Spanish>Estás suturando heridas de %1 en %2</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_STITCHING">
<Original>Stitching</Original>
<Russian>Наложение швов</Russian>
<Spanish>Suturando</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_YOU_TREAT_AIRWAY">
<Original>You treat the airway of %1</Original>
<Russian>Вы интубируете раненого %1</Russian>
<Spanish>Estás intubando a %1</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_AIRWAY">
<Original>Airway</Original>
<Russian>Дыхательные пути</Russian>
<Spanish>Vías Aéreas</Spanish>
</Key>
<Key ID="STR_ACE_MEDICAL_IS_TREATING_YOUR_AIRWAY">
<Original>%1 is treating your airway</Original>
<Russian>%1 проводит вам интубацию</Russian>
<Spanish>%1 te está intubando</Spanish>
</Key>
</Container>
</Package>
</Project>

View File

@ -11,7 +11,7 @@ class Rsctitles {
class controlsBackground {
class bodyImgBackground: ACE_gui_backgroundBase {
idc = -1;
x = "safezoneX + (2 * (((safezoneW / safezoneH) min 1.2) / 40))";
x = "safezoneX + (2.5 * (((safezoneW / safezoneH) min 1.2) / 40))";
y = "1.5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
w = "8.5 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "8.5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
@ -48,11 +48,25 @@ class Rsctitles {
idc = 55;
text = QUOTE(PATHTOF(ui\body_leg_right.paa));
};
class InjuryListLabel {
idc = 199;
type = CT_STATIC;
x = "safezoneX + (2 * (((safezoneW / safezoneH) min 1.2) / 40))";
y = "10.2 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
w = "9 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "0.7 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)";
style = 0x00 + 0x100; // ST_LEFT + ST_SHADOW
font = "PuristaMedium";
colorText[] = {0.95, 0.95, 0.95, 0.75};
colorBackground[] = {"(profilenamespace getvariable ['GUI_BCG_RGB_R',0.69])","(profilenamespace getvariable ['GUI_BCG_RGB_G',0.75])","(profilenamespace getvariable ['GUI_BCG_RGB_B',0.5])", "(profilenamespace getvariable ['GUI_BCG_RGB_A',0.9])"};
text = "INJURIES";
};
class InjuryList: ACE_gui_listBoxBase {
idc = 200;
x = "safezoneX + (2 * (((safezoneW / safezoneH) min 1.2) / 40))";
y = "11 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
w = "8.5 * (((safezoneW / safezoneH) min 1.2) / 40)";
w = "9 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "9 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)";
rowHeight = 0.03;
@ -64,6 +78,48 @@ class Rsctitles {
colorSelectBackground[] = {0, 0, 0, 0.0};
colorSelectBackground2[] = {0.0, 0.0, 0.0, 0.5};
};
class LogName {
idc = 301;
type = CT_STATIC;
x = "safezoneX + (2 * (((safezoneW / safezoneH) min 1.2) / 40))";
y = "20.5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
w = "9 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "0.7 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)";
style = 0x00 + 0x100; // ST_LEFT + ST_SHADOW
font = "PuristaMedium";
colorText[] = {0.95, 0.95, 0.95, 0.75};
colorBackground[] = {"(profilenamespace getvariable ['GUI_BCG_RGB_R',0.69])","(profilenamespace getvariable ['GUI_BCG_RGB_G',0.75])","(profilenamespace getvariable ['GUI_BCG_RGB_B',0.5])", "(profilenamespace getvariable ['GUI_BCG_RGB_A',0.9])"};
text = "ACTIVITY LOG";
};
class ActivityLog: InjuryList {
idc = 302;
y = "21.3 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
h = "7 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)";
rowHeight = 0.03;
colorBackground[] = {0, 0, 0, 0.2};
colorText[] = {1,1, 1, 1.0};
colorScrollbar[] = {0.95, 0.95, 0.95, 1};
colorSelect[] = {0.95, 0.95, 0.95, 1};
colorSelect2[] = {0.95, 0.95, 0.95, 1};
colorSelectBackground[] = {0, 0, 0, 0.0};
colorSelectBackground2[] = {0.0, 0.0, 0.0, 0.5};
};
class TriageStatus {
idc = 303;
type = CT_STATIC;
x = "safezoneX + (2 * (((safezoneW / safezoneH) min 1.2) / 40))";
y = "28.5 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + safezoneY";
w = "9 * (((safezoneW / safezoneH) min 1.2) / 40)";
h = "0.7 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
SizeEx = "(((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.7)";
style = 0x00 + 0x100; // ST_LEFT + ST_SHADOW
font = "PuristaMedium";
colorText[] = {0.95, 0.95, 0.95, 0.75};
colorBackground[] = {0,0,0,0.9};
text = "";
};
};
};
};

Binary file not shown.