mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical Rewrite - Continued (#4744)
This commit is contained in:
parent
9cba0baade
commit
a5ce5b4a34
@ -6,15 +6,15 @@ class ACE_Medical_StateMachine {
|
||||
onState = QUOTE(DFUNC(handleStateDefault));
|
||||
class Injury {
|
||||
targetState = "Injured";
|
||||
events[] = {QGVAR(TakenInjury)};
|
||||
events[] = {QGVAR(Injury)};
|
||||
};
|
||||
class CriticalInjuryOrVitals {
|
||||
targetState = "Unconscious";
|
||||
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)};
|
||||
events[] = {QGVAR(CriticalInjury), QGVAR(CriticalVitals)};
|
||||
};
|
||||
class FatalInjury {
|
||||
targetState = "FatalInjury";
|
||||
events[] = {QGVAR(InjuryFatal)};
|
||||
events[] = {QGVAR(FatalInjury)};
|
||||
};
|
||||
};
|
||||
class Injured {
|
||||
@ -23,13 +23,9 @@ class ACE_Medical_StateMachine {
|
||||
targetState = "Default";
|
||||
events[] = {QGVAR(FullHeal)};
|
||||
};
|
||||
class LastWoundTreated {
|
||||
targetState = "Default";
|
||||
events[] = {QGVAR(LastWoundTreated)};
|
||||
};
|
||||
class CriticalInjuryOrVitals {
|
||||
targetState = "Unconscious";
|
||||
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)};
|
||||
events[] = {QGVAR(CriticalInjury), QGVAR(CriticalVitals)};
|
||||
};
|
||||
class FatalVitals {
|
||||
targetState = "CardiacArrest";
|
||||
@ -37,30 +33,25 @@ class ACE_Medical_StateMachine {
|
||||
};
|
||||
class FatalInjury {
|
||||
targetState = "FatalInjury";
|
||||
events[] = {QGVAR(InjuryFatal)};
|
||||
events[] = {QGVAR(FatalInjury)};
|
||||
};
|
||||
};
|
||||
class Unconscious {
|
||||
onState = QUOTE(DFUNC(handleStateUnconscious));
|
||||
onStateEntered = QUOTE(DFUNC(enteredUnconsciousState));
|
||||
onStateLeaving = "_this setVariable ['ACE_isUnconscious', false, true];";
|
||||
class WakeUpFromKnockDown {
|
||||
onStateEntered = QUOTE([ARR_2(_this,(true))] call FUNC(setUnconscious));
|
||||
onStateLeaving = QUOTE([ARR_2(_this,(false))] call FUNC(setUnconscious));
|
||||
class WakeUp {
|
||||
targetState = "Injured";
|
||||
condition = QUOTE(_this call FUNC(hasStableVitals));
|
||||
events[] = {QGVAR(MinUnconsciousTimer)};
|
||||
};
|
||||
class WakeUpStable {
|
||||
targetState = "Injured";
|
||||
condition = "unitUnconsciousTimer >= MinUnconsciousTimer";
|
||||
events[] = {QGVAR(VitalsWentStable)};
|
||||
events[] = {QGVAR(WakeUp)};
|
||||
};
|
||||
class FatalTransitions {
|
||||
targetState = "CardiacArrest";
|
||||
events[] = {QGVAR(FatalVitals), QGVAR(UnconsciousTimerRanOut)};
|
||||
events[] = {QGVAR(FatalVitals)};
|
||||
};
|
||||
class FatalInjury {
|
||||
targetState = "FatalInjury";
|
||||
events[] = {QGVAR(InjuryFatal)};
|
||||
events[] = {QGVAR(FatalInjury)};
|
||||
};
|
||||
};
|
||||
class FatalInjury {
|
||||
@ -81,19 +72,19 @@ class ACE_Medical_StateMachine {
|
||||
};
|
||||
class CardiacArrest {
|
||||
onStateEntered = QUOTE(DFUNC(enteredStateCardiacArrest));
|
||||
onStateLeaving = '_this setVariable [QGVAR(cardiacArrestStart), nil]';
|
||||
class TimerRanOut {
|
||||
onStateLeaving = QUOTE(DFUNC(leftStateCardiacArrest));
|
||||
class Timeout {
|
||||
targetState = "Dead";
|
||||
condition = QUOTE(DFUNC(conditionCardiacArrestTimer));
|
||||
};
|
||||
class Reanimated {
|
||||
class Reanimation {
|
||||
targetState = "Unconscious";
|
||||
events[] = {QGVAR(CPRSucceeded)};
|
||||
};
|
||||
class Execution {
|
||||
targetState = "Dead";
|
||||
condition = QUOTE(DFUNC(conditionExecutionDeath));
|
||||
events[] = {QGVAR(InjuryFatal)};
|
||||
events[] = {QGVAR(FatalInjury)};
|
||||
};
|
||||
};
|
||||
class Dead {
|
||||
|
@ -1,17 +1,9 @@
|
||||
class ACE_Settings {
|
||||
class GVAR(level) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_level_DisplayName);
|
||||
description = CSTRING(MedicalSettings_level_Description);
|
||||
value = 1;
|
||||
typeName = "SCALAR";
|
||||
values[] = {"Disabled", "Basic", "Advanced"};
|
||||
};
|
||||
class GVAR(medicSetting) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_medicSetting_DisplayName);
|
||||
description = CSTRING(MedicalSettings_medicSetting_Description);
|
||||
value = 1;
|
||||
value = 0;
|
||||
typeName = "SCALAR";
|
||||
values[] = {"Disabled", "Normal", "Advanced"};
|
||||
};
|
||||
@ -26,15 +18,10 @@ class ACE_Settings {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_enableFor_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_enableFor_Description);
|
||||
value = 0;
|
||||
value = 1;
|
||||
typeName = "SCALAR";
|
||||
values[] = {"Players only", "Players and AI"};
|
||||
};
|
||||
class GVAR(enableOverdosing) {
|
||||
category = CSTRING(Category_Medical);
|
||||
typeName = "BOOL";
|
||||
value = 1;
|
||||
};
|
||||
class GVAR(bleedingCoefficient) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_bleedingCoefficient_DisplayName);
|
||||
@ -49,22 +36,12 @@ class ACE_Settings {
|
||||
typeName = "SCALAR";
|
||||
value = 1;
|
||||
};
|
||||
class GVAR(enableAirway) {
|
||||
category = CSTRING(Category_Medical);
|
||||
typeName = "BOOL";
|
||||
value = false;
|
||||
};
|
||||
class GVAR(enableFractures) {
|
||||
category = CSTRING(Category_Medical);
|
||||
typeName = "BOOL";
|
||||
value = false;
|
||||
};
|
||||
class GVAR(enableAdvancedWounds) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_Description);
|
||||
typeName = "BOOL";
|
||||
value = false;
|
||||
value = 1;
|
||||
};
|
||||
class GVAR(enableVehicleCrashes) {
|
||||
category = CSTRING(Category_Medical);
|
||||
@ -80,6 +57,8 @@ class ACE_Settings {
|
||||
typeName = "BOOL";
|
||||
value = 1;
|
||||
};
|
||||
|
||||
// Use those for handleIncapacitation?
|
||||
class GVAR(playerDamageThreshold) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_playerDamageThreshold_DisplayName);
|
||||
@ -94,11 +73,13 @@ class ACE_Settings {
|
||||
typeName = "SCALAR";
|
||||
value = 1;
|
||||
};
|
||||
|
||||
|
||||
class GVAR(enableUnconsciousnessAI) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_enableUnconsciousnessAI_DisplayName);
|
||||
description = CSTRING(MedicalSettings_enableUnconsciousnessAI_Description);
|
||||
value = 1;
|
||||
value = 2;
|
||||
typeName = "SCALAR";
|
||||
values[] = {"Disabled", "50/50", "Enabled"};
|
||||
};
|
||||
@ -148,7 +129,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_DisplayName);
|
||||
description = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 1;
|
||||
value = 0;
|
||||
values[] = {"Anyone", "Medics only", "Doctors only"};
|
||||
};
|
||||
class GVAR(medicSetting_PAK) {
|
||||
@ -156,7 +137,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 1;
|
||||
value = 0;
|
||||
values[] = {"Anyone", "Medics only", "Doctors only"};
|
||||
};
|
||||
class GVAR(medicSetting_SurgicalKit) {
|
||||
@ -164,7 +145,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 1;
|
||||
value = 0;
|
||||
values[] = {"Anyone", "Medics only", "Doctors only"};
|
||||
};
|
||||
class GVAR(consumeItem_PAK) {
|
||||
@ -172,7 +153,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 0;
|
||||
value = 1;
|
||||
values[] = {"No", "Yes"};
|
||||
};
|
||||
class GVAR(consumeItem_SurgicalKit) {
|
||||
@ -180,7 +161,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 0;
|
||||
value = 1;
|
||||
values[] = {"No", "Yes"};
|
||||
};
|
||||
class GVAR(useLocation_basicEpi) {
|
||||
@ -196,7 +177,7 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_useLocation_PAK_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_useLocation_PAK_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 3;
|
||||
value = 0;
|
||||
values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)};
|
||||
};
|
||||
class GVAR(useLocation_SurgicalKit) {
|
||||
@ -204,38 +185,23 @@ class ACE_Settings {
|
||||
displayName = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 2;
|
||||
value = 0;
|
||||
values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)};
|
||||
};
|
||||
class GVAR(useCondition_PAK) {
|
||||
class GVAR(fullHealLocation_PAK) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_useCondition_PAK_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_useCondition_PAK_Description);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_fullHealLocation_PAK_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_fullHealLocation_PAK_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 0;
|
||||
values[] = {"Anytime", "Stable"};
|
||||
value = 3;
|
||||
values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)};
|
||||
};
|
||||
class GVAR(useCondition_SurgicalKit) {
|
||||
class GVAR(fieldEffectiveness_PAK) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_Description);
|
||||
displayName = CSTRING(MedicalSettings_fieldEffectiveness_PAK_DisplayName);
|
||||
description = CSTRING(MedicalSettings_fieldEffectiveness_PAK_Description);
|
||||
typeName = "SCALAR";
|
||||
value = 0;
|
||||
values[] = {"Anytime", "Stable"};
|
||||
};
|
||||
class GVAR(keepLocalSettingsSynced) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(MedicalSettings_keepLocalSettingsSynced_DisplayName);
|
||||
description = CSTRING(MedicalSettings_keepLocalSettingsSynced_Description);
|
||||
typeName = "BOOL";
|
||||
value = 1;
|
||||
};
|
||||
class GVAR(healHitPointAfterAdvBandage) {
|
||||
category = CSTRING(Category_Medical);
|
||||
displayName = CSTRING(AdvancedMedicalSettings_healHitPointAfterAdvBandage_DisplayName);
|
||||
description = CSTRING(AdvancedMedicalSettings_healHitPointAfterAdvBandage_Description);
|
||||
typeName = "BOOL";
|
||||
value = 0;
|
||||
value = 0.9;
|
||||
};
|
||||
class GVAR(painIsOnlySuppressed) {
|
||||
category = CSTRING(Category_Medical);
|
||||
|
@ -1,35 +1,41 @@
|
||||
|
||||
PREP(addDamageToUnit);
|
||||
PREP(addStateHandler);
|
||||
PREP(adjustPainLevel);
|
||||
PREP(conditionCardiacArrestTimer);
|
||||
PREP(conditionExecutionDeath);
|
||||
PREP(enteredStateCardiacArrest);
|
||||
PREP(enteredStateFatalInjury);
|
||||
PREP(getBloodLoss);
|
||||
PREP(getBloodPressure);
|
||||
PREP(getBloodVolumeChange);
|
||||
PREP(getCardiacOutput);
|
||||
PREP(getHeartRateChange);
|
||||
PREP(handleIncapacitation);
|
||||
PREP(handleKilled);
|
||||
PREP(handleLocal);
|
||||
PREP(handleMedications);
|
||||
PREP(handleStateDefault);
|
||||
PREP(handleStateInjured);
|
||||
PREP(handleStateUnconscious);
|
||||
PREP(handleUnitVitals);
|
||||
PREP(hasStableVitals);
|
||||
PREP(hasTourniquetAppliedTo);
|
||||
PREP(init);
|
||||
PREP(install);
|
||||
PREP(isBeingCarried);
|
||||
PREP(isBeingDragged);
|
||||
PREP(isInMedicalFacility);
|
||||
PREP(isInMedicalVehicle);
|
||||
PREP(isInStableCondition);
|
||||
PREP(isMedic);
|
||||
PREP(isMedicalVehicle);
|
||||
|
||||
// PREP(hasMedicalEnabled);
|
||||
|
||||
PREP(enteredStateCardiacArrest);
|
||||
PREP(leavingStateCardiacArrest);
|
||||
|
||||
PREP(enteredStateFatalInjury);
|
||||
|
||||
PREP(conditionExecutionDeath);
|
||||
PREP(transitionSecondChance);
|
||||
|
||||
PREP(handleStateDefault);
|
||||
PREP(handleStateInjured);
|
||||
PREP(handleStateUnconscious);
|
||||
PREP(handleUnitVitals);
|
||||
PREP(handleMedications);
|
||||
|
||||
PREP(addPain);
|
||||
PREP(setUnconscious);
|
||||
PREP(leftStateCardiacArrest);
|
||||
PREP(moduleAssignMedicRoles);
|
||||
PREP(moduleAssignMedicalVehicle);
|
||||
PREP(serverRemoveBody);
|
||||
PREP(setCardiacArrest);
|
||||
PREP(setDead);
|
||||
|
||||
PREP(hasTourniquetAppliedTo);
|
||||
PREP(setUnconscious);
|
||||
PREP(showBloodEffect);
|
||||
PREP(transitionSecondChance);
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Author: commy2
|
||||
* Adds or removes pain to/from unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Pain to add. Negative to remove <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Nothing
|
||||
*
|
||||
* Example:
|
||||
* [player, 0.5] call ace_medical_fnc_addPain
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_painToAdd"];
|
||||
|
||||
private _pain = _unit getVariable [QEGVAR(medical,pain), 0];
|
||||
|
||||
if (_pain > 0) then {
|
||||
_pain = _pain + (_painToAdd min 1) * (1 - _pain);
|
||||
} else {
|
||||
_pain = (_pain + _painToAdd) max 0;
|
||||
};
|
||||
|
||||
_unit setVariable [QEGVAR(medical,pain), _pain];
|
||||
|
||||
if (_painToAdd > 0 && {_pain >= PAIN_UNCONSCIOUS}) then {
|
||||
[_unit, true, PAIN_KNOCK_OUT_DURATION] call FUNC(setUnconscious);
|
||||
};
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Interface to allow external modules to safely adjust pain levels.
|
||||
* Interface to allow external modules to affect the pain level
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The patient <OBJECT>
|
||||
* 1: Added ammount of pain (can be negative) <NUMBER>
|
||||
* 1: Desired pain level (0 .. 1) <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* The new pain level <NUMBER>
|
||||
* nothing
|
||||
*
|
||||
* Example:
|
||||
* [guy, 0.5] call ace_medical_fnc_adjustPainLevel
|
||||
@ -16,21 +16,14 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_pain"];
|
||||
params ["_unit", "_desiredPainLevel"];
|
||||
|
||||
params ["_unit", "_addedPain"];
|
||||
//Only run on local units:
|
||||
if (!local _unit) exitWith {ERROR("unit is not local");};
|
||||
TRACE_3("ACE_DEBUG: adjustPainLevel Called",_unit, _pain, _addedPain);
|
||||
if (!local _unit) exitWith { ERROR("unit is not local"); };
|
||||
|
||||
//Ignore if medical system disabled:
|
||||
if (GVAR(level) == 0) exitWith {};
|
||||
TRACE_2("ACE_DEBUG: adjustPainLevel Called",_unit,_desiredPainLevel);
|
||||
|
||||
private _pain = ((_unit getVariable [QGVAR(pain), 0]) + _addedPain) max 0;
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
|
||||
_pain = 0 max (_pain max _desiredPainLevel) min 1;
|
||||
|
||||
_unit setVariable [QGVAR(pain), _pain];
|
||||
|
||||
//Start up the vital watching (if not already running)
|
||||
// [_unit] call FUNC(addVitalLoop);
|
||||
|
||||
_pain;
|
||||
|
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Displays the patient information for given unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Show <BOOL> (default: true)
|
||||
* 2: Selection <NUMBER> (default: 0)
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
#define MAX_DISTANCE 10
|
||||
|
||||
// Exit for basic medical
|
||||
if (GVAR(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), [[LSTRING(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 = [LSTRING(Head), LSTRING(Torso), LSTRING(LeftArm) ,LSTRING(RightArm) ,LSTRING(LeftLeg), LSTRING(RightLeg)] select _selectionN;
|
||||
_genericMessages pushback [localize _partText, [1, 1, 1, 1]];
|
||||
|
||||
if (_target getVariable[QGVAR(isBleeding), false]) then {
|
||||
_genericMessages pushback [localize LSTRING(Status_Bleeding), [1, 0.1, 0.1, 1]];
|
||||
};
|
||||
if (_target getVariable[QGVAR(hasLostBlood), 0] > 1) then {
|
||||
_genericMessages pushback [localize LSTRING(Status_Lost_Blood), [1, 0.1, 0.1, 1]];
|
||||
};
|
||||
|
||||
if (((_target getVariable [QGVAR(tourniquets), [0,0,0,0,0,0]]) select _selectionN) > 0) then {
|
||||
_genericMessages pushback [localize LSTRING(Status_Tourniquet_Applied), [0.77, 0.51, 0.08, 1]];
|
||||
};
|
||||
if (_target getVariable[QGVAR(hasPain), false]) then {
|
||||
_genericMessages pushback [localize LSTRING(Status_Pain), [1, 1, 1, 1]];
|
||||
};
|
||||
|
||||
private _totalIvVolume = 0;
|
||||
private _bloodBags = _unit getVariable [QGVAR(ivBags), []];
|
||||
{
|
||||
_x params ["_bagVolumeRemaining"];
|
||||
_totalIvVolume = _totalIvVolume + _bagVolumeRemaining;
|
||||
} foreach _bloodBags;
|
||||
|
||||
if (_totalIvVolume >= 1) then {
|
||||
_genericMessages pushback [format[localize LSTRING(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 [QGVAR(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_damage,woundsData) select _x1) select 6, ceil _amountOf], [1,1,1,1]];
|
||||
} else {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushback [format["Partial %1", (EGVAR(medical_damage,woundsData) select _x1) select 6], [1,1,1,1]];
|
||||
};
|
||||
};
|
||||
};
|
||||
} foreach _openWounds;
|
||||
|
||||
private _bandagedwounds = _target getVariable [QGVAR(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_damage,woundsData) 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_damage,woundsData) 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 LSTRING(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 EFUNC(medical_treatment,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"];
|
||||
};
|
@ -11,6 +11,9 @@
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
_unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime];
|
||||
|
||||
[_unit] call FUNC(setCardiacArrest);
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Handle entering an unconscious state.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The unit that will be put in an unconscious state <OBJECT>
|
||||
* 1: Set unconsciouns <BOOL> (default: true)
|
||||
* 2: Minimum unconscious time <NUMBER> (default: (round(random(10)+5)))
|
||||
* 3: Force AI Unconscious (skip random death chance) <BOOL> (default: false)
|
||||
*
|
||||
* ReturnValue:
|
||||
* nil
|
||||
*
|
||||
* Public: no
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
#define DEFAULT_DELAY (round(random(10)+5))
|
||||
|
||||
params ["_unit", "_event", "_args"];
|
||||
|
||||
[_unit, true] call FUNC(setUnconscious);
|
@ -6,7 +6,7 @@
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* ReturnValue:
|
||||
* Total blood loss of unit <NUMBER>
|
||||
* Total blood loss of unit (liter per second) <NUMBER>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
@ -14,18 +14,26 @@
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _totalBloodLoss = 0;
|
||||
private _bloodLoss = 0;
|
||||
private _limbBleeding = 0;
|
||||
private _bodyBleeding = 0;
|
||||
private _tourniquets = _unit getVariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
|
||||
|
||||
{
|
||||
if (_tourniquets select (_x select 2) == 0) then {
|
||||
// total bleeding ratio * percentage of injury left
|
||||
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
|
||||
_x params ["", "", "_bodyPart", "_percentage", "_bleeeding"];
|
||||
if (_bodyPart == 1) then {
|
||||
_bodyBleeding = _bodyBleeding + (_bleeeding * _percentage);
|
||||
} else {
|
||||
if (_tourniquets select _bodyPart == 0) then {
|
||||
_limbBleeding = _limbBleeding + (_bleeeding * _percentage);
|
||||
};
|
||||
};
|
||||
} forEach (_unit getVariable [QGVAR(openWounds), []]);
|
||||
|
||||
{
|
||||
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
|
||||
} forEach (_unit getVariable [QGVAR(internalWounds), []]);
|
||||
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
|
||||
|
||||
_totalBloodLoss * ((_unit getVariable [QGVAR(bleedingCoefficient), GVAR(bleedingCoefficient)]) max 0) * DEFAULT_BLOOD_VOLUME / 100;
|
||||
// limb bleeding is scaled down based on the amount of body bleeding and limited by the current cardiac output
|
||||
_limbBleeding = 0 max (_limbBleeding * (1 - (_bodyBleeding min 1))) min 1;
|
||||
_bloodLoss = (_bodyBleeding + _limbBleeding) * _cardiacOutput;
|
||||
|
||||
_bloodLoss * (_unit getVariable [QGVAR(bleedingCoefficient), GVAR(bleedingCoefficient)])
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Calculates the blood volume change and decreases the IVs given to the unit.
|
||||
* Calculate the blood pressure of a unit.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
@ -15,17 +15,15 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Value is taken because with cardic output and resistance at default values, it will put blood pressure High at 120.
|
||||
#define MODIFIER_BP_HIGH 0.229
|
||||
#define MODIFIER_BP_HIGH 13.7142792
|
||||
|
||||
// Value is taken because with cardic output and resistance at default values, it will put blood pressure Low at 80.
|
||||
#define MODIFIER_BP_LOW 0.1524
|
||||
#define MODIFIER_BP_LOW 9.1428528
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
|
||||
private _resistance = _unit getVariable [QGVAR(peripheralResistance), 100];
|
||||
private _bloodPressure = _cardiacOutput * _resistance;
|
||||
|
||||
private _bloodPressureHigh = (_cardiacOutput * MODIFIER_BP_HIGH) * _resistance;
|
||||
private _bloodPressureLow = (_cardiacOutput * MODIFIER_BP_LOW) * _resistance;
|
||||
|
||||
[_bloodPressureLow max 0, _bloodPressureHigh max 0]
|
||||
[round(_bloodPressure * MODIFIER_BP_LOW), round(_bloodPressure * MODIFIER_BP_HIGH)]
|
||||
|
@ -4,47 +4,49 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Global Sync Values (bloodbags) <BOOL>
|
||||
* 1: Time since last update <NUMBER>
|
||||
* 2: Global Sync Values (bloodbags) <BOOL>
|
||||
*
|
||||
* ReturnValue:
|
||||
* Blood volume change (in % total) <NUMBER>
|
||||
* Blood volume change (liters per second) <NUMBER>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_syncValues"];
|
||||
params ["_unit", "_deltaT", "_syncValues"];
|
||||
|
||||
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME];
|
||||
private _bloodVolumeChange = -(_unit call FUNC(getBloodLoss));
|
||||
private _bloodVolumeChange = -_deltaT * (_unit call FUNC(getBloodLoss));
|
||||
|
||||
if (!isNil {_unit getVariable QGVAR(ivBags)}) then {
|
||||
if (_bloodVolume < DEFAULT_BLOOD_VOLUME) then {
|
||||
private _bloodBags = _unit getVariable [QGVAR(ivBags), []];
|
||||
private _bloodBags = _unit getVariable [QGVAR(ivBags), []];
|
||||
|
||||
_bloodBags = _bloodBags apply {
|
||||
_x params ["_bagVolumeRemaining"];
|
||||
_bloodBags = _bloodBags apply {
|
||||
_x params ["_bagVolumeRemaining"];
|
||||
|
||||
private _bagChange = IV_CHANGE_PER_SECOND min _bagVolumeRemaining; // absolute value of the change in miliLiters
|
||||
if (GVAR(advancedIVBags)) then {
|
||||
private _bagChange = _deltaT * (IV_CHANGE_PER_SECOND min _bagVolumeRemaining); // absolute value of the change in miliLiters
|
||||
_bagVolumeRemaining = _bagVolumeRemaining - _bagChange;
|
||||
_bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000);
|
||||
|
||||
if (_bagVolumeRemaining < 0.01) then {
|
||||
[]
|
||||
} else {
|
||||
[_bagVolumeRemaining];
|
||||
[_bagVolumeRemaining]
|
||||
};
|
||||
};
|
||||
|
||||
_bloodBags = _bloodBags - [[]]; // remove empty bags
|
||||
|
||||
if (_bloodBags isEqualTo []) then {
|
||||
_unit setVariable [QGVAR(ivBags), nil, true]; // no bags left - clear variable (always globaly sync this)
|
||||
} else {
|
||||
_unit setVariable [QGVAR(ivBags), _bloodBags, _syncValues];
|
||||
_bloodVolumeChange = _bloodVolumeChange + (_bagVolumeRemaining / 1000);
|
||||
[]
|
||||
};
|
||||
};
|
||||
|
||||
_bloodBags = _bloodBags - [[]]; // remove empty bags
|
||||
|
||||
if (_bloodBags isEqualTo []) then {
|
||||
_unit setVariable [QGVAR(ivBags), nil, true]; // no bags left - clear variable (always globaly sync this)
|
||||
} else {
|
||||
_unit setVariable [QGVAR(ivBags), nil, true]; // blood volume = 100% - clear variable (always globaly sync this)
|
||||
_unit setVariable [QGVAR(ivBags), _bloodBags, _syncValues];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* ReturnValue:
|
||||
* Current cardiac output <NUMBER>
|
||||
* Current cardiac output (liter per second) <NUMBER>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
@ -14,8 +14,7 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
/*
|
||||
Cardiac output (Q or or CO ) is the volume of blood being pumped by the heart, in particular by a left or right ventricle in the CBA_missionTime interval of one minute. CO may be measured in many ways, for example dm3/min (1 dm3 equals 1 litre).
|
||||
|
||||
Cardiac output (Q or or CO ) is the volume of blood being pumped by the heart, in particular by a left or right ventricle in the CBA_missionTime interval of one second. CO may be measured in many ways, for example dm3/min (1 dm3 equals 1 litre).
|
||||
Source: http://en.wikipedia.org/wiki/Cardiac_output
|
||||
*/
|
||||
|
||||
@ -24,4 +23,10 @@
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
((_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) / MODIFIER_CARDIAC_OUTPUT) + ((_unit getVariable [QGVAR(heartRate), 80]) / 80 - 1);
|
||||
if (_unit getVariable [QGVAR(inCardiacArrest), false]) exitWith { 0 };
|
||||
|
||||
private _bloodVolume = ((_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) / DEFAULT_BLOOD_VOLUME) * 100;
|
||||
private _heartRate = _unit getVariable [QGVAR(heartRate), 80];
|
||||
private _cardiacOutput = ((_bloodVolume / MODIFIER_CARDIAC_OUTPUT) + ((_heartRate / 80) - 1)) / 60;
|
||||
|
||||
(0 max _cardiacOutput)
|
||||
|
@ -13,15 +13,11 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
#define HEART_RATE_MODIFIER 0.02
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _hrIncrease = 0;
|
||||
if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
|
||||
private _heartRate = _unit getVariable [QGVAR(heartRate), 80];
|
||||
private _bloodLoss = [_unit] call FUNC(getBloodLoss);
|
||||
|
||||
if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
|
||||
private _adjustment = _unit getVariable [QGVAR(heartRateAdjustments), []];
|
||||
{
|
||||
_x params ["_values", "_time", "_callBack"];
|
||||
@ -49,36 +45,37 @@ if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
|
||||
_adjustment = _adjustment - [ObjNull];
|
||||
_unit setVariable [QGVAR(heartRateAdjustments), _adjustment];
|
||||
|
||||
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME];
|
||||
if (_bloodVolume > 75) then {
|
||||
if (_bloodLoss > 0.0) then {
|
||||
if (_bloodLoss < 0.5) then {
|
||||
if (_heartRate < 126) then {
|
||||
_hrIncrease = _hrIncrease + 0.05;
|
||||
};
|
||||
} else {
|
||||
if (_bloodLoss < 1) then {
|
||||
if (_heartRate < 161) then {
|
||||
_hrIncrease = _hrIncrease + 0.1;
|
||||
};
|
||||
} else {
|
||||
if (_heartRate < 220) then {
|
||||
_hrIncrease = _hrIncrease + 0.15;
|
||||
};
|
||||
if (!(_unit getVariable [QGVAR(inCardiacArrest), false])) then {
|
||||
private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]);
|
||||
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME];
|
||||
if (_bloodVolume > BLOOD_VOLUME_CLASS_4_HEMORRHAGE) then {
|
||||
private _hrChange = 0;
|
||||
([_unit] call FUNC(getBloodPressure)) params ["_bloodPressureL", "_bloodPressureH"];
|
||||
private _meanBP = (2/3) * _bloodPressureH + (1/3) * _bloodPressureL;
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
private _hasPain = _unit getVariable [QGVAR(hasPain), false];
|
||||
private _targetBP = 107;
|
||||
private _targetHR = 80;
|
||||
if (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE) then {
|
||||
_targetBP = _targetBP * (_bloodVolume / DEFAULT_BLOOD_VOLUME);
|
||||
};
|
||||
if (_hasPain && {_pain > 0.2}) then {
|
||||
_targetHR = 130;
|
||||
};
|
||||
if (_heartRate < _targetHR) then {
|
||||
_hrChange = round(_targetHR - _heartRate) / 2;
|
||||
};
|
||||
if ((_meanBP > _targetBP && {_heartRate > _targetHR}) || {_bloodVolume < BLOOD_VOLUME_CLASS_2_HEMORRHAGE && {_heartRate < 200}}) then {
|
||||
_hrChange = 2 * round(_targetBP - _meanBP);
|
||||
if (_hrChange < 0) then {
|
||||
_hrChange = _hrChange / 20;
|
||||
};
|
||||
};
|
||||
_hrIncrease = _hrIncrease + _hrChange;
|
||||
} else {
|
||||
// Stabalize it
|
||||
if (_heartRate < (60 + round(random(10)))) then {
|
||||
_hrIncrease = _hrIncrease + HEART_RATE_MODIFIER;
|
||||
} else {
|
||||
if (_heartRate > (77 + round(random(10)))) then {
|
||||
_hrIncrease = _hrIncrease - HEART_RATE_MODIFIER;
|
||||
};
|
||||
};
|
||||
_hrIncrease = _hrIncrease - (random 5) * round(_heartRate / 10);
|
||||
};
|
||||
} else {
|
||||
_hrIncrease = _hrIncrease - HEART_RATE_MODIFIER;
|
||||
};
|
||||
};
|
||||
|
||||
_hrIncrease
|
||||
|
45
addons/medical/functions/fnc_handleIncapacitation.sqf
Normal file
45
addons/medical/functions/fnc_handleIncapacitation.sqf
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Author: Ruthberg
|
||||
* Handle incapacitation due to damage and pain
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* ReturnValue:
|
||||
* nothing
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
private _headDamage = 0;
|
||||
private _bodyDamage = 0;
|
||||
|
||||
{
|
||||
_x params ["", "", "_bodyPart", "", "", "_damage"];
|
||||
switch (_bodyPart) do {
|
||||
case 0: {
|
||||
_headDamage = _headDamage + _damage;
|
||||
};
|
||||
case 1: {
|
||||
if (_damage > PENETRATION_THRESHOLD) then {
|
||||
_bodyDamage = _bodyDamage + _damage;
|
||||
};
|
||||
};
|
||||
};
|
||||
} forEach (_unit getVariable [QGVAR(openWounds), []]);
|
||||
|
||||
// todo: use an ace settings for the thresholds
|
||||
if (_headDamage > 0.50) then {
|
||||
[QGVAR(CriticalInjury), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
if (_bodyDamage > 1.05) then {
|
||||
[QGVAR(CriticalInjury), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
if ((_pain >= PAIN_UNCONSCIOUS) && {random 1 < 0.1}) then {
|
||||
[QGVAR(CriticalInjury), _unit] call CBA_fnc_localEvent;
|
||||
};
|
@ -17,8 +17,6 @@ params ["_unit"];
|
||||
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];
|
||||
};
|
||||
_unit setVariable [QGVAR(heartRate), 0];
|
||||
_unit setVariable [QGVAR(bloodPressure), [0, 0]];
|
||||
_unit setVariable [QGVAR(airwayStatus), 0];
|
@ -17,17 +17,10 @@
|
||||
|
||||
params ["_unit", "_local"];
|
||||
if (_local) then {
|
||||
// If the unit had a loop tracking its vitals, restart it locally
|
||||
if (_unit getVariable [QGVAR(addedToUnitLoop),false]) then {
|
||||
[_unit, true] call FUNC(addVitalLoop);
|
||||
};
|
||||
|
||||
if ((_unit getVariable ["ACE_isUnconscious",false]) && {count (_unit getVariable [QGVAR(unconsciousArguments), []]) >= 6}) then {
|
||||
private _arguments = (_unit getVariable [QGVAR(unconsciousArguments), []]);
|
||||
_arguments set [2, CBA_missionTime];
|
||||
|
||||
//[DFUNC(unconsciousPFH), 0.1, _arguments ] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
_unit setVariable [QGVAR(unconsciousArguments), nil, true];
|
||||
};
|
||||
};
|
||||
|
@ -1,24 +1,19 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
params ["_unit", "_stateName"];
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true];
|
||||
};
|
||||
|
||||
systemChat format["handling state default for unit: %1", _this];
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
[_unit] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
|
@ -1,22 +1,19 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
params ["_unit", "_stateName"];
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
[_unit] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
|
@ -1,22 +1,19 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
params ["_unit", "_stateName"];
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
[_unit] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
|
@ -12,27 +12,33 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_interval"];
|
||||
TRACE_3("ACE_DEBUG",_unit,_interval,_unit);
|
||||
params ["_unit"];
|
||||
|
||||
if (_interval == 0) exitWith {};
|
||||
private _lastTimeUpdated = _unit getVariable [QGVAR(lastTimeUpdated), CBA_missionTime];
|
||||
private _deltaT = CBA_missionTime - _lastTimeUpdated;
|
||||
_unit setVariable [QGVAR(lastTimeUpdated), CBA_missionTime];
|
||||
|
||||
TRACE_2("ACE_DEBUG",_unit,_deltaT);
|
||||
|
||||
if (_deltaT == 0) exitWith {};
|
||||
|
||||
private _lastTimeValuesSynced = _unit getVariable [QGVAR(lastMomentValuesSynced), 0];
|
||||
private _syncValues = (CBA_missionTime - _lastTimeValuesSynced >= 10 + floor(random(10))) && GVAR(keepLocalSettingsSynced);
|
||||
private _syncValues = (CBA_missionTime - _lastTimeValuesSynced) >= (10 + floor(random(10)));
|
||||
|
||||
if (_syncValues) then {
|
||||
_unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime];
|
||||
};
|
||||
|
||||
private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) + ([_unit, _syncValues] call FUNC(getBloodVolumeChange));
|
||||
_bloodVolume = (_bloodVolume max 0) min DEFAULT_BLOOD_VOLUME;
|
||||
private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) + ([_unit, _deltaT, _syncValues] call FUNC(getBloodVolumeChange));
|
||||
_bloodVolume = 0 max _bloodVolume min DEFAULT_BLOOD_VOLUME;
|
||||
|
||||
// @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic)
|
||||
_unit setVariable [QGVAR(bloodVolume), _bloodVolume, _syncValues];
|
||||
|
||||
TRACE_3("ACE_DEBUG",_bloodVolume,_syncValues,_unit);
|
||||
// Set variables for synchronizing information across the net
|
||||
if (_bloodVolume < BLOOD_VOLUME_HAS_LOST_SOME) then {
|
||||
if (_bloodVolume < BLOOD_VOLUME_HAS_LOST_MUCH) then {
|
||||
if (_bloodVolume < BLOOD_VOLUME_CLASS_1_HEMORRHAGE) then {
|
||||
if (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE) then {
|
||||
if (_unit getVariable [QGVAR(hasLostBlood), 0] != 2) then {
|
||||
_unit setVariable [QGVAR(hasLostBlood), 2, true];
|
||||
};
|
||||
@ -52,7 +58,7 @@ TRACE_3("ACE_DEBUG",_bloodLoss,_unit getVariable QGVAR(isBleeding),_unit);
|
||||
if (_bloodLoss > 0) then {
|
||||
_unit setVariable [QGVAR(bloodloss), _bloodLoss, _syncValues];
|
||||
|
||||
[QGVAR(TakenInjury), _unit] call CBA_fnc_localEvent;
|
||||
[QGVAR(Injury), _unit] call CBA_fnc_localEvent;
|
||||
|
||||
if !(_unit getVariable [QGVAR(isBleeding), false]) then {
|
||||
_unit setVariable [QGVAR(isBleeding), true, true];
|
||||
@ -75,75 +81,55 @@ if (_painStatus > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
};
|
||||
};
|
||||
|
||||
if (_bloodVolume < BLOOD_VOLUME_DEAD) exitWith {
|
||||
[_unit, "bloodloss"] call FUNC(setDead);
|
||||
TRACE_6("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_bloodVolume,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
|
||||
|
||||
// Handle pain due tourniquets, that have been applied more than 120 s ago
|
||||
private _oldTourniquets = (_unit getVariable [QGVAR(tourniquets), []]) select {_x > 0 && {CBA_missionTime - _x > 120}};
|
||||
// Increase pain at a rate of 0.001 units/s per old tourniquet
|
||||
_painStatus = _painStatus + (count _oldTourniquets) * 0.001 * _deltaT;
|
||||
|
||||
private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]) + _deltaT * ([_unit] call FUNC(getHeartRateChange));
|
||||
_unit setVariable [QGVAR(heartRate), 0 max _heartRate, _syncValues];
|
||||
|
||||
private _bloodPressure = [_unit] call FUNC(getBloodPressure);
|
||||
_unit setVariable [QGVAR(bloodPressure), _bloodPressure, _syncValues];
|
||||
|
||||
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
|
||||
if (_bloodLoss > BLOOD_LOSS_KNOCK_OUT_THRESHOLD * _cardiacOutput) then {
|
||||
[QGVAR(CriticalVitals), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
if ([_unit] call EFUNC(common,isAwake)) then {
|
||||
if (_bloodVolume < BLOOD_VOLUME_UNCONSCIOUS && {random 1 < BLOOD_LOSS_KNOCK_OUT_CHANCE}) exitWith {
|
||||
[_unit, true, BLOOD_LOSS_KNOCK_OUT_DURATION] call FUNC(setUnconscious);
|
||||
};
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
if (!isPlayer _unit) then {
|
||||
private _cardiacArrest = _unit getVariable [QGVAR(inCardiacArrest), false];
|
||||
hintSilent format["blood volume: %1, blood loss: [%2, %3]\nhr: %4, bp: %5, pain: %6", round(_bloodVolume * 100) / 100, round(_bloodLoss * 1000) / 1000, round((_bloodLoss / _cardiacOutput) * 100) / 100, round(_heartRate), _bloodPressure, round(_painStatus * 100) / 100];
|
||||
};
|
||||
#endif
|
||||
|
||||
_unit setVariable [QGVAR(pain), 0 max (_painStatus - _deltaT * PAIN_REDUCTION_SPEED), _syncValues];
|
||||
|
||||
TRACE_8("ACE_DEBUG_ADVANCED_VITALS",_painStatus,PAIN_REDUCTION_SPEED,_heartRate,_bloodVolume,_bloodPressure,_deltaT,_syncValues,_unit);
|
||||
|
||||
_bloodPressure params ["_bloodPressureL", "_bloodPressureH"];
|
||||
if (_bloodPressureL < 40) then {
|
||||
[QGVAR(CriticalVitals), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
if ((_heartRate < 20) || {_heartRate > 220} || {_bloodPressureH < 50}) then {
|
||||
[QGVAR(FatalVitals), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
/*
|
||||
if (GVAR(level) == 1) then {
|
||||
TRACE_5("ACE_DEBUG_BASIC_VITALS",_painStatus,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
|
||||
// reduce pain
|
||||
if (_painStatus > 0) then {
|
||||
_unit setVariable [QGVAR(pain), (_painStatus - 0.001 * _interval) max 0, _syncValues];
|
||||
};
|
||||
|
||||
//// reduce painkillers
|
||||
//if (_unit getVariable [QGVAR(morphine), 0] > 0) then {
|
||||
// _unit setVariable [QGVAR(morphine), ((_unit getVariable [QGVAR(morphine), 0]) - 0.0015 * _interval) max 0, _syncValues];
|
||||
//};
|
||||
};
|
||||
*/
|
||||
|
||||
// handle advanced medical, with vitals
|
||||
/*
|
||||
if (GVAR(level) >= 2) then {
|
||||
TRACE_6("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_bloodVolume, _unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
|
||||
|
||||
// Handle pain due tourniquets, that have been applied more than 120 s ago
|
||||
private _oldTourniquets = (_unit getVariable [QGVAR(tourniquets), []]) select {_x > 0 && {CBA_missionTime - _x > 120}};
|
||||
// Increase pain at a rate of 0.001 units/s per old tourniquet
|
||||
_painStatus = _painStatus + (count _oldTourniquets) * 0.001 * _interval;
|
||||
|
||||
// Set the vitals
|
||||
private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]) + (([_unit] call FUNC(getHeartRateChange)) * _interval);
|
||||
_unit setVariable [QGVAR(heartRate), _heartRate max 0, _syncValues];
|
||||
|
||||
private _bloodPressure = [_unit] call FUNC(getBloodPressure);
|
||||
_unit setVariable [QGVAR(bloodPressure), _bloodPressure, _syncValues];
|
||||
|
||||
_painReduce = [0.001, 0.002] select (_painStatus > 5);
|
||||
|
||||
// @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic)
|
||||
_unit setVariable [QGVAR(pain), (_painStatus - _painReduce * _interval) max 0, _syncValues];
|
||||
|
||||
TRACE_8("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_painReduce,_heartRate,_bloodVolume,_bloodPressure,_interval,_syncValues,_unit);
|
||||
|
||||
// Check vitals for medical status
|
||||
// TODO check for in revive state instead of variable
|
||||
_bloodPressure params ["_bloodPressureL", "_bloodPressureH"];
|
||||
|
||||
if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
|
||||
if (_heartRate < 10 || _bloodPressureH < 30 || _bloodVolume < BLOOD_VOLUME_CARDIAC_ARREST) then {
|
||||
[_unit, true, 10+ random(20)] call FUNC(setUnconscious); // safety check to ensure unconsciousness for units if they are not dead already.
|
||||
};
|
||||
|
||||
if ((_bloodPressureH > 260)
|
||||
|| {_bloodPressureL < 40 && ({_heartRate > 190})}
|
||||
|| {(_bloodPressureH > 145 && {_heartRate > 150})}) then {
|
||||
|
||||
if (random(1) > 0.7) then {
|
||||
[_unit] call FUNC(setCardiacArrest);
|
||||
// Handle spontaneous wakeup from unconsciousness
|
||||
if (_unit getVariable [QGVAR(isUnconscious), false]) then {
|
||||
if (_unit call FUNC(hasStableVitals)) then {
|
||||
private _lastWakeUpCheck = _unit getVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
|
||||
if (CBA_missionTime - _lastWakeUpCheck > SPONTANEOUS_WAKE_UP_INTERVAL) then {
|
||||
_unit setVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
|
||||
if ((random 1) < SPONTANEOUS_WAKE_UP_CHANCE) then {
|
||||
[QGVAR(WakeUp), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
||||
if (_heartRate > 200 || (_heartRate < 20)) then {
|
||||
[_unit] call FUNC(setCardiacArrest);
|
||||
};
|
||||
} else {
|
||||
// Unstable vitals, procrastinate the next wakeup check
|
||||
_unit setVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
32
addons/medical/functions/fnc_hasStableVitals.sqf
Normal file
32
addons/medical/functions/fnc_hasStableVitals.sqf
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Author: Ruthberg
|
||||
* Check if a unit has stable vitals (required to become conscious)
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The patient <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Has stable vitals <BOOL>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
if (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME] < BLOOD_VOLUME_CLASS_2_HEMORRHAGE) exitWith { false };
|
||||
if (_unit getVariable [QGVAR(inCardiacArrest), false]) exitWith { false };
|
||||
|
||||
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
|
||||
private _bloodLoss = _unit call FUNC(getBloodLoss);
|
||||
if (_bloodLoss > (BLOOD_LOSS_KNOCK_OUT_THRESHOLD * _cardiacOutput) / 2) exitWith { false };
|
||||
|
||||
private _bloodPressure = [_unit] call FUNC(getBloodPressure);
|
||||
_bloodPressure params ["_bloodPressureL", "_bloodPressureH"];
|
||||
if (_bloodPressureL < 50 || {_bloodPressureH < 60}) exitWith { false };
|
||||
|
||||
private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]);
|
||||
if (_heartRate < 40) exitWith { false };
|
||||
|
||||
true
|
@ -20,7 +20,8 @@ if (damage _unit > 0) then {
|
||||
|
||||
_unit setVariable [QGVAR(pain), 0, true];
|
||||
_unit setVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME, true];
|
||||
_unit setVariable ["ACE_isUnconscious", false, true]; // TODO this is done based on state
|
||||
_unit setVariable [QGVAR(isUnconscious), false, true];
|
||||
_unit setVariable [QGVAR(partialHealCounter), 0, true];
|
||||
|
||||
// tourniquets
|
||||
_unit setVariable [QGVAR(tourniquets), [0,0,0,0,0,0], true];
|
||||
@ -29,7 +30,7 @@ _unit setVariable [QGVAR(occludedMedications), nil, true]; //Delayed Medications
|
||||
// wounds and injuries
|
||||
_unit setVariable [QGVAR(openWounds), [], true];
|
||||
_unit setVariable [QGVAR(bandagedWounds), [], true];
|
||||
_unit setVariable [QGVAR(internalWounds), [], true];
|
||||
_unit setVariable [QGVAR(stitchedWounds), [], true];
|
||||
|
||||
// vitals
|
||||
_unit setVariable [QGVAR(heartRate), 80];
|
||||
@ -37,9 +38,6 @@ _unit setVariable [QGVAR(heartRateAdjustments), []];
|
||||
_unit setVariable [QGVAR(bloodPressure), [80, 120]];
|
||||
_unit setVariable [QGVAR(peripheralResistance), 100];
|
||||
|
||||
// fractures
|
||||
_unit setVariable [QGVAR(fractures), [], true];
|
||||
|
||||
// triage card and logs
|
||||
// TODO move to treatment
|
||||
//_unit setVariable [QGVAR(triageLevel), 0, true];
|
||||
@ -51,14 +49,8 @@ _unit setVariable [QGVAR(ivBags), nil, true];
|
||||
// damage storage
|
||||
_unit setVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true];
|
||||
|
||||
// airway
|
||||
_unit setVariable [QGVAR(airwayStatus), 100];
|
||||
_unit setVariable [QGVAR(airwayOccluded), false];
|
||||
_unit setVariable [QGVAR(airwayCollapsed), false];
|
||||
|
||||
// generic medical admin
|
||||
_unit setVariable [QGVAR(addedToUnitLoop), false, true]; // TODO this is replaced by unit state
|
||||
_unit setVariable [QGVAR(inCardiacArrest), false, true]; // TODO this is no longer present
|
||||
_unit setVariable [QGVAR(inCardiacArrest), false, true];
|
||||
_unit setVariable [QGVAR(hasLostBlood), 0, true];
|
||||
_unit setVariable [QGVAR(isBleeding), false, true];
|
||||
_unit setVariable [QGVAR(hasPain), false, true];
|
||||
|
@ -15,10 +15,9 @@
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _totalBloodLoss = 0;
|
||||
{
|
||||
// total bleeding ratio * percentage of injury left
|
||||
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
|
||||
} forEach (_unit getVariable [QGVAR(openWounds), []]);
|
||||
if (!alive _unit) exitWith { false };
|
||||
if (_unit call FUNC(getBloodLoss) > 0) exitWith { false };
|
||||
if (!(_unit call FUNC(hasStableVitals))) exitWith { false };
|
||||
if (_unit getVariable [QGVAR(isUnconscious), false]) exitWith { false };
|
||||
|
||||
(_totalBloodLoss == 0);
|
||||
true
|
||||
|
@ -16,13 +16,14 @@
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
if (_unit getVariable [QGVAR(inCardiacArrest),false]) exitWith {};
|
||||
_unit setVariable [QGVAR(inCardiacArrest), true,true];
|
||||
_unit setVariable [QGVAR(heartRate), 0];
|
||||
if (_unit getVariable [QGVAR(inCardiacArrest), false]) exitWith {};
|
||||
_unit setVariable [QGVAR(inCardiacArrest), true, true];
|
||||
_unit setVariable [QGVAR(heartRate), 0, true];
|
||||
|
||||
["ace_cardiacArrestEntered", [_unit]] call CBA_fnc_localEvent;
|
||||
|
||||
[_unit, true] call FUNC(setUnconscious);
|
||||
[QEGVAR(medical,InjuryCritical), _unit] call CBA_fnc_localEvent;
|
||||
private _timeInCardiacArrest = 120 + round(random(600));
|
||||
|
||||
[{
|
||||
@ -30,13 +31,13 @@ private _timeInCardiacArrest = 120 + round(random(600));
|
||||
_args params ["_unit", "_startTime", "_timeInCardiacArrest"];
|
||||
|
||||
private _heartRate = _unit getVariable [QGVAR(heartRate), 80];
|
||||
if (_heartRate > 0 || !alive _unit) exitWith {
|
||||
if (_heartRate > 20 || !alive _unit) exitWith {
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
_unit setVariable [QGVAR(inCardiacArrest), nil,true];
|
||||
_unit setVariable [QGVAR(inCardiacArrest), nil, true];
|
||||
};
|
||||
if (CBA_missionTime - _startTime >= _timeInCardiacArrest) exitWith {
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
_unit setVariable [QGVAR(inCardiacArrest), nil,true];
|
||||
_unit setVariable [QGVAR(inCardiacArrest), nil, true];
|
||||
[_unit] call FUNC(setDead);
|
||||
};
|
||||
}, 1, [_unit, CBA_missionTime, _timeInCardiacArrest] ] call CBA_fnc_addPerFrameHandler;
|
||||
|
@ -5,8 +5,6 @@
|
||||
* Arguments:
|
||||
* 0: The unit that will be put in an unconscious state <OBJECT>
|
||||
* 1: Set unconsciouns <BOOL> (default: true)
|
||||
* 2: Minimum unconscious time <NUMBER> (default: (round(random(10)+5)))
|
||||
* 3: Force AI Unconscious (skip random death chance) <BOOL> (default: false)
|
||||
*
|
||||
* ReturnValue:
|
||||
* Success? <BOOLEAN>
|
||||
@ -23,20 +21,15 @@ if !(EGVAR(common,settingsInitFinished)) exitWith {
|
||||
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(setUnconscious), _this];
|
||||
};
|
||||
|
||||
params ["_unit", ["_knockOut", true], ["_minUnconsciousTime", DEFAULT_KNOCK_OUT_DELAY], ["_force", false]];
|
||||
params ["_unit", ["_knockOut", true]];
|
||||
|
||||
if (isNull _unit || {!(_unit isKindOf "CAManBase")}) exitWith {false};
|
||||
|
||||
if (!local _unit) exitWith {
|
||||
[QGVAR(setUnconscious), [_unit, _knockOut, _minUnconsciousTime, _force], _unit] call CBA_fnc_targetEvent;
|
||||
[QGVAR(setUnconscious), [_unit, _knockOut], _unit] call CBA_fnc_targetEvent;
|
||||
true
|
||||
};
|
||||
|
||||
// use maximum for wake up time
|
||||
if (_knockOut) then {
|
||||
_unit setVariable [QGVAR(wakeUpTime), (CBA_missionTime + _minUnconsciousTime) max (_unit getVariable [QGVAR(wakeUpTime), 0])];
|
||||
};
|
||||
|
||||
if (_knockOut isEqualTo (_unit getVariable [QGVAR(isUnconscious), false])) exitWith {false};
|
||||
|
||||
// --- wake up
|
||||
@ -55,6 +48,7 @@ if !(_knockOut) exitWith {
|
||||
|
||||
// --- knock out
|
||||
_unit setVariable [QGVAR(isUnconscious), true, true];
|
||||
_unit setVariable [QGVAR(lastWakeUpCheck), CBA_missiontime];
|
||||
|
||||
if (_unit == ACE_player) then {
|
||||
if (visibleMap) then {openMap false};
|
||||
@ -64,39 +58,8 @@ if (_unit == ACE_player) then {
|
||||
};
|
||||
};
|
||||
|
||||
// if we have unconsciousness for AI disabled, we will kill the unit instead
|
||||
/*
|
||||
private _isDead = false;
|
||||
|
||||
if (!([_unit, GVAR(remoteControlledAI)] call EFUNC(common,isPlayer)) && !_force) then {
|
||||
_enableUncon = _unit getVariable [QGVAR(enableUnconsciousnessAI), GVAR(enableUnconsciousnessAI)];
|
||||
|
||||
if (_enableUncon == 0 or {_enableUncon == 1 and (random 1) < 0.5}) then {
|
||||
[_unit, true] call FUNC(setDead);
|
||||
_isDead = true;
|
||||
};
|
||||
};
|
||||
|
||||
if (_isDead) exitWith {};
|
||||
*/
|
||||
|
||||
[_unit, true] call EFUNC(medical_engine,setUnconsciousAnim);
|
||||
[QGVAR(Unconscious), _unit] call CBA_fnc_localEvent;
|
||||
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent;
|
||||
|
||||
// auto wake up
|
||||
[{
|
||||
params ["_unit"];
|
||||
|
||||
private _time = _unit getVariable [QGVAR(wakeUpTime), 0];
|
||||
|
||||
!(_unit getVariable [QGVAR(isUnconscious), false]) || {CBA_missionTime > _time}
|
||||
}, {
|
||||
params ["_unit"];
|
||||
|
||||
if (_unit getVariable [QGVAR(isUnconscious), false]) then {
|
||||
[_unit, false] call FUNC(setUnconscious);
|
||||
};
|
||||
}, _unit] call CBA_fnc_waitUntilAndExecute;
|
||||
|
||||
true
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* PFH logic for unconscious state
|
||||
*
|
||||
* Arguments:
|
||||
* 0: PFEH - Args
|
||||
* 0: The unit that will be put in an unconscious state <OBJECT>
|
||||
* 1: unitPos (stance) <STRING>
|
||||
* 2: Starting Time <NUMBER>
|
||||
* 3: Minimum Waiting Time <NUMBER>
|
||||
* 4: Has Moved Out <BOOL>
|
||||
* 5: Parachute Check <BOOL>
|
||||
* 1: PFEH ID <NUMBER>
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: yes
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_unit", "_minWaitingTime", "_slotInfo", "_hasMovedOut", "_parachuteCheck", "_args", "_originalPos", "_startingTime", "_awakeInVehicleAnimation", "_oldVehicleAnimation", "_vehicle"];
|
||||
params ["_args", "_idPFH"];
|
||||
_args params ["_unit", "_originalPos", "_startingTime", "_minWaitingTime", "_hasMovedOut", "_parachuteCheck"];
|
||||
|
||||
TRACE_6("ACE_DEBUG_Unconscious_PFH",_unit, _originalPos, _startingTime, _minWaitingTime, _hasMovedOut, _parachuteCheck);
|
||||
|
||||
if (!alive _unit) exitWith {
|
||||
if ("ACE_FakePrimaryWeapon" in (weapons _unit)) then {
|
||||
TRACE_1("Removing fake weapon [on death]",_unit);
|
||||
_unit removeWeapon "ACE_FakePrimaryWeapon";
|
||||
};
|
||||
if (GVAR(moveUnitsFromGroupOnUnconscious)) then {
|
||||
[_unit, false, "ACE_isUnconscious", side group _unit] call EFUNC(common,switchToGroupSide);
|
||||
};
|
||||
[_unit, "setCaptive", "ace_unconscious", false] call EFUNC(common,statusEffect_set);
|
||||
[_unit, false] call EFUNC(common,disableAI);
|
||||
//_unit setUnitPos _originalPos;
|
||||
//_unit setUnconscious false;
|
||||
|
||||
[_unit, "isUnconscious"] call EFUNC(common,unmuteUnit);
|
||||
["ace_unconscious", [_unit, false]] call CBA_fnc_globalEvent;
|
||||
|
||||
TRACE_3("ACE_DEBUG_Unconscious_Exit",_unit, (!alive _unit) , "ace_unconscious");
|
||||
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
|
||||
// In case the unit is no longer in an unconscious state, we are going to check if we can already reset the animation
|
||||
if !(_unit getVariable ["ACE_isUnconscious",false]) exitWith {
|
||||
TRACE_7("ACE_DEBUG_Unconscious_PFH",_unit, _args, [_unit] call EFUNC(medical_treatment,isBeingCarried), [_unit] call EFUNC(medical_treatment,isBeingDragged), _idPFH, _unit getVariable QGVAR(unconsciousArguments),animationState _unit);
|
||||
// TODO, handle this with carry instead, so we can remove the PFH here.
|
||||
// Wait until the unit isn't being carried anymore, so we won't end up with wierd animations
|
||||
if !(([_unit] call EFUNC(medical_treatment,isBeingCarried)) || ([_unit] call EFUNC(medical_treatment,isBeingDragged))) then {
|
||||
if ("ACE_FakePrimaryWeapon" in (weapons _unit)) then {
|
||||
TRACE_1("Removing fake weapon [on wakeup]",_unit);
|
||||
_unit removeWeapon "ACE_FakePrimaryWeapon";
|
||||
};
|
||||
|
||||
if (vehicle _unit == _unit) then {
|
||||
if (animationState _unit == "AinjPpneMstpSnonWrflDnon") then {
|
||||
[_unit,"AinjPpneMstpSnonWrflDnon_rolltofront", 2] call EFUNC(common,doAnimation);
|
||||
[_unit,"amovppnemstpsnonwnondnon", 1] call EFUNC(common,doAnimation);
|
||||
} else {
|
||||
[_unit,"amovppnemstpsnonwnondnon", 2] call EFUNC(common,doAnimation);
|
||||
};
|
||||
} else {
|
||||
_vehicle = vehicle _unit;
|
||||
_oldVehicleAnimation = _unit getVariable [QGVAR(vehicleAwakeAnim), []];
|
||||
_awakeInVehicleAnimation = "";
|
||||
if (((count _oldVehicleAnimation) > 0) && {(_oldVehicleAnimation select 0) == _vehicle}) then {
|
||||
_awakeInVehicleAnimation = _oldVehicleAnimation select 1;
|
||||
};
|
||||
//Make sure we have a valid, non-terminal animation:
|
||||
if ((_awakeInVehicleAnimation != "") && {(getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> _awakeInVehicleAnimation >> "terminal")) == 0}) then {
|
||||
[_unit, _awakeInVehicleAnimation, 2] call EFUNC(common,doAnimation);
|
||||
} else {
|
||||
//Don't have a valid animation saved, reset the unit animation with a moveInXXX
|
||||
TRACE_1("No Valid Animation, doing seat reset", _awakeInVehicleAnimation);
|
||||
_slotInfo = [];
|
||||
{if ((_x select 0) == _unit) exitWith {_slotInfo = _x;};} forEach (fullCrew _vehicle);
|
||||
if (_slotInfo isEqualTo []) exitWith {ERROR("No _slotInfo?");};
|
||||
//Move the unit out:
|
||||
_unit setPosASL ((getPosASL _unit) vectorAdd [0,0,100]);
|
||||
//Move the unit back into old seat:
|
||||
if ((_slotInfo select 1) == "driver") then {
|
||||
_unit moveInDriver _vehicle;
|
||||
} else {
|
||||
if ((_slotInfo select 1) == "cargo") then {
|
||||
_unit moveInCargo [_vehicle, (_slotInfo select 2)];
|
||||
} else {
|
||||
_unit moveInTurret [_vehicle, (_slotInfo select 3)];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
_unit setVariable [QGVAR(vehicleAwakeAnim), nil];
|
||||
|
||||
["ace_unconscious", [_unit, false]] call CBA_fnc_globalEvent;
|
||||
// EXIT PFH
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
if (!_hasMovedOut) then {
|
||||
// Reset the unit back to the previous captive state.
|
||||
[_unit, "setCaptive", "ace_unconscious", false] call EFUNC(common,statusEffect_set);
|
||||
|
||||
// Swhich the unit back to its original group
|
||||
//Unconscious units shouldn't be put in another group #527:
|
||||
if (GVAR(moveUnitsFromGroupOnUnconscious)) then {
|
||||
[_unit, false, "ACE_isUnconscious", side group _unit] call EFUNC(common,switchToGroupSide);
|
||||
};
|
||||
[_unit, false] call EFUNC(common,disableAI);
|
||||
_unit setUnitPos _originalPos; // This is not position but stance (DOWN, MIDDLE, UP)
|
||||
|
||||
_unit setUnconscious false;
|
||||
|
||||
[_unit, "isUnconscious"] call EFUNC(common,unmuteUnit);
|
||||
|
||||
// ensure this statement runs only once
|
||||
_args set [4, true];
|
||||
};
|
||||
};
|
||||
|
||||
if (_parachuteCheck) then {
|
||||
if !(vehicle _unit isKindOf "ParachuteBase") then {
|
||||
[_unit, [_unit] call EFUNC(common,getDeathAnim), 1, true] call EFUNC(common,doAnimation);
|
||||
_args set [5, false];
|
||||
};
|
||||
};
|
||||
|
||||
if (!local _unit) exitWith {
|
||||
TRACE_6("ACE_DEBUG_Unconscious_PFH",_unit, _args, _startingTime, _minWaitingTime, _idPFH, _unit getVariable QGVAR(unconsciousArguments));
|
||||
_args set [3, _minWaitingTime - (CBA_missionTime - _startingTime)];
|
||||
_unit setVariable [QGVAR(unconsciousArguments), _args, true];
|
||||
[_idPFH] call CBA_fnc_removePerFrameHandler;
|
||||
};
|
||||
|
||||
// Ensure we are waiting at least a minimum period before checking if we can wake up the unit again, allows for temp knock outs
|
||||
if ((CBA_missionTime - _startingTime) >= _minWaitingTime) exitWith {
|
||||
TRACE_2("ACE_DEBUG_Unconscious_Temp knock outs",_unit, [_unit] call FUNC(getUnconsciousCondition));
|
||||
if (!([_unit] call FUNC(getUnconsciousCondition))) then {
|
||||
//_unit setVariable ["ACE_isUnconscious", false, true];
|
||||
[QGVAR(MinUnconsciousTimer), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
@ -17,28 +17,30 @@
|
||||
// 0.077 l/kg * 80kg = 6.16l
|
||||
#define DEFAULT_BLOOD_VOLUME 6.0 // in liters
|
||||
|
||||
#define BLOOD_VOLUME_HAS_LOST_SOME 5.700 // lost 5% blood, Class I Hemorrhage
|
||||
#define BLOOD_VOLUME_HAS_LOST_MUCH 5.100 // lost 15% blood, Class II Hemorrhage
|
||||
|
||||
#define BLOOD_VOLUME_UNCONSCIOUS 4.200 // lost 30% blood, Class III Hemorrhage
|
||||
#define BLOOD_VOLUME_DEAD 3.600 // lost 40% blood, Class IV Hemorrhage
|
||||
#define BLOOD_VOLUME_CARDIAC_ARREST 1.2 // TBD
|
||||
#define BLOOD_VOLUME_CLASS_1_HEMORRHAGE 6.000 // lost less than 15% blood, Class I Hemorrhage
|
||||
#define BLOOD_VOLUME_CLASS_2_HEMORRHAGE 5.100 // lost more than 15% blood, Class II Hemorrhage
|
||||
#define BLOOD_VOLUME_CLASS_3_HEMORRHAGE 4.200 // lost more than 30% blood, Class III Hemorrhage
|
||||
#define BLOOD_VOLUME_CLASS_4_HEMORRHAGE 3.600 // lost more than 40% blood, Class IV Hemorrhage
|
||||
|
||||
// IV Change per second calculation:
|
||||
// 250ml should take 60 seconds to fill. 250ml/60s = 4.166ml/s.
|
||||
#define IV_CHANGE_PER_SECOND ([1000, 4.166] select GVAR(advancedIVBags)) // in milliliters per second
|
||||
// 250 ml should take 60 seconds to fill. 250 ml / 60 s ~ 4.1667 ml/s.
|
||||
#define IV_CHANGE_PER_SECOND 4.1667 // in milliliters per second
|
||||
|
||||
// chance per second to get knocked out due to blood loss
|
||||
#define BLOOD_LOSS_KNOCK_OUT_CHANCE 0.1 // 10%
|
||||
// Minimum amount of damage required for penetrating wounds (also minDamage for velocity wounds)
|
||||
#define PENETRATION_THRESHOLD 0.35
|
||||
|
||||
// duration in seconds to stay knocked out due to blood loss
|
||||
#define BLOOD_LOSS_KNOCK_OUT_DURATION (15 + random 20)
|
||||
|
||||
// --- unconsciousness
|
||||
#define DEFAULT_KNOCK_OUT_DELAY (5 + random 10)
|
||||
// To be replaced by a proper blood pressure calculation
|
||||
#define BLOOD_LOSS_KNOCK_OUT_THRESHOLD 0.5 // 50% of cardiac output
|
||||
|
||||
// --- pain
|
||||
#define PAIN_UNCONSCIOUS 0.7
|
||||
#define PAIN_UNCONSCIOUS 0.5
|
||||
|
||||
// duration in seconds to stay knocked out due to pain
|
||||
#define PAIN_KNOCK_OUT_DURATION (15 + random 20)
|
||||
#define PAIN_KNOCK_OUT_DURATION (5 + random 10)
|
||||
|
||||
// Pain reduction per second
|
||||
#define PAIN_REDUCTION_SPEED 0.001
|
||||
|
||||
// Chance to wake up when vitals are stable (checked once every SPONTANEOUS_WAKE_UP_INTERVAL seconds)
|
||||
#define SPONTANEOUS_WAKE_UP_CHANCE 0.1
|
||||
#define SPONTANEOUS_WAKE_UP_INTERVAL 10
|
||||
|
@ -2942,31 +2942,17 @@
|
||||
<Italian>Coefficiente che modifica l'intensità del dolore</Italian>
|
||||
<Japanese>この係数では痛みの強さを変更できます</Japanese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_keepLocalSettingsSynced_DisplayName">
|
||||
<English>Sync status</English>
|
||||
<Russian>Синхронизация статуса</Russian>
|
||||
<Polish>Synchronizuj status</Polish>
|
||||
<Spanish>Sincronizador estado</Spanish>
|
||||
<German>Status synchronisieren</German>
|
||||
<Czech>Synchronizovat status</Czech>
|
||||
<Portuguese>Sincronizar estado</Portuguese>
|
||||
<French>Status de la synchronisation</French>
|
||||
<Hungarian>Szinkronizációs állapot</Hungarian>
|
||||
<Italian>Sincronizza stato</Italian>
|
||||
<Japanese>同期状態</Japanese>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_fullHealLocation_PAK_DisplayName">
|
||||
<English>Full Heal Locations</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_keepLocalSettingsSynced_Description">
|
||||
<English>Keep unit status synced. Recommended on.</English>
|
||||
<Russian>Синхронизировать статус юнитов. Рекомендуется включить.</Russian>
|
||||
<Polish>Utrzymuj synchronizację statusu jednostek. Zalecane zostawienie tej opcji włączonej.</Polish>
|
||||
<Spanish>Mantener el estado de la unidad sincronizado. Recomendado activado</Spanish>
|
||||
<German>Status der Einheit synchron halten. Sollte aktiviert bleiben.</German>
|
||||
<Czech>Udržuje status jednotky synchronizovaný. Doporučeno zapnout.</Czech>
|
||||
<Portuguese>Mater o estado da unidade sincronizado. Recomendado ativado.</Portuguese>
|
||||
<French>Garder l'unité synchronisée, Recommandé sur oui.</French>
|
||||
<Hungarian>Egységállapotok szinkronizálása. Javasolt a bekapcsolása.</Hungarian>
|
||||
<Italian>Mantieni lo stato delle unità sincronizzato. Consigliato attivo.</Italian>
|
||||
<Japanese>ユニット状態の同期を続けます。有効化を推奨。</Japanese>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_fullHealLocation_PAK_Description">
|
||||
<English>Where does the PAK perform a full heal?</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_fieldEffectiveness_PAK_DisplayName">
|
||||
<English>PAK effectiveness</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_fieldEffectiveness_PAK_Description">
|
||||
<English>PAK effectiveness when used outside of medical facilities</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_MedicalSettings_Module_Description">
|
||||
<English>Provides a medical system for both players and AI.</English>
|
||||
|
@ -6,7 +6,7 @@
|
||||
if ((GVAR(enabledFor) == 1) && {!isServer} && {hasInterface}) exitWith {}; // 1: Don't Run on non-hc Clients
|
||||
|
||||
// Only run for AI that does not have to deal with advanced medical
|
||||
if (EGVAR(medical,enableFor) == 1 || {hasInterface && {EGVAR(medical,level) == 2}}) exitWith {};
|
||||
if (EGVAR(medical,enableFor) == 1 || {hasInterface}) exitWith {};
|
||||
|
||||
["ace_firedNonPlayer", {
|
||||
_unit setVariable [QGVAR(lastFired), CBA_missionTime];
|
||||
|
@ -1,229 +1,86 @@
|
||||
// bleeding - maximum possible bleeding rate for a given wound type (0 .. 1)
|
||||
// pain - maximum possible pain level for a given wound type (0 .. 1)
|
||||
|
||||
class ACE_Medical_Injuries {
|
||||
// Defines all the possible injury types for advanced medical
|
||||
// Defines all the possible injury types
|
||||
class wounds {
|
||||
// Source: Scarle
|
||||
// Also called scrapes, they occur when the skin is rubbed away by friction against another rough surface (e.g. rope burns and skinned knees).
|
||||
class Abrasion {
|
||||
name = CSTRING(Abrasion);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.0001;
|
||||
pain = 0.01;
|
||||
causes[] = {"falling", "ropeburn", "vehiclecrash", "unknown"};
|
||||
bleeding = 0.001;
|
||||
pain = 0.4;
|
||||
minDamage = 0.01;
|
||||
class Minor {
|
||||
name = CSTRING(Abrasion_Minor);
|
||||
minDamage = 0.01;
|
||||
maxDamage = 0.2;
|
||||
bleedingRate = 0.0001;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Abrasion_Medium);
|
||||
minDamage = 0.2;
|
||||
maxDamage = 0.3;
|
||||
bleedingRate = 0.00015;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Abrasion_Large);
|
||||
minDamage = 0.3;
|
||||
maxDamage = 0.5;
|
||||
bleedingRate = 0.0002;
|
||||
};
|
||||
maxDamage = 0.30;
|
||||
};
|
||||
// Occur when an entire structure or part of it is forcibly pulled away, such as the loss of a permanent tooth or an ear lobe. Explosions, gunshots, and animal bites may cause avulsions.
|
||||
class Avulsions {
|
||||
name = CSTRING(Avulsion);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.3;
|
||||
causes[] = {"explosive", "vehiclecrash", "grenade", "shell", "bullet", "backblast", "bite"};
|
||||
minDamage = 0.2;
|
||||
class Minor {
|
||||
name = CSTRING(Avulsion_Minor);
|
||||
minDamage = 0.2;
|
||||
maxDamage = 0.3;
|
||||
bleedingRate = 0.01;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Avulsion_Medium);
|
||||
minDamage = 0.3;
|
||||
maxDamage = 0.6;
|
||||
bleedingRate = 0.02;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Avulsion_Large);
|
||||
minDamage = 0.5;
|
||||
bleedingRate = 0.05;
|
||||
};
|
||||
bleeding = 0.5;
|
||||
pain = 1.0;
|
||||
minDamage = 4;
|
||||
causeLimping = 1;
|
||||
};
|
||||
// Also called bruises, these are the result of a forceful trauma that injures an internal structure without breaking the skin. Blows to the chest, abdomen, or head with a blunt instrument (e.g. a football or a fist) can cause contusions.
|
||||
class Contusion {
|
||||
name = CSTRING(Contusion);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.0;
|
||||
pain = 0.05;
|
||||
causes[] = {"bullet", "backblast", "punch", "vehiclecrash", "falling"};
|
||||
minDamage = 0.01;
|
||||
maxDamage = 0.1;
|
||||
class Minor {
|
||||
name = CSTRING(Contusion_Minor);
|
||||
minDamage = 0.01;
|
||||
maxDamage = 0.1;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Contusion_Medium);
|
||||
minDamage = 0.1;
|
||||
maxDamage = 0.15;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Contusion_Large);
|
||||
minDamage = 0.15;
|
||||
maxDamage = 0.2;
|
||||
};
|
||||
bleeding = 0.0;
|
||||
pain = 0.3;
|
||||
minDamage = 0.02;
|
||||
maxDamage = 0.35;
|
||||
};
|
||||
// Occur when a heavy object falls onto a person, splitting the skin and shattering or tearing underlying structures.
|
||||
class CrushWound {
|
||||
name = CSTRING(Crush);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.1;
|
||||
causes[] = {"falling", "vehiclecrash", "punch", "unknown"};
|
||||
bleeding = 0.1;
|
||||
pain = 0.8;
|
||||
minDamage = 0.1;
|
||||
class Minor {
|
||||
name = CSTRING(Crush_Minor);
|
||||
minDamage = 0.1;
|
||||
maxDamage = 0.45;
|
||||
bleedingRate = 0.005;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Crush_Medium);
|
||||
minDamage = 0.4;
|
||||
maxDamage = 0.7;
|
||||
bleedingRate = 0.007;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Crush_Large);
|
||||
minDamage = 0.6;
|
||||
bleedingRate = 0.0095;
|
||||
};
|
||||
causeLimping = 1;
|
||||
};
|
||||
// Slicing wounds made with a sharp instrument, leaving even edges. They may be as minimal as a paper cut or as significant as a surgical incision.
|
||||
class Cut {
|
||||
name = CSTRING(Cut);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.075;
|
||||
causes[] = {"vehiclecrash", "grenade", "explosive", "shell", "backblast", "stab", "unknown"};
|
||||
bleeding = 0.04;
|
||||
pain = 0.1;
|
||||
minDamage = 0.1;
|
||||
class Minor {
|
||||
name = CSTRING(Cut_Minor);
|
||||
minDamage = 0.1;
|
||||
maxDamage = 0.3;
|
||||
bleedingRate = 0.005;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Cut_Medium);
|
||||
minDamage = 0.3;
|
||||
maxDamage = 0.65;
|
||||
bleedingRate = 0.02;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Cut_Large);
|
||||
minDamage = 0.65;
|
||||
bleedingRate = 0.05;
|
||||
};
|
||||
};
|
||||
// Also called tears, these are separating wounds that produce ragged edges. They are produced by a tremendous force against the body, either from an internal source as in childbirth, or from an external source like a punch.
|
||||
class Laceration {
|
||||
name = CSTRING(Laceration);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.075;
|
||||
causes[] = {"vehiclecrash", "punch"};
|
||||
bleeding = 0.05;
|
||||
pain = 0.2;
|
||||
minDamage = 0.01;
|
||||
class Minor {
|
||||
name = CSTRING(Laceration_Minor);
|
||||
minDamage = 0.1;
|
||||
maxDamage = 0.5;
|
||||
bleedingRate = 0.005;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(Laceration_Medium);
|
||||
minDamage = 0.5;
|
||||
maxDamage = 0.7;
|
||||
bleedingRate = 0.01;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(Laceration_Large);
|
||||
minDamage = 0.7;
|
||||
bleedingRate = 0.03;
|
||||
};
|
||||
};
|
||||
// Also called velocity wounds, they are caused by an object entering the body at a high speed, typically a bullet or small peices of shrapnel.
|
||||
class velocityWound {
|
||||
name = CSTRING(VelocityWound);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.2;
|
||||
causes[] = {"bullet", "grenade","explosive", "shell", "unknown"};
|
||||
minDamage = 0.15;
|
||||
class Minor {
|
||||
name = CSTRING(VelocityWound_Minor);
|
||||
minDamage = 0.15;
|
||||
maxDamage = 0.3;
|
||||
bleedingRate = 0.025;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(VelocityWound_Medium);
|
||||
minDamage = 0.3;
|
||||
maxDamage = 0.75;
|
||||
bleedingRate = 0.05;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(VelocityWound_Large);
|
||||
minDamage = 0.75;
|
||||
bleedingRate = 0.1;
|
||||
};
|
||||
bleeding = 1.0;
|
||||
pain = 0.9;
|
||||
minDamage = 0.35;
|
||||
causeLimping = 1;
|
||||
};
|
||||
// Deep, narrow wounds produced by sharp objects such as nails, knives, and broken glass.
|
||||
class punctureWound {
|
||||
name = CSTRING(PunctureWound);
|
||||
selections[] = {"All"};
|
||||
bleedingRate = 0.01;
|
||||
pain = 0.075;
|
||||
causes[] = {"stab", "grenade"};
|
||||
minDamage = 0.01;
|
||||
class Minor {
|
||||
name = CSTRING(PunctureWound_Minor);
|
||||
minDamage = 0.01;
|
||||
maxDamage = 0.5;
|
||||
bleedingRate = 0.01;
|
||||
};
|
||||
class Medium {
|
||||
name = CSTRING(PunctureWound_Medium);
|
||||
minDamage = 0.5;
|
||||
maxDamage = 0.75;
|
||||
bleedingRate = 0.03;
|
||||
};
|
||||
class Large {
|
||||
name = CSTRING(PunctureWound_Large);
|
||||
minDamage = 0.65;
|
||||
bleedingRate = 0.08;
|
||||
};
|
||||
};
|
||||
};
|
||||
class fractures {
|
||||
class Femur {
|
||||
name = CSTRING(Femur);
|
||||
selections[] = {"Head", "Body"};
|
||||
pain = 0.2;
|
||||
causes[] = {"Bullet", "VehicleCrash", "Backblast", "Explosive", "Shell", "Grenade"};
|
||||
minDamage = 0.5;
|
||||
bleeding = 0.1;
|
||||
pain = 0.4;
|
||||
minDamage = 0.02;
|
||||
causeLimping = 1;
|
||||
};
|
||||
};
|
||||
class damageTypes {
|
||||
// thresholds[] {{<min damage>, <max number of wounds>}, {...}}
|
||||
thresholds[] = {{0.1, 1}};
|
||||
selectionSpecific = 1;
|
||||
lethalDamage = 0.01;
|
||||
|
||||
class bullet {
|
||||
// above damage, amount. Put the highest threshold to the left and lower the threshold with the elements to the right of it.
|
||||
@ -243,14 +100,12 @@ class ACE_Medical_Injuries {
|
||||
selectionSpecific = 0;
|
||||
};
|
||||
class vehiclecrash {
|
||||
thresholds[] = {{0.25, 5}, {0.05, 1}};
|
||||
thresholds[] = {{0.5, 5}, {0.3, 2}, {0.05, 1}};
|
||||
selectionSpecific = 0;
|
||||
lethalDamage = 0.2;
|
||||
};
|
||||
class backblast {
|
||||
thresholds[] = {{1, 6}, {0.55, 5}, {0, 2}};
|
||||
selectionSpecific = 0;
|
||||
lethalDamage = 1;
|
||||
};
|
||||
class stab {
|
||||
thresholds[] = {{0.1, 1}};
|
||||
@ -261,9 +116,8 @@ class ACE_Medical_Injuries {
|
||||
selectionSpecific = 1;
|
||||
};
|
||||
class falling {
|
||||
thresholds[] = {{0.1, 1}};
|
||||
thresholds[] = {{0.6, 4}, {0.35, 2}, {0.1, 1}};
|
||||
selectionSpecific = 1;
|
||||
lethalDamage = 0.4;
|
||||
};
|
||||
class ropeburn {
|
||||
thresholds[] = {{0.1, 1}};
|
||||
|
@ -2,8 +2,4 @@
|
||||
PREP(parseConfigForInjuries);
|
||||
PREP(getTypeOfDamage);
|
||||
|
||||
PREP(airwayHandler);
|
||||
PREP(fracturesHandler);
|
||||
PREP(internalInjuriesHandler);
|
||||
PREP(woundsHandler);
|
||||
PREP(woundsHandlerSQF);
|
||||
|
@ -6,18 +6,11 @@ ADDON = false;
|
||||
|
||||
call FUNC(parseConfigForInjuries);
|
||||
|
||||
// decide which woundsHandler to use by whether the extension is present or not
|
||||
if ("ace_medical" callExtension "version" != "") then {
|
||||
DFUNC(woundsHandlerActive) = FUNC(woundsHandler);
|
||||
} else {
|
||||
DFUNC(woundsHandlerActive) = FUNC(woundsHandlerSQF);
|
||||
};
|
||||
|
||||
[QEGVAR(medical_engine,woundReceived), {
|
||||
params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"];
|
||||
|
||||
private _typeOfDamage = _ammo call FUNC(getTypeOfDamage);
|
||||
[_unit, _woundedHitPoint, _receivedDamage, _ammo, _typeOfDamage] call FUNC(woundsHandlerActive); // TODO also support the sqf variant
|
||||
[_unit, _woundedHitPoint, _receivedDamage, _ammo, _typeOfDamage] call FUNC(woundsHandler);
|
||||
|
||||
[_unit, EGVAR(medical,STATE_MACHINE)] call EFUNC(medical,addStateHandler);
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Handling of the airway injuries upon the handleDamage eventhandler.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit That Was Hit <OBJECT>
|
||||
* 1: Name Of Body Part <STRING>
|
||||
* 2: Amount Of Damage <NUMBER>
|
||||
* 3: Shooter or source of the damage <OBJECT>
|
||||
* 4: Type of the damage done <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_bodyPart", "_amountOfDamage", "_sourceOfDamage", "_typeOfDamage"];
|
||||
|
||||
private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
|
||||
|
||||
if (_partIndex > 1) exitWith {};
|
||||
|
||||
if (_amountOfDamage > 0.5) then {
|
||||
if (random(1) >= 0.8) then {
|
||||
if !(_unit getVariable[QGVAR(airwayCollapsed), false]) then {
|
||||
_unit setVariable [QGVAR(airwayCollapsed), true, true];
|
||||
};
|
||||
};
|
||||
};
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Handling of the fracture injuries upon the handleDamage eventhandler.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit That Was Hit <OBJECT>
|
||||
* 1: Name Of Body Part <STRING>
|
||||
* 2: Amount Of Damage <NUMBER>
|
||||
* 3: Shooter or source of the damage <OBJECT>
|
||||
* 4: Type of the damage done <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None <NIL>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_bodyPart", "_amountOfDamage", "_sourceOfDamage", "_typeOfDamage"];
|
||||
|
||||
private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
|
||||
|
||||
private _fractureType = 1;
|
||||
|
||||
if (_amountOfDamage > 0.05) then {
|
||||
// TODO specify fractures based off typeOfInjury details better.
|
||||
switch (_typeOfDamage) do {
|
||||
case "Bullet": {
|
||||
_fractureType = round(random(2));
|
||||
};
|
||||
case "Grenade": {
|
||||
_fractureType = round(random(2));
|
||||
if (_fractureType < 1) then {
|
||||
_fractureType = 1;
|
||||
};
|
||||
};
|
||||
case "Explosive": {
|
||||
_fractureType = round(random(2));
|
||||
if (_fractureType < 1) then {
|
||||
_fractureType = 1;
|
||||
};
|
||||
};
|
||||
case "Shell": {
|
||||
_fractureType = round(random(2));
|
||||
if (_fractureType < 1) then {
|
||||
_fractureType = 1;
|
||||
};
|
||||
};
|
||||
case "Unknown": {
|
||||
_fractureType = round(random(1));
|
||||
};
|
||||
case "VehicleCrash": {
|
||||
_fractureType = round(random(0));
|
||||
};
|
||||
default {
|
||||
_fractureType = round(random(1));
|
||||
};
|
||||
};
|
||||
|
||||
private _fractures = _unit getVariable[QGVAR(fractures), []];
|
||||
private _fractureID = 1;
|
||||
private _amountOf = count _fractures;
|
||||
|
||||
if (_amountOf > 0) then {
|
||||
_fractureID = (_fractures select (_amountOf - 1) select 0) + 1;
|
||||
};
|
||||
|
||||
_fractures pushBack [_fractureID, _fractureType, _partIndex, 1 /* percentage treated */];
|
||||
_unit setVariable [QGVAR(fractures), _fractures, true];
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Handling of the internal injuries upon the handleDamage eventhandler.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit That Was Hit <OBJECT>
|
||||
* 1: Name Of Body Part <STRING>
|
||||
* 2: Amount Of Damage <NUMBER>
|
||||
* 3: Shooter or source of the damage <OBJECT>
|
||||
* 4: Type of the damage done <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_bodyPart", "_amountOfDamage", "_sourceOfDamage", "_typeOfDamage"];
|
||||
|
||||
// private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
|
||||
// TODO implement internal injuries
|
@ -12,55 +12,6 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
private _fnc_getAnyFromConfig = {
|
||||
params ["_config", "_default"];
|
||||
|
||||
if (_default isEqualType []) exitWith {
|
||||
GET_ARRAY(_config,_default)
|
||||
};
|
||||
|
||||
if (_default isEqualType 0) exitWith {
|
||||
GET_NUMBER(_config,_default)
|
||||
};
|
||||
|
||||
if (_default isEqualType "") exitWith {
|
||||
GET_STRING(_config,_default)
|
||||
};
|
||||
|
||||
_default
|
||||
};
|
||||
|
||||
private _fnc_parseSubClassWounds = {
|
||||
params ["_subClass"];
|
||||
|
||||
private _subClassConfig = _entry >> _subClass;
|
||||
|
||||
if (isClass _subClassConfig) exitWith {
|
||||
private _subClassSelections = [_subClassConfig >> "selections", _selections] call _fnc_getAnyFromConfig;
|
||||
private _subClassCauses = [_subClassConfig >> "causes", _causes] call _fnc_getAnyFromConfig;
|
||||
|
||||
if (count _subClassSelections > 0 && {count _subClassCauses > 0}) then {
|
||||
// constructs a type name, such as: 'woundMinor'
|
||||
GVAR(woundClassNames) pushBack (_className + configName _subClassConfig);
|
||||
GVAR(woundsData) pushBack [
|
||||
_classID,
|
||||
_subClassSelections,
|
||||
[_subClassConfig >> "bleedingRate", _bleedingRate] call _fnc_getAnyFromConfig,
|
||||
[_subClassConfig >> "pain", _pain] call _fnc_getAnyFromConfig,
|
||||
[[_subClassConfig >> "minDamage", _minDamage] call _fnc_getAnyFromConfig, [_subClassConfig >> "maxDamage", _maxDamage] call _fnc_getAnyFromConfig],
|
||||
_subClassCauses,
|
||||
[_subClassConfig >> "name", _displayName + " " + _subClass] call _fnc_getAnyFromConfig
|
||||
];
|
||||
|
||||
_classID = _classID + 1;
|
||||
};
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
false
|
||||
};
|
||||
|
||||
private _injuriesConfigRoot = configFile >> "ACE_Medical_Injuries";
|
||||
|
||||
// --- parse wounds
|
||||
@ -74,36 +25,28 @@ private _classID = 0;
|
||||
private _entry = _x;
|
||||
private _className = configName _entry;
|
||||
|
||||
private _selections = GET_ARRAY(_entry >> "selections",[]);
|
||||
private _bleedingRate = GET_NUMBER(_entry >> "bleedingRate",0);
|
||||
private _selections = GET_ARRAY(_entry >> "selections",["All"]);
|
||||
private _bleeding = GET_NUMBER(_entry >> "bleeding",0);
|
||||
private _pain = GET_NUMBER(_entry >> "pain",0);
|
||||
private _minDamage = GET_NUMBER(_entry >> "minDamage",0);
|
||||
private _maxDamage = GET_NUMBER(_entry >> "maxDamage",-1);
|
||||
private _causes = GET_ARRAY(_entry >> "causes",[]);
|
||||
private _displayName = GET_STRING(_entry >> "name",_className); // @todo, don't translate in config
|
||||
private _causeLimping = GET_NUMBER(_entry >> "causeLimping",0);
|
||||
|
||||
// TODO instead of hardcoding minor, medium and large just go through all sub classes recursively until none are found
|
||||
if !("Minor" call _fnc_parseSubClassWounds || "Medium" call _fnc_parseSubClassWounds || "Large" call _fnc_parseSubClassWounds) then {
|
||||
// There were no subclasses, so we will add this one instead.
|
||||
if (count _selections > 0 && {count _causes > 0}) then {
|
||||
GVAR(woundClassNames) pushBack _className;
|
||||
GVAR(woundsData) pushBack [_classID, _selections, _bleedingRate, _pain, [_minDamage, _maxDamage], _causes, _displayName];
|
||||
_classID = _classID + 1;
|
||||
};
|
||||
if (count _causes > 0) then {
|
||||
GVAR(woundClassNames) pushBack _className;
|
||||
GVAR(woundsData) pushBack [_classID, _selections, _bleeding, _pain, [_minDamage, _maxDamage], _causes, _displayName, _causeLimping];
|
||||
_classID = _classID + 1;
|
||||
};
|
||||
} forEach configProperties [_woundsConfig, "isClass _x"];
|
||||
|
||||
// --- parse fractures
|
||||
//GVAR(fractureClassNames) = []; // unused
|
||||
|
||||
// --- parse damage types
|
||||
GVAR(allDamageTypes) = []; // @todo, currently unused by handle damage (was GVAR(allAvailableDamageTypes))
|
||||
GVAR(lethalDamages) = []; // @todo, currently unused by handle damage (was GVAR(minLethalDamages))
|
||||
GVAR(allDamageTypesData) = [] call CBA_fnc_createNamespace;
|
||||
|
||||
// minimum lethal damage collection, mapped to damageTypes
|
||||
private _damageTypesConfig = _injuriesConfigRoot >> "damageTypes";
|
||||
private _lethalDamageDefault = getNumber (_damageTypesConfig >> "lethalDamage");
|
||||
private _thresholdsDefault = getArray (_damageTypesConfig >> "thresholds");
|
||||
private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionSpecific");
|
||||
|
||||
@ -113,7 +56,6 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
|
||||
private _className = configName _entry;
|
||||
|
||||
GVAR(allDamageTypes) pushBack _className;
|
||||
GVAR(lethalDamages) pushBack GET_NUMBER(_entry >> "lethalDamage",_lethalDamageDefault);
|
||||
|
||||
// Check if this type is in the causes of a wound class, if so, we will store the wound types for this damage type
|
||||
private _woundTypes = [];
|
||||
@ -138,7 +80,7 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
|
||||
private _extensionArgs = format [
|
||||
"addDamageType,%1,%2,%3,%4,%5",
|
||||
_className,
|
||||
GVAR(lethalDamages) select _forEachIndex,
|
||||
1, //@todo remove 'minLethalDamage' from extension
|
||||
_minDamageThresholds,
|
||||
_amountThresholds,
|
||||
_selectionSpecific
|
||||
|
@ -36,25 +36,43 @@ private _woundsCreated = [];
|
||||
|
||||
call compile _extensionOutput;
|
||||
|
||||
// todo: Make the pain and bleeding calculations part of the extension again
|
||||
private _painLevel = 0;
|
||||
{
|
||||
_x params ["", "_woundClassIDToAdd", "_bodyPartNToAdd"];
|
||||
_x params ["", "_woundClassIDToAdd", "_bodyPartNToAdd", "", "_bleeding"];
|
||||
|
||||
_foundIndex = -1;
|
||||
{
|
||||
// Check if we have an id of the given class on the given bodypart already
|
||||
if ((_woundClassIDToAdd isEqualTo (_x select 1)) && {_bodyPartNToAdd isEqualTo (_x select 2)}) exitWith {
|
||||
_foundIndex = _forEachIndex;
|
||||
};
|
||||
} forEach _openWounds;
|
||||
|
||||
if (_foundIndex < 0) then {
|
||||
// Since it is a new injury, we will have to add it to the open wounds array to store it
|
||||
_openWounds pushBack _x;
|
||||
// The higher the nastiness likelihood the higher the change to get a painful and bloody wound
|
||||
private _nastinessLikelihood = if (_damage > 1) then {
|
||||
(_damage ^ 0.33)
|
||||
} 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.
|
||||
private _injury = _openWounds select _foundIndex;
|
||||
_injury set [3, (_injury select 3) + 1];
|
||||
(0.1 max _damage)
|
||||
};
|
||||
private _bloodiness = 0.01 + 0.99 * (1 - random[0, 1, 0.9]) ^ (1 / _nastinessLikelihood);
|
||||
private _painfullness = 0.05 + 0.95 * (1 - random[0, 1, 0.5]) ^ (1 / _nastinessLikelihood);
|
||||
|
||||
_bleeding = _bleeding * _bloodiness;
|
||||
|
||||
_x set [4, _bleeding];
|
||||
_x set [5, _damage];
|
||||
|
||||
private _pain = ((GVAR(woundsData) select _woundClassIDToAdd) select 3) * _painfullness;
|
||||
_painLevel = _painLevel max _pain;
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, round(_damage * 100) / 100, _damage > PENETRATION_THRESHOLD, round(_bleeding * 1000) / 1000, round(_pain * 1000) / 1000];
|
||||
#endif
|
||||
|
||||
if (_bodyPartNToAdd == 0 && {_damage > 1}) then {
|
||||
[QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
// todo `forceWalk` based on leg damage
|
||||
private _causeLimping = (GVAR(woundsData) select _woundClassIDToAdd) select 7;
|
||||
if (_causeLimping == 1 && {_damage > 0.3} && {_bodyPartNToAdd > 3}) then {
|
||||
[_unit, true] call EFUNC(medical_engine,setLimping);
|
||||
};
|
||||
|
||||
_openWounds pushBack _x;
|
||||
} forEach _woundsCreated;
|
||||
|
||||
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
|
||||
@ -64,9 +82,10 @@ _unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
|
||||
// Only update if new wounds have been created
|
||||
if (count _woundsCreated > 0) then {
|
||||
_unit setVariable [QEGVAR(medical,lastUniqueWoundID), _woundID, true];
|
||||
[_unit] call EFUNC(medical,handleIncapacitation);
|
||||
};
|
||||
|
||||
[_unit, _painToAdd] call EFUNC(medical,addPain);
|
||||
[_unit, "hit", PAIN_TO_SCREAM(_painToAdd)] call EFUNC(medical_engine,playInjuredSound);
|
||||
[_unit, _painLevel] call EFUNC(medical,adjustPainLevel);
|
||||
[_unit, "hit", PAIN_TO_SCREAM(_painLevel)] call EFUNC(medical_engine,playInjuredSound);
|
||||
|
||||
TRACE_5("exit",_unit, _painToAdd, _unit getVariable QEGVAR(medical,pain), _unit getVariable QEGVAR(medical,openWounds),_woundsCreated);
|
||||
TRACE_5("exit",_unit,_painLevel,_unit getVariable QEGVAR(medical,pain),_unit getVariable QEGVAR(medical,openWounds),_woundsCreated);
|
||||
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal, commy2
|
||||
* Handling of the open wounds & injuries upon the handleDamage eventhandler.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit That Was Hit <OBJECT>
|
||||
* 1: Name Of Body Part <STRING>
|
||||
* 2: Amount Of Damage <NUMBER>
|
||||
* 3: Shooter or source of the damage <OBJECT>
|
||||
* 4: Type of the damage done <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_bodyPart", "_damage", "_typeOfProjectile", "_typeOfDamage"];
|
||||
TRACE_5("start",_unit,_bodyPart,_damage,_typeOfProjectile,_typeOfDamage);
|
||||
|
||||
// Convert the selectionName to a number and ensure it is a valid selection.
|
||||
private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart;
|
||||
if (_bodyPartN < 0) exitWith {};
|
||||
|
||||
if (_typeOfDamage isEqualTo "") then {
|
||||
_typeOfDamage = "unknown";
|
||||
};
|
||||
|
||||
// Get the damage type information. Format: [typeDamage thresholds, selectionSpecific, woundTypes]
|
||||
// WoundTypes are the available wounds for this damage type. Format [[classID, selections, bleedingRate, pain], ..]
|
||||
private _damageTypeInfo = [GVAR(allDamageTypesData) getVariable _typeOfDamage] param [0, [[], false, []]];
|
||||
_damageTypeInfo params ["_thresholds", "_isSelectionSpecific", "_woundTypes"];
|
||||
|
||||
// It appears we are dealing with an unknown type of damage.
|
||||
if (count _woundTypes == 0) then {
|
||||
// grabbing the configuration for unknown damage type
|
||||
_damageTypeInfo = [GVAR(allDamageTypesData) getVariable "unknown"] param [0, [[], false, []]];
|
||||
_woundTypes = _damageTypeInfo select 2;
|
||||
};
|
||||
|
||||
// find the available injuries for this damage type and damage amount
|
||||
private _highestPossibleSpot = -1;
|
||||
private _highestPossibleDamage = -1;
|
||||
private _allPossibleInjuries = [];
|
||||
|
||||
{
|
||||
_x params ["", "_selections", "", "", "_damageExtrema"];
|
||||
_damageExtrema params ["_minDamage", "_maxDamage"];
|
||||
|
||||
// Check if the damage is higher as the min damage for the specific injury
|
||||
if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then {
|
||||
// Check if the injury can be applied to the given selection name
|
||||
if ("All" in _selections || _bodyPart in _selections) then { // @todo, this is case sensitive!
|
||||
|
||||
// Find the wound which has the highest minimal damage, so we can use this later on for adding the correct injuries
|
||||
if (_minDamage > _highestPossibleDamage) then {
|
||||
_highestPossibleSpot = _forEachIndex;
|
||||
_highestPossibleDamage = _minDamage;
|
||||
};
|
||||
|
||||
// Store the valid possible injury for the damage type, damage amount and selection
|
||||
_allPossibleInjuries pushBack _x;
|
||||
};
|
||||
};
|
||||
} forEach _woundTypes;
|
||||
|
||||
// No possible wounds available for this damage type or damage amount.
|
||||
if (_highestPossibleSpot < 0) exitWith {};
|
||||
|
||||
// Administration for open wounds and ids
|
||||
private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []];
|
||||
private _woundID = _unit getVariable [QGVAR(lastUniqueWoundID), 1];
|
||||
|
||||
private _painToAdd = 0;
|
||||
private _woundsCreated = [];
|
||||
|
||||
{
|
||||
if (_x select 0 <= _damage) exitWith {
|
||||
for "_i" from 0 to ((_x select 1)-1) do {
|
||||
|
||||
// Find the injury we are going to add. Format [ classID, allowdSelections, bleedingRate, injuryPain]
|
||||
private _oldInjury = if (random 1 >= 0.85) then {
|
||||
_woundTypes select _highestPossibleSpot
|
||||
} else {
|
||||
selectRandom _allPossibleInjuries
|
||||
};
|
||||
|
||||
_oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain"];
|
||||
|
||||
private _bodyPartNToAdd = [floor random 6, _bodyPartN] select _isSelectionSpecific; // 6 == count ALL_BODY_PARTS
|
||||
|
||||
// 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..
|
||||
private _foundIndex = -1;
|
||||
if (_isSelectionSpecific) then {
|
||||
{
|
||||
// Check if we have an id of the given class on the given bodypart already
|
||||
if ((_woundClassIDToAdd isEqualTo (_x select 1)) && {_bodyPartNToAdd isEqualTo (_x select 2)}) exitWith {
|
||||
_foundIndex = _forEachIndex;
|
||||
};
|
||||
} forEach _openWounds;
|
||||
};
|
||||
|
||||
private _injury = [];
|
||||
if (_foundIndex < 0) then {
|
||||
// Create a new injury. Format [ID, classID, bodypart, percentage treated, bleeding rate]
|
||||
_injury = [_woundID, _woundClassIDToAdd, _bodyPartNToAdd, 1, _injuryBleedingRate];
|
||||
|
||||
// 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.
|
||||
_woundsCreated pushBack _injury;
|
||||
|
||||
// Collect the pain that is caused by this injury
|
||||
_painToAdd = _injuryPain + _painToAdd;
|
||||
};
|
||||
};
|
||||
} forEach _thresholds;
|
||||
|
||||
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true];
|
||||
|
||||
[_unit, _bodyPart] call EFUNC(medical_engine,updateBodyPartVisuals);
|
||||
|
||||
// Only update if new wounds have been created
|
||||
if (count _woundsCreated > 0) then {
|
||||
_unit setVariable [QGVAR(lastUniqueWoundID), _woundID, true];
|
||||
};
|
||||
|
||||
[_unit, _painToAdd] call EFUNC(medical,addPain);
|
||||
[_unit, "hit", PAIN_TO_SCREAM(_painToAdd)] call EFUNC(medical_engine,playInjuredSound);
|
||||
|
||||
TRACE_5("exit",_unit, _painToAdd, _unit getVariable QEGVAR(medical,pain), _unit getVariable QEGVAR(medical,openWounds),_woundsCreated);
|
@ -18,8 +18,8 @@
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
[QGVAR(woundReceived), {
|
||||
diag_log _this;
|
||||
systemChat str _this;
|
||||
//diag_log _this;
|
||||
//systemChat str _this;
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
#endif
|
||||
|
||||
|
@ -104,7 +104,13 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
|
||||
// Check for falling damage.
|
||||
if (_ammo isEqualTo "") then {
|
||||
if (velocity _unit select 2 < -2) then {
|
||||
_woundedHitPoint = selectRandom ["LeftLeg", "RightLeg"];
|
||||
if (_receivedDamage < 0.35) then {
|
||||
// Less than ~ 5 m
|
||||
_woundedHitPoint = selectRandom ["LeftLeg", "RightLeg"];
|
||||
} else {
|
||||
// More than ~ 5 m
|
||||
_woundedHitPoint = selectRandom ["LeftLeg", "RightLeg", "Body", "Head"];
|
||||
};
|
||||
_ammo = "#falling";
|
||||
} else {
|
||||
// Assume collision damage.
|
||||
|
@ -44,22 +44,22 @@ switch (toLower _bodyPart) do {
|
||||
};
|
||||
|
||||
private _openWounds = _unit getVariable QEGVAR(medical,openWounds);
|
||||
private _bloodLossOnAffectedBodyParts = 0;
|
||||
private _damageOnAffectedBodyParts = 0;
|
||||
|
||||
{
|
||||
private _bloodLossOnBodyPart = 0;
|
||||
private _damageOnBodyPart = 0;
|
||||
private _partIndex = ALL_BODY_PARTS find toLower _x;
|
||||
|
||||
{
|
||||
_x params ["", "", "_bodyPartN", "_amountOf", "_percentageOpen"];
|
||||
_x params ["", "", "_bodyPartN", "", "_bleeding", "_damage"];
|
||||
|
||||
if (_bodyPartN isEqualTo _partIndex) then {
|
||||
_bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _percentageOpen);
|
||||
_damageOnBodyPart = _damageOnBodyPart + _damage;
|
||||
};
|
||||
} forEach _openWounds;
|
||||
|
||||
// report maximum of both legs or arms
|
||||
_bloodLossOnAffectedBodyParts = _bloodLossOnAffectedBodyParts max _bloodLossOnBodyPart;
|
||||
_damageOnAffectedBodyParts = _damageOnAffectedBodyParts max _damageOnBodyPart;
|
||||
} forEach _affectedBodyParts;
|
||||
|
||||
[_unit, _bodyPart, _bloodLossOnAffectedBodyParts > 0] call FUNC(damageBodyPart);
|
||||
[_unit, _bodyPart, _damageOnAffectedBodyParts > 0.35] call FUNC(damageBodyPart);
|
||||
|
@ -48,7 +48,7 @@ class CfgVehicles {
|
||||
displayName = ECSTRING(medical,Actions_Medical);
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 0)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,0)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
condition = "true";
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
#include "InteractionBodyParts.hpp"
|
||||
|
@ -2,7 +2,7 @@ class ACE_Head {
|
||||
displayName = ECSTRING(interaction,Head);
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 0)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,0)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,0,_this select 3)] call FUNC(modifyAction));
|
||||
condition = "true";
|
||||
runOnHover = 1;
|
||||
@ -13,7 +13,7 @@ class ACE_Torso {
|
||||
condition = "true";
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 1)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,1)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,1,_this select 3)] call FUNC(modifyAction));
|
||||
showDisabled = 1;
|
||||
priority = 2;
|
||||
@ -23,7 +23,7 @@ class ACE_ArmLeft {
|
||||
displayName = ECSTRING(interaction,ArmLeft);
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 2)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,2)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,2,_this select 3)] call FUNC(modifyAction));
|
||||
condition = "true";
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
@ -32,7 +32,7 @@ class ACE_ArmRight {
|
||||
displayName = ECSTRING(interaction,ArmRight);
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 3)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,3)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,3,_this select 3)] call FUNC(modifyAction));
|
||||
condition = "true";
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
@ -41,7 +41,7 @@ class ACE_LegLeft {
|
||||
displayName = ECSTRING(interaction,LegLeft);
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 4)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,4)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,4,_this select 3)] call FUNC(modifyAction));
|
||||
condition = "true";
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
@ -50,7 +50,7 @@ class ACE_LegRight {
|
||||
displayName = ECSTRING(interaction,LegRight);
|
||||
runOnHover = 1;
|
||||
exceptions[] = {"isNotInside", "isNotSitting"};
|
||||
statement = QUOTE([ARR_3(_target, true, 5)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
statement = QUOTE([ARR_3(_target,1,5)] call EFUNC(medical_treatment,displayPatientInformation));
|
||||
modifierFunction = QUOTE([ARR_4(_target,_player,5,_this select 3)] call FUNC(modifyAction));
|
||||
condition = "true";
|
||||
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
|
||||
|
@ -7,7 +7,7 @@ GVAR(lastOpenedOn) = -1;
|
||||
GVAR(pendingReopen) = false;
|
||||
|
||||
["ace_settingsInitialized", {
|
||||
if (EGVAR(medical,level) > 0 && {EGVAR(medical,menuTypeStyle) == 0}) then {
|
||||
if (EGVAR(medical,menuTypeStyle) == 0) then {
|
||||
[] call FUNC(collectActions3D);
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
@ -4,8 +4,9 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: selection bloodloss <ARRAY>
|
||||
* 1: damaged (array of bools) <ARRAY>
|
||||
* 2: display <DISPLAY>
|
||||
* 1: selection damage <ARRAY>
|
||||
* 2: selection torniquet <ARRAY>
|
||||
* 3: display <DISPLAY>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
@ -17,7 +18,7 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_selectionBloodLoss", "_damaged", "_display"];
|
||||
params ["_selectionBloodLoss", "_selectionDamage", "_selectionTourniquet", "_display"];
|
||||
|
||||
// Handle the body image coloring
|
||||
private _availableSelections = [50, 51, 52, 53, 54, 55];
|
||||
@ -26,16 +27,22 @@ private _availableSelections = [50, 51, 52, 53, 54, 55];
|
||||
private _green = 1;
|
||||
private _blue = 1;
|
||||
|
||||
if (_x > 0) then {
|
||||
if (_damaged select _forEachIndex) then {
|
||||
_green = (0.9 - _x) max 0;
|
||||
private _torniquet = _selectionTourniquet select _forEachIndex;
|
||||
if (_torniquet > 0) then {
|
||||
_red = 0.77;
|
||||
_green = 0.51;
|
||||
_blue = 0.08;
|
||||
} else {
|
||||
private _bloodLoss = _selectionBloodLoss select _forEachIndex;
|
||||
if (_bloodLoss > 0) then {
|
||||
_green = 0 max (0.9 - _bloodLoss);
|
||||
_blue = _green;
|
||||
} else {
|
||||
_green = (0.9 - _x) max 0;
|
||||
private _damage = _selectionDamage select _forEachIndex;
|
||||
_green = 0 max (0.9 - _damage);
|
||||
_red = _green;
|
||||
//_blue = _green;
|
||||
};
|
||||
};
|
||||
|
||||
(_display displayCtrl (_availableSelections select _forEachIndex)) ctrlSetTextColor [_red, _green, _blue, 1.0];
|
||||
} forEach _selectionBloodLoss;
|
||||
(_display displayCtrl _x) ctrlSetTextColor [_red, _green, _blue, 1.0];
|
||||
} forEach _availableSelections;
|
||||
|
@ -18,15 +18,13 @@
|
||||
|
||||
params ["_target", "_display"];
|
||||
|
||||
private ["_allInjuryTexts", "_bandagedwounds", "_damaged", "_genericMessages", "_logs", "_openWounds", "_part", "_partText", "_pointDamage", "_selectionBloodLoss", "_selectionN", "_severity", "_totalIvVolume", "_triageStatus"];
|
||||
|
||||
if (isNil "_display" || {isNull _display}) exitWith {ERROR("No display");};
|
||||
|
||||
_selectionN = GVAR(selectedBodyPart);
|
||||
private _selectionN = GVAR(selectedBodyPart);
|
||||
if (_selectionN < 0 || {_selectionN > 5}) exitWith {};
|
||||
|
||||
_genericMessages = [];
|
||||
_partText = [ELSTRING(medical,Head), ELSTRING(medical,Torso), ELSTRING(medical,LeftArm) ,ELSTRING(medical,RightArm) ,ELSTRING(medical,LeftLeg), ELSTRING(medical,RightLeg)] select _selectionN;
|
||||
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 {
|
||||
@ -45,7 +43,7 @@ if (_target getVariable [QEGVAR(medical,hasPain), false]) then {
|
||||
_genericMessages pushBack [localize ELSTRING(medical,Status_Pain), [1, 1, 1, 1]];
|
||||
};
|
||||
|
||||
_totalIvVolume = 0;
|
||||
private _totalIvVolume = 0;
|
||||
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
|
||||
{
|
||||
_x params ["_bagVolumeRemaining"];
|
||||
@ -56,96 +54,64 @@ if (_totalIvVolume >= 1) then {
|
||||
_genericMessages pushBack [format [localize ELSTRING(medical,receivingIvVolume), floor _totalIvVolume], [1, 1, 1, 1]];
|
||||
};
|
||||
|
||||
_damaged = [false, false, false, false, false, false];
|
||||
_selectionBloodLoss = [0, 0, 0, 0, 0, 0];
|
||||
private _selectionTourniquet = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]];
|
||||
private _selectionBloodLoss = [0, 0, 0, 0, 0, 0];
|
||||
private _selectionDamage = [0, 0, 0, 0, 0, 0];
|
||||
private _allInjuryTexts = [];
|
||||
|
||||
_allInjuryTexts = [];
|
||||
if (EGVAR(medical,level) >= 2) then { // && {([_target] call EFUNC(medical,hasMedicalEnabled))}
|
||||
_openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
|
||||
private "_amountOf";
|
||||
{
|
||||
_amountOf = _x select 3;
|
||||
// Find how much this bodypart is bleeding
|
||||
{
|
||||
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"];
|
||||
_selectionBloodLoss set [_bodyPartN, (_selectionBloodLoss select _bodyPartN) + (20 * (_bleeding * _amountOf))];
|
||||
_selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage];
|
||||
if (_selectionN == _bodyPartN) 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 {
|
||||
_damaged set [_x select 2, true];
|
||||
_selectionBloodLoss set [_x select 2, (_selectionBloodLoss select (_x select 2)) + (20 * ((_x select 4) * _amountOf))];
|
||||
|
||||
if (_selectionN == (_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 >= 1) then {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format["%2x %1", (EGVAR(medical,AllWoundInjuryTypes) select (_x select 1)) select 6, ceil _amountOf], [1,1,1,1]];
|
||||
} else {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format["Partial %1", (EGVAR(medical,AllWoundInjuryTypes) select (_x select 1)) select 6], [1,1,1,1]];
|
||||
};
|
||||
if (_amountOf >= 1) then {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format["%2x %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6, ceil _amountOf], [1,1,1,1]];
|
||||
} else {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format["Partial %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6], [1,1,1,1]];
|
||||
};
|
||||
};
|
||||
} forEach _openWounds;
|
||||
|
||||
_bandagedwounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
|
||||
{
|
||||
_amountOf = _x select 3;
|
||||
// Find how much this bodypart is bleeding
|
||||
if !(_damaged select (_x select 2)) then {
|
||||
_selectionBloodLoss set [_x select 2, (_selectionBloodLoss select (_x select 2)) + (20 * ((_x select 4) * _amountOf))];
|
||||
};
|
||||
if (_selectionN == (_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 ["[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;
|
||||
} else {
|
||||
|
||||
// Add all bleeding from wounds on selection
|
||||
_openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
|
||||
private "_amountOf";
|
||||
{
|
||||
_amountOf = _x select 3;
|
||||
// Find how much this bodypart is bleeding
|
||||
if (_amountOf > 0) then {
|
||||
_damaged set [_x select 2, true];
|
||||
_selectionBloodLoss set [_x select 2, (_selectionBloodLoss select (_x select 2)) + (20 * ((_x select 4) * _amountOf))];
|
||||
};
|
||||
} forEach _openWounds;
|
||||
|
||||
_bandagedwounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
|
||||
{
|
||||
_amountOf = _x select 3;
|
||||
// Find how much this bodypart is bleeding
|
||||
if !(_damaged select (_x select 2)) then {
|
||||
_selectionBloodLoss set [_x select 2, (_selectionBloodLoss select (_x select 2)) + (20 * ((_x select 4) * _amountOf))];
|
||||
};
|
||||
} forEach _bandagedwounds;
|
||||
|
||||
private _bloodLossOnSelection = _selectionBloodLoss select _selectionN;
|
||||
if (_bloodLossOnSelection > 0) then {
|
||||
private _severity = switch (true) do {
|
||||
case (_bloodLossOnSelection > 0.5): {localize ELSTRING(medical,HeavilyWounded)};
|
||||
case (_bloodLossOnSelection > 0.1): {localize ELSTRING(medical,LightlyWounded)};
|
||||
default {localize ELSTRING(medical,VeryLightlyWounded)};
|
||||
};
|
||||
private _part = localize ([
|
||||
ELSTRING(medical,Head),
|
||||
ELSTRING(medical,Torso),
|
||||
ELSTRING(medical,LeftArm),
|
||||
ELSTRING(medical,RightArm),
|
||||
ELSTRING(medical,LeftLeg),
|
||||
ELSTRING(medical,RightLeg)
|
||||
] select _selectionN);
|
||||
_allInjuryTexts pushBack [format ["%1 %2", _severity, toLower _part], [1,1,1,1]];
|
||||
};
|
||||
};
|
||||
} forEach (_target getVariable [QEGVAR(medical,openWounds), []]);
|
||||
|
||||
[_selectionBloodLoss, _damaged, _display] call FUNC(updateBodyImage);
|
||||
{
|
||||
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"];
|
||||
_selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage];
|
||||
if (_selectionN == _bodyPartN) 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_damage,woundsData) select _woundClassID) select 6, ceil _amountOf], [0.88,0.7,0.65,1]];
|
||||
} else {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format ["[B] Partial %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6], [0.88,0.7,0.65,1]];
|
||||
};
|
||||
};
|
||||
};
|
||||
} forEach (_target getVariable [QEGVAR(medical,bandagedWounds), []]);
|
||||
|
||||
{
|
||||
_x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"];
|
||||
_selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage];
|
||||
if (_selectionN == _bodyPartN) 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 ["[S] %2x %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6, ceil _amountOf], [0.7,0.7,0.7,1]];
|
||||
} else {
|
||||
// TODO localization
|
||||
_allInjuryTexts pushBack [format ["[S] Partial %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6], [0.7,0.7,0.7,1]];
|
||||
};
|
||||
};
|
||||
};
|
||||
} forEach (_target getVariable [QEGVAR(medical,stitchedWounds), []]);
|
||||
|
||||
[_selectionBloodLoss, _selectionDamage, _selectionTourniquet, _display] call FUNC(updateBodyImage);
|
||||
[_display, _genericMessages, _allInjuryTexts] call FUNC(updateInformationLists);
|
||||
|
||||
[_display, _target getVariable [QEGVAR(medical,logFile_activity_view), []]] call FUNC(updateActivityLog);
|
||||
|
@ -13,7 +13,6 @@ class GVAR(Actions) {
|
||||
treatmentTimeSelfCoef = 1;
|
||||
items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}};
|
||||
condition = QUOTE(!EGVAR(medical,advancedBandages));
|
||||
patientStateCondition = 0;
|
||||
itemConsumed = 1;
|
||||
callbackSuccess = QFUNC(treatmentBandage);
|
||||
callbackFailure = "";
|
||||
@ -76,7 +75,7 @@ class GVAR(Actions) {
|
||||
displayNameProgress = ECSTRING(medical,Applying_Tourniquet);
|
||||
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
|
||||
items[] = {"ACE_tourniquet"};
|
||||
treatmentTime = 4;
|
||||
treatmentTime = 5;
|
||||
callbackSuccess = QFUNC(treatmentTourniquet);
|
||||
condition = QUOTE(EGVAR(medical,advancedBandages) && {!([ARR_2(_target,_bodyPart)] call EFUNC(medical,hasTourniquetAppliedTo))});
|
||||
litter[] = {};
|
||||
@ -97,7 +96,7 @@ class GVAR(Actions) {
|
||||
category = "medication";
|
||||
items[] = {"ACE_morphine"};
|
||||
condition = "";
|
||||
treatmentTime = 10;
|
||||
treatmentTime = 9;
|
||||
callbackSuccess = QFUNC(treatmentMedication);
|
||||
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_morphine"}} };
|
||||
@ -106,12 +105,14 @@ class GVAR(Actions) {
|
||||
class Adenosine: Morphine {
|
||||
displayName = ECSTRING(medical,Inject_Adenosine);
|
||||
displayNameProgress = ECSTRING(medical,Injecting_Adenosine);
|
||||
condition = QEGVAR(medical,advancedMedication);
|
||||
items[] = {"ACE_adenosine"};
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_adenosine"}} };
|
||||
};
|
||||
class Atropine: Morphine {
|
||||
displayName = ECSTRING(medical,Inject_Atropine);
|
||||
displayNameProgress = ECSTRING(medical,Injecting_Atropine);
|
||||
condition = QEGVAR(medical,advancedMedication);
|
||||
items[] = {"ACE_atropine"};
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_atropine"}} };
|
||||
};
|
||||
@ -205,6 +206,7 @@ class GVAR(Actions) {
|
||||
class CheckBloodPressure: CheckPulse {
|
||||
displayName = ECSTRING(medical,Actions_CheckBloodPressure);
|
||||
displayNameProgress = ECSTRING(medical,Check_Bloodpressure_Content);
|
||||
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
|
||||
callbackSuccess = QFUNC(actionCheckBloodPressure);
|
||||
};
|
||||
class CheckResponse: CheckPulse {
|
||||
@ -258,48 +260,42 @@ class GVAR(Actions) {
|
||||
litter[] = {};
|
||||
};
|
||||
|
||||
/*
|
||||
class Advanced {
|
||||
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 = QUOTE(count (_target getVariable [ARR_2('EGVAR(medical,bandagedWounds)',[])]) * 5);
|
||||
callbackSuccess = "";
|
||||
callbackProgress = QFUNC(treatmentSurgicalKit_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(_target call FUNC(treatmentFullHealTreatmentTime));
|
||||
callbackSuccess = QFUNC(treatmentFullHeal);
|
||||
itemConsumed = QEGVAR(medical,consumeItem_PAK);
|
||||
animationPatient = "";
|
||||
animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback";
|
||||
animationCaller = "AinvPknlMstpSlayW[wpn]Dnon_medicOther";
|
||||
animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther";
|
||||
animationCallerSelf = "";
|
||||
animationCallerSelfProne = "";
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"}},
|
||||
{"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
|
||||
{"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
|
||||
{"All", "_bloodLossOnBodyPart <= 0", {"ACE_MedicalLitter_clean"}}
|
||||
};
|
||||
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);
|
||||
treatmentTime = QUOTE(count (_target getVariable [ARR_2('EGVAR(medical,bandagedWounds)',[])]) * 5);
|
||||
callbackSuccess = "";
|
||||
callbackProgress = QFUNC(treatmentSurgicalKit_onProgress);
|
||||
itemConsumed = QEGVAR(medical,consumeItem_SurgicalKit);
|
||||
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"} }};
|
||||
};
|
||||
class PersonalAidKit: BasicBandage {
|
||||
displayName = ECSTRING(medical,Use_Aid_Kit);
|
||||
displayNameProgress = ECSTRING(medical,TreatmentAction);
|
||||
category = "advanced";
|
||||
condition = QUOTE(_target call EFUNC(medical,isInStableCondition));
|
||||
items[] = {"ACE_personalAidKit"};
|
||||
treatmentLocations[] = {QEGVAR(medical,useLocation_PAK)};
|
||||
requiredMedic = QEGVAR(medical,medicSetting_PAK);
|
||||
treatmentTime = QUOTE(_target call FUNC(treatmentFullHealTreatmentTime));
|
||||
callbackSuccess = QFUNC(treatmentFullHeal);
|
||||
itemConsumed = QEGVAR(medical,consumeItem_PAK);
|
||||
animationPatient = "";
|
||||
animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback";
|
||||
animationCaller = "AinvPknlMstpSlayW[wpn]Dnon_medicOther";
|
||||
animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther";
|
||||
animationCallerSelf = "";
|
||||
animationCallerSelfProne = "";
|
||||
litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"}},
|
||||
{"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
|
||||
{"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
|
||||
{"All", "_bloodLossOnBodyPart <= 0", {"ACE_MedicalLitter_clean"}}
|
||||
};
|
||||
};
|
||||
*/
|
||||
};
|
||||
|
@ -75,18 +75,6 @@ if (isText (_config >> "condition")) then {
|
||||
|
||||
if !(_condition) exitWith {false};
|
||||
|
||||
private _patientStateCondition = 0;
|
||||
|
||||
if (isNumber (_config >> "patientStateCondition")) then {
|
||||
_patientStateCondition = getNumber (_config >> "patientStateCondition");
|
||||
} else {
|
||||
if (isText (_config >> "patientStateCondition")) then {
|
||||
_patientStateCondition = missionNamespace getVariable [getText (_config >> "patientStateCondition"), 0];
|
||||
};
|
||||
};
|
||||
|
||||
if (_patientStateCondition == 1 && {!([_target] call EFUNC(medical,isInStableCondition))}) exitWith {false};
|
||||
|
||||
// check allowed locations
|
||||
private _locations = getArray (_config >> "treatmentLocations") apply {toLower _x};
|
||||
|
||||
|
@ -20,38 +20,19 @@ _unit removeItems "FirstAidKit";
|
||||
private _countMedikit = {_x == "Medikit"} count items _unit;
|
||||
_unit removeItems "Medikit";
|
||||
|
||||
if (EGVAR(medical,level) >= 2) then {
|
||||
// --- advanced
|
||||
for "" from 1 to _countFirstAidKit do {
|
||||
_unit addItem "ACE_fieldDressing";
|
||||
_unit addItem "ACE_packingBandage";
|
||||
_unit addItem "ACE_morphine";
|
||||
_unit addItem "ACE_tourniquet";
|
||||
};
|
||||
|
||||
for "" from 1 to _countMedikit do {
|
||||
_unit addItemToBackpack "ACE_fieldDressing";
|
||||
_unit addItemToBackpack "ACE_packingBandage";
|
||||
_unit addItemToBackpack "ACE_packingBandage";
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_morphine";
|
||||
_unit addItemToBackpack "ACE_salineIV_250";
|
||||
_unit addItemToBackpack "ACE_tourniquet";
|
||||
};
|
||||
} else {
|
||||
// --- basic
|
||||
for "" from 1 to _countFirstAidKit do {
|
||||
_unit addItem "ACE_fieldDressing";
|
||||
_unit addItem "ACE_fieldDressing";
|
||||
_unit addItem "ACE_morphine";
|
||||
};
|
||||
|
||||
for "" from 1 to _countMedikit do {
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_bloodIV";
|
||||
_unit addItemToBackpack "ACE_bloodIV";
|
||||
};
|
||||
for "_i" from 1 to _countFirstAidKit do {
|
||||
_unit addItem "ACE_fieldDressing";
|
||||
_unit addItem "ACE_packingBandage";
|
||||
_unit addItem "ACE_morphine";
|
||||
_unit addItem "ACE_tourniquet";
|
||||
};
|
||||
|
||||
for "_i" from 1 to _countMedikit do {
|
||||
_unit addItemToBackpack "ACE_fieldDressing";
|
||||
_unit addItemToBackpack "ACE_packingBandage";
|
||||
_unit addItemToBackpack "ACE_packingBandage";
|
||||
_unit addItemToBackpack "ACE_epinephrine";
|
||||
_unit addItemToBackpack "ACE_morphine";
|
||||
_unit addItemToBackpack "ACE_salineIV_250";
|
||||
_unit addItemToBackpack "ACE_tourniquet";
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Show <BOOL> (default: true)
|
||||
* 1: Show <NUMBER> (default: 0)
|
||||
* 2: Selection <NUMBER> (default: 0)
|
||||
*
|
||||
* ReturnValue:
|
||||
@ -16,15 +16,12 @@
|
||||
#include "script_component.hpp"
|
||||
#define MAX_DISTANCE 10
|
||||
|
||||
// Exit for basic medical
|
||||
if (EGVAR(medical,level) < 2) exitWith {};
|
||||
|
||||
params ["_target", ["_show", true], ["_selectionN", 0]];
|
||||
params ["_target", ["_show", 0], ["_selectionN", 0]];
|
||||
|
||||
GVAR(currentSelectedSelectionN) = [0, _selectionN] select (IS_SCALAR(_selectionN));
|
||||
GVAR(displayPatientInformationTarget) = [ObjNull, _target] select _show;
|
||||
|
||||
if (_show) then {
|
||||
if (_show == 1) then {
|
||||
("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutRsc [QGVAR(DisplayInformation),"PLAIN"];
|
||||
|
||||
[{
|
||||
@ -94,10 +91,10 @@ if (_show) 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]];
|
||||
_allInjuryTexts pushback [format["%2x %1", (EGVAR(medical_damage,woundsData) 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]];
|
||||
_allInjuryTexts pushback [format["Partial %1", (EGVAR(medical_damage,woundsData) select _x1) select 6], [1,1,1,1]];
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -115,10 +112,10 @@ if (_show) then {
|
||||
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]];
|
||||
_allInjuryTexts pushback [format["[B] %2x %1", (EGVAR(medical_damage,woundsData) 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]];
|
||||
_allInjuryTexts pushback [format["[B] Partial %1", (EGVAR(medical_damage,woundsData) select (_x select 1)) select 6], [0.88,0.7,0.65,1]];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -74,8 +74,9 @@ private _bandagedInjury = [];
|
||||
} 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];
|
||||
// [ID, classID, bodypart, percentage treated, bloodloss, damage]
|
||||
_bandagedInjury = +_injury;
|
||||
_bandagedInjury set [3, _impact];
|
||||
_bandagedWounds pushBack _bandagedInjury;
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ if (!_foundEntry) then {
|
||||
|
||||
|
||||
private _usedMeds = _target getVariable [_variable, 0];
|
||||
if (_usedMeds >= floor (_maxDosage + round(random(2))) && _maxDosage >= 1 && GVAR(enableOverdosing)) then {
|
||||
if (_usedMeds >= floor (_maxDosage + round(random(2))) && _maxDosage >= 1) then {
|
||||
[_target] call EFUNC(medical,setDead);
|
||||
};
|
||||
|
||||
@ -58,7 +58,7 @@ private _hasOverDosed = 0;
|
||||
} forEach _allUsedMedication;
|
||||
} forEach _incompatabileMeds;
|
||||
|
||||
if (_hasOverDosed > 0 && GVAR(enableOverdosing)) then {
|
||||
if (_hasOverDosed > 0) then {
|
||||
private _medicationConfig = (configFile >> "ace_medical_treatment" >> "Medication");
|
||||
private _onOverDose = getText (_medicationConfig >> "onOverDose");
|
||||
if (isClass (_medicationConfig >> _className)) then {
|
||||
|
@ -156,6 +156,8 @@ if (isNumber (_config >> "treatmentTime")) then {
|
||||
};
|
||||
TRACE_1("",_treatmentTime);
|
||||
|
||||
if (_treatmentTime == 0) exitWith { false };
|
||||
|
||||
// speed up animation depending on treatment time
|
||||
if (!isNil "_animDuration") then {
|
||||
[QEGVAR(common,setAnimSpeedCoef), [_caller, _animDuration / _treatmentTime]] call CBA_fnc_globalEvent;
|
||||
|
@ -99,96 +99,9 @@ _openWounds set [_mostEffectiveSpot, _mostEffectiveInjury];
|
||||
|
||||
_target setVariable [QEGVAR(medical,openWounds), _openWounds, true];
|
||||
|
||||
[_target, _bodyPart] call EFUNC(medical_engine,updateBodyPartVisuals);
|
||||
|
||||
// Handle the reopening of bandaged wounds
|
||||
if (_impact > 0 && {EGVAR(medical,level) >= 2} && {EGVAR(medical,enableAdvancedWounds)}) then {
|
||||
if (_impact > 0 && {EGVAR(medical,enableAdvancedWounds)}) then {
|
||||
[_target, _impact, _partIndex, _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 _leftArmWounds = 0;
|
||||
private _leftLegWounds = 0;
|
||||
private _rightArmWounds = 0;
|
||||
private _rightLegWounds = 0;
|
||||
|
||||
// Loop through all current wounds and add up the number of unbandaged wounds on each body part.
|
||||
{
|
||||
_x params ["", "", "_partIndex", "_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 (_partIndex) do {
|
||||
// Head
|
||||
case 0: {
|
||||
_headWounds = _headWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
|
||||
// Body
|
||||
case 1: {
|
||||
_bodyWounds = _bodyWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
|
||||
// Left Arm
|
||||
case 2: {
|
||||
_leftArmWounds = _leftArmWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
|
||||
// Right Arm
|
||||
case 3: {
|
||||
_rightArmWounds = _rightArmWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
|
||||
// Left Leg
|
||||
case 4: {
|
||||
_leftLegWounds = _leftLegWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
|
||||
// Right Leg
|
||||
case 5: {
|
||||
_rightLegWounds = _rightLegWounds + (_numOpenWounds * _bloodLoss);
|
||||
};
|
||||
};
|
||||
} forEach _currentWounds;
|
||||
|
||||
// ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"]
|
||||
private _bodyStatus = _target getVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0]];
|
||||
|
||||
// Any body part that has no wounds is healed to full health
|
||||
if (_headWounds == 0) then {
|
||||
_bodyStatus set [0, 0];
|
||||
};
|
||||
if (_bodyWounds == 0) then {
|
||||
_bodyStatus set [1, 0];
|
||||
};
|
||||
if (_leftArmWounds == 0) then {
|
||||
_bodyStatus set [2, 0];
|
||||
};
|
||||
if (_rightArmWounds == 0) then {
|
||||
_bodyStatus set [3, 0];
|
||||
};
|
||||
if (_leftLegWounds == 0) then {
|
||||
_bodyStatus set [4, 0];
|
||||
};
|
||||
if (_rightLegWounds == 0) then {
|
||||
_bodyStatus set [5, 0];
|
||||
};
|
||||
|
||||
_target setVariable [QEGVAR(medical,bodyPartStatus), _bodyStatus, true];
|
||||
|
||||
//[_target] call EFUNC(medical_damage,setDamage);
|
||||
};
|
||||
|
||||
true
|
||||
|
@ -24,10 +24,11 @@ if (_target getVariable [QEGVAR(medical,inReviveState), false]) then {
|
||||
};
|
||||
};
|
||||
|
||||
if (EGVAR(medical,level) > 1 && {(random 1) >= 0.6}) then {
|
||||
if ({(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]];
|
||||
[QGVAR(CPRSucceeded), _target] call CBA_fnc_localEvent;
|
||||
};
|
||||
|
||||
[_target, "activity", ELSTRING(medical,Activity_CPR), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog);
|
||||
|
@ -15,7 +15,42 @@
|
||||
|
||||
params ["_caller", "_target"];
|
||||
|
||||
if (alive _target) exitWith {
|
||||
if (!alive _target) exitWith {};
|
||||
|
||||
private _fullHealLocation = EGVAR(medical,fullHealLocation_PAK);
|
||||
private _partialHeal = _fullHealLocation > 0; // Full heal not everywhere
|
||||
|
||||
if (_partialHeal) then {
|
||||
private _medFacility = ([_caller] call EFUNC(medical,isInMedicalFacility)) || {[_target] call EFUNC(medical,isInMedicalFacility)};
|
||||
private _medVeh = ([_caller] call EFUNC(medical,isInMedicalVehicle)) || {[_target] call EFUNC(medical,isInMedicalVehicle)};
|
||||
switch (_fullHealLocation) do {
|
||||
case 1: { _partialHeal = !_medFacility; };
|
||||
case 2: { _partialHeal = !_medVeh; };
|
||||
case 3: { _partialHeal = !_medFacility && {!_medVeh}; };
|
||||
};
|
||||
};
|
||||
|
||||
if (_partialHeal) then {
|
||||
private _partialHealCounter = _target getVariable [QGVAR(partialHealCounter), 0];
|
||||
_partialHealCounter = _partialHealCounter + 1;
|
||||
_target setVariable [QGVAR(partialHealCounter), _partialHealCounter, true];
|
||||
|
||||
private _effectiveness = (0 max EGVAR(medical,fieldEffectiveness_PAK) min 1) ^ _partialHealCounter;
|
||||
private _persistentDamage = 1 - _effectiveness;
|
||||
|
||||
private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
|
||||
private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
|
||||
private _stitchedWounds = _target getVariable [QEGVAR(medical,stitchedWounds), []];
|
||||
{
|
||||
_x params ["", "", "", "", "_bleeding", "_damage"];
|
||||
_x set [6, _damage min _persistentDamage];
|
||||
} forEach (_openWounds + _bandagedWounds + _stitchedWounds);
|
||||
|
||||
// todo: only reset limping if leg damage was reduced enough
|
||||
[_unit, false] call EFUNC(medical_engine,setLimping);
|
||||
|
||||
_target setDamage ((damage _target) min _persistentDamage);
|
||||
} else {
|
||||
_target setVariable [QEGVAR(medical,pain), 0, true];
|
||||
_target setVariable [QEGVAR(medical,morphine), 0, true];
|
||||
_target setVariable [QEGVAR(medical,bloodVolume), DEFAULT_BLOOD_VOLUME, true];
|
||||
@ -26,7 +61,7 @@ if (alive _target) exitWith {
|
||||
// wounds and injuries
|
||||
_target setVariable [QEGVAR(medical,openWounds), [], true];
|
||||
_target setVariable [QEGVAR(medical,bandagedWounds), [], true];
|
||||
_target setVariable [QEGVAR(medical,internalWounds), [], true];
|
||||
_target setVariable [QEGVAR(medical,stitchedWounds), [], true];
|
||||
|
||||
// vitals
|
||||
_target setVariable [QEGVAR(medical,heartRate), 80];
|
||||
@ -34,30 +69,22 @@ if (alive _target) exitWith {
|
||||
_target setVariable [QEGVAR(medical,bloodPressure), [80, 120]];
|
||||
_target setVariable [QEGVAR(medical,peripheralResistance), 100];
|
||||
|
||||
// fractures
|
||||
_target setVariable [QEGVAR(medical,fractures), []];
|
||||
|
||||
// IVs
|
||||
_target setVariable [QEGVAR(medical,ivBags), nil, true];
|
||||
|
||||
// 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,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];
|
||||
|
||||
_target setVariable [QGVAR(partialHealCounter), 0, true];
|
||||
|
||||
// medication
|
||||
private _allUsedMedication = _target getVariable [QEGVAR(medical,allUsedMedication), []];
|
||||
|
||||
@ -65,9 +92,13 @@ if (alive _target) exitWith {
|
||||
_target setVariable [_x select 0, nil];
|
||||
} forEach _allUsedMedication;
|
||||
|
||||
[_unit, false] call EFUNC(medical_engine,setLimping);
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
[QEGVAR(medical,FullHeal), _target] call CBA_fnc_localEvent;
|
||||
|
||||
[_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
|
||||
|
@ -32,7 +32,7 @@ if !(EGVAR(medical,advancedMedication)) exitWith {
|
||||
};
|
||||
|
||||
if (_className == "Epinephrine") exitWith {
|
||||
[_target, false] call EFUNC(medical,setUnconscious);
|
||||
[QEGVAR(medical,WakeUp), _target] call CBA_fnc_localEvent;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -20,14 +20,17 @@ params ["_args", "_elapsedTime", "_totalTime"];
|
||||
_args params ["_caller", "_target"];
|
||||
|
||||
private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []];
|
||||
private _stitchedWounds = _target getVariable [QEGVAR(medical,stitchedWounds), []];
|
||||
|
||||
//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;
|
||||
private _treatedWound = _bandagedWounds deleteAt 0;
|
||||
_stitchedWounds pushBack _treatedWound;
|
||||
_target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true];
|
||||
_target setVariable [QEGVAR(medical,stitchedWounds), _stitchedWounds, true];
|
||||
};
|
||||
|
||||
true
|
||||
|
@ -16,9 +16,6 @@
|
||||
|
||||
params ["_target", "_tourniquetItem", "_bodyPart"];
|
||||
|
||||
//If we're not already tracking vitals, start:
|
||||
[_target] call EFUNC(medical,addVitalLoop);
|
||||
|
||||
private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
|
||||
|
||||
// Place a tourniquet on the bodypart
|
||||
|
@ -68,9 +68,4 @@ _args call _callback;
|
||||
_args pushBack _bloodLossOnBodyPart;
|
||||
_args call FUNC(litterCreate);
|
||||
|
||||
//If we're not already tracking vitals, start:
|
||||
if !(_target getVariable [QGVAR(addedToUnitLoop),false]) then {
|
||||
[_target] call FUNC(addVitalLoop);
|
||||
};
|
||||
|
||||
["ace_treatmentSucceded", [_caller, _target, _bodyPart, _className]] call CBA_fnc_localEvent;
|
||||
|
Loading…
Reference in New Issue
Block a user