Medical Rewrite - Continued (#4744)

This commit is contained in:
ulteq 2016-12-05 21:34:20 +01:00 committed by GitHub
parent 9cba0baade
commit a5ce5b4a34
61 changed files with 657 additions and 1672 deletions

View File

@ -6,15 +6,15 @@ class ACE_Medical_StateMachine {
onState = QUOTE(DFUNC(handleStateDefault)); onState = QUOTE(DFUNC(handleStateDefault));
class Injury { class Injury {
targetState = "Injured"; targetState = "Injured";
events[] = {QGVAR(TakenInjury)}; events[] = {QGVAR(Injury)};
}; };
class CriticalInjuryOrVitals { class CriticalInjuryOrVitals {
targetState = "Unconscious"; targetState = "Unconscious";
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)}; events[] = {QGVAR(CriticalInjury), QGVAR(CriticalVitals)};
}; };
class FatalInjury { class FatalInjury {
targetState = "FatalInjury"; targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)}; events[] = {QGVAR(FatalInjury)};
}; };
}; };
class Injured { class Injured {
@ -23,13 +23,9 @@ class ACE_Medical_StateMachine {
targetState = "Default"; targetState = "Default";
events[] = {QGVAR(FullHeal)}; events[] = {QGVAR(FullHeal)};
}; };
class LastWoundTreated {
targetState = "Default";
events[] = {QGVAR(LastWoundTreated)};
};
class CriticalInjuryOrVitals { class CriticalInjuryOrVitals {
targetState = "Unconscious"; targetState = "Unconscious";
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)}; events[] = {QGVAR(CriticalInjury), QGVAR(CriticalVitals)};
}; };
class FatalVitals { class FatalVitals {
targetState = "CardiacArrest"; targetState = "CardiacArrest";
@ -37,30 +33,25 @@ class ACE_Medical_StateMachine {
}; };
class FatalInjury { class FatalInjury {
targetState = "FatalInjury"; targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)}; events[] = {QGVAR(FatalInjury)};
}; };
}; };
class Unconscious { class Unconscious {
onState = QUOTE(DFUNC(handleStateUnconscious)); onState = QUOTE(DFUNC(handleStateUnconscious));
onStateEntered = QUOTE(DFUNC(enteredUnconsciousState)); onStateEntered = QUOTE([ARR_2(_this,(true))] call FUNC(setUnconscious));
onStateLeaving = "_this setVariable ['ACE_isUnconscious', false, true];"; onStateLeaving = QUOTE([ARR_2(_this,(false))] call FUNC(setUnconscious));
class WakeUpFromKnockDown { class WakeUp {
targetState = "Injured"; targetState = "Injured";
condition = QUOTE(_this call FUNC(hasStableVitals)); condition = QUOTE(_this call FUNC(hasStableVitals));
events[] = {QGVAR(MinUnconsciousTimer)}; events[] = {QGVAR(WakeUp)};
};
class WakeUpStable {
targetState = "Injured";
condition = "unitUnconsciousTimer >= MinUnconsciousTimer";
events[] = {QGVAR(VitalsWentStable)};
}; };
class FatalTransitions { class FatalTransitions {
targetState = "CardiacArrest"; targetState = "CardiacArrest";
events[] = {QGVAR(FatalVitals), QGVAR(UnconsciousTimerRanOut)}; events[] = {QGVAR(FatalVitals)};
}; };
class FatalInjury { class FatalInjury {
targetState = "FatalInjury"; targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)}; events[] = {QGVAR(FatalInjury)};
}; };
}; };
class FatalInjury { class FatalInjury {
@ -81,19 +72,19 @@ class ACE_Medical_StateMachine {
}; };
class CardiacArrest { class CardiacArrest {
onStateEntered = QUOTE(DFUNC(enteredStateCardiacArrest)); onStateEntered = QUOTE(DFUNC(enteredStateCardiacArrest));
onStateLeaving = '_this setVariable [QGVAR(cardiacArrestStart), nil]'; onStateLeaving = QUOTE(DFUNC(leftStateCardiacArrest));
class TimerRanOut { class Timeout {
targetState = "Dead"; targetState = "Dead";
condition = QUOTE(DFUNC(conditionCardiacArrestTimer)); condition = QUOTE(DFUNC(conditionCardiacArrestTimer));
}; };
class Reanimated { class Reanimation {
targetState = "Unconscious"; targetState = "Unconscious";
events[] = {QGVAR(CPRSucceeded)}; events[] = {QGVAR(CPRSucceeded)};
}; };
class Execution { class Execution {
targetState = "Dead"; targetState = "Dead";
condition = QUOTE(DFUNC(conditionExecutionDeath)); condition = QUOTE(DFUNC(conditionExecutionDeath));
events[] = {QGVAR(InjuryFatal)}; events[] = {QGVAR(FatalInjury)};
}; };
}; };
class Dead { class Dead {

View File

@ -1,17 +1,9 @@
class ACE_Settings { 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) { class GVAR(medicSetting) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(MedicalSettings_medicSetting_DisplayName); displayName = CSTRING(MedicalSettings_medicSetting_DisplayName);
description = CSTRING(MedicalSettings_medicSetting_Description); description = CSTRING(MedicalSettings_medicSetting_Description);
value = 1; value = 0;
typeName = "SCALAR"; typeName = "SCALAR";
values[] = {"Disabled", "Normal", "Advanced"}; values[] = {"Disabled", "Normal", "Advanced"};
}; };
@ -26,15 +18,10 @@ class ACE_Settings {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(AdvancedMedicalSettings_enableFor_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_enableFor_DisplayName);
description = CSTRING(AdvancedMedicalSettings_enableFor_Description); description = CSTRING(AdvancedMedicalSettings_enableFor_Description);
value = 0; value = 1;
typeName = "SCALAR"; typeName = "SCALAR";
values[] = {"Players only", "Players and AI"}; values[] = {"Players only", "Players and AI"};
}; };
class GVAR(enableOverdosing) {
category = CSTRING(Category_Medical);
typeName = "BOOL";
value = 1;
};
class GVAR(bleedingCoefficient) { class GVAR(bleedingCoefficient) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(MedicalSettings_bleedingCoefficient_DisplayName); displayName = CSTRING(MedicalSettings_bleedingCoefficient_DisplayName);
@ -49,22 +36,12 @@ class ACE_Settings {
typeName = "SCALAR"; typeName = "SCALAR";
value = 1; 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) { class GVAR(enableAdvancedWounds) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_DisplayName);
description = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_Description); description = CSTRING(AdvancedMedicalSettings_enableAdvancedWounds_Description);
typeName = "BOOL"; typeName = "BOOL";
value = false; value = 1;
}; };
class GVAR(enableVehicleCrashes) { class GVAR(enableVehicleCrashes) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
@ -80,6 +57,8 @@ class ACE_Settings {
typeName = "BOOL"; typeName = "BOOL";
value = 1; value = 1;
}; };
// Use those for handleIncapacitation?
class GVAR(playerDamageThreshold) { class GVAR(playerDamageThreshold) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(MedicalSettings_playerDamageThreshold_DisplayName); displayName = CSTRING(MedicalSettings_playerDamageThreshold_DisplayName);
@ -94,11 +73,13 @@ class ACE_Settings {
typeName = "SCALAR"; typeName = "SCALAR";
value = 1; value = 1;
}; };
class GVAR(enableUnconsciousnessAI) { class GVAR(enableUnconsciousnessAI) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);
displayName = CSTRING(MedicalSettings_enableUnconsciousnessAI_DisplayName); displayName = CSTRING(MedicalSettings_enableUnconsciousnessAI_DisplayName);
description = CSTRING(MedicalSettings_enableUnconsciousnessAI_Description); description = CSTRING(MedicalSettings_enableUnconsciousnessAI_Description);
value = 1; value = 2;
typeName = "SCALAR"; typeName = "SCALAR";
values[] = {"Disabled", "50/50", "Enabled"}; values[] = {"Disabled", "50/50", "Enabled"};
}; };
@ -148,7 +129,7 @@ class ACE_Settings {
displayName = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_DisplayName); displayName = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_DisplayName);
description = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_Description); description = CSTRING(BasicMedicalSettings_medicSetting_basicEpi_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 1; value = 0;
values[] = {"Anyone", "Medics only", "Doctors only"}; values[] = {"Anyone", "Medics only", "Doctors only"};
}; };
class GVAR(medicSetting_PAK) { class GVAR(medicSetting_PAK) {
@ -156,7 +137,7 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_Description); description = CSTRING(AdvancedMedicalSettings_medicSetting_PAK_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 1; value = 0;
values[] = {"Anyone", "Medics only", "Doctors only"}; values[] = {"Anyone", "Medics only", "Doctors only"};
}; };
class GVAR(medicSetting_SurgicalKit) { class GVAR(medicSetting_SurgicalKit) {
@ -164,7 +145,7 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName);
description = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_Description); description = CSTRING(AdvancedMedicalSettings_medicSetting_SurgicalKit_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 1; value = 0;
values[] = {"Anyone", "Medics only", "Doctors only"}; values[] = {"Anyone", "Medics only", "Doctors only"};
}; };
class GVAR(consumeItem_PAK) { class GVAR(consumeItem_PAK) {
@ -172,7 +153,7 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_Description); description = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 0; value = 1;
values[] = {"No", "Yes"}; values[] = {"No", "Yes"};
}; };
class GVAR(consumeItem_SurgicalKit) { class GVAR(consumeItem_SurgicalKit) {
@ -180,7 +161,7 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName);
description = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_Description); description = CSTRING(AdvancedMedicalSettings_consumeItem_SurgicalKit_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 0; value = 1;
values[] = {"No", "Yes"}; values[] = {"No", "Yes"};
}; };
class GVAR(useLocation_basicEpi) { class GVAR(useLocation_basicEpi) {
@ -196,7 +177,7 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_useLocation_PAK_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_useLocation_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useLocation_PAK_Description); description = CSTRING(AdvancedMedicalSettings_useLocation_PAK_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 3; value = 0;
values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)}; values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)};
}; };
class GVAR(useLocation_SurgicalKit) { class GVAR(useLocation_SurgicalKit) {
@ -204,38 +185,23 @@ class ACE_Settings {
displayName = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_Description); description = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 2; value = 0;
values[] = {CSTRING(AdvancedMedicalSettings_anywhere), CSTRING(AdvancedMedicalSettings_vehicle), CSTRING(AdvancedMedicalSettings_facility), CSTRING(AdvancedMedicalSettings_vehicleAndFacility), ECSTRING(common,Disabled)}; 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); category = CSTRING(Category_Medical);
displayName = CSTRING(AdvancedMedicalSettings_useCondition_PAK_DisplayName); displayName = CSTRING(AdvancedMedicalSettings_fullHealLocation_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useCondition_PAK_Description); description = CSTRING(AdvancedMedicalSettings_fullHealLocation_PAK_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 0; value = 3;
values[] = {"Anytime", "Stable"}; 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); category = CSTRING(Category_Medical);
displayName = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_DisplayName); displayName = CSTRING(MedicalSettings_fieldEffectiveness_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_Description); description = CSTRING(MedicalSettings_fieldEffectiveness_PAK_Description);
typeName = "SCALAR"; typeName = "SCALAR";
value = 0; value = 0.9;
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;
}; };
class GVAR(painIsOnlySuppressed) { class GVAR(painIsOnlySuppressed) {
category = CSTRING(Category_Medical); category = CSTRING(Category_Medical);

View File

@ -1,35 +1,41 @@
PREP(addDamageToUnit);
PREP(addStateHandler);
PREP(adjustPainLevel); PREP(adjustPainLevel);
PREP(conditionCardiacArrestTimer);
PREP(conditionExecutionDeath);
PREP(enteredStateCardiacArrest);
PREP(enteredStateFatalInjury);
PREP(getBloodLoss); PREP(getBloodLoss);
PREP(getBloodPressure); PREP(getBloodPressure);
PREP(getBloodVolumeChange); PREP(getBloodVolumeChange);
PREP(getCardiacOutput); PREP(getCardiacOutput);
PREP(getHeartRateChange); 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(init);
PREP(install); PREP(install);
PREP(isBeingCarried);
PREP(isBeingDragged);
PREP(isInMedicalFacility); PREP(isInMedicalFacility);
PREP(isInMedicalVehicle); PREP(isInMedicalVehicle);
PREP(isInStableCondition); PREP(isInStableCondition);
PREP(isMedic); PREP(isMedic);
PREP(isMedicalVehicle); PREP(isMedicalVehicle);
PREP(leftStateCardiacArrest);
// PREP(hasMedicalEnabled); PREP(moduleAssignMedicRoles);
PREP(moduleAssignMedicalVehicle);
PREP(enteredStateCardiacArrest); PREP(serverRemoveBody);
PREP(leavingStateCardiacArrest); PREP(setCardiacArrest);
PREP(enteredStateFatalInjury);
PREP(conditionExecutionDeath);
PREP(transitionSecondChance);
PREP(handleStateDefault);
PREP(handleStateInjured);
PREP(handleStateUnconscious);
PREP(handleUnitVitals);
PREP(handleMedications);
PREP(addPain);
PREP(setUnconscious);
PREP(setDead); PREP(setDead);
PREP(setUnconscious);
PREP(hasTourniquetAppliedTo); PREP(showBloodEffect);
PREP(transitionSecondChance);

View File

@ -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);
};

View File

@ -1,13 +1,13 @@
/* /*
* Author: PabstMirror * Author: PabstMirror
* Interface to allow external modules to safely adjust pain levels. * Interface to allow external modules to affect the pain level
* *
* Arguments: * Arguments:
* 0: The patient <OBJECT> * 0: The patient <OBJECT>
* 1: Added ammount of pain (can be negative) <NUMBER> * 1: Desired pain level (0 .. 1) <NUMBER>
* *
* Return Value: * Return Value:
* The new pain level <NUMBER> * nothing
* *
* Example: * Example:
* [guy, 0.5] call ace_medical_fnc_adjustPainLevel * [guy, 0.5] call ace_medical_fnc_adjustPainLevel
@ -16,21 +16,14 @@
*/ */
#include "script_component.hpp" #include "script_component.hpp"
private ["_pain"]; params ["_unit", "_desiredPainLevel"];
params ["_unit", "_addedPain"]; if (!local _unit) exitWith { ERROR("unit is not local"); };
//Only run on local units:
if (!local _unit) exitWith {ERROR("unit is not local");};
TRACE_3("ACE_DEBUG: adjustPainLevel Called",_unit, _pain, _addedPain);
//Ignore if medical system disabled: TRACE_2("ACE_DEBUG: adjustPainLevel Called",_unit,_desiredPainLevel);
if (GVAR(level) == 0) exitWith {};
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]; _unit setVariable [QGVAR(pain), _pain];
//Start up the vital watching (if not already running)
// [_unit] call FUNC(addVitalLoop);
_pain;

View File

@ -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"];
};

View File

@ -11,6 +11,9 @@
* Public: No * Public: No
*/ */
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit"]; params ["_unit"];
_unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime]; _unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime];
[_unit] call FUNC(setCardiacArrest);

View File

@ -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);

View File

@ -6,7 +6,7 @@
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
* *
* ReturnValue: * ReturnValue:
* Total blood loss of unit <NUMBER> * Total blood loss of unit (liter per second) <NUMBER>
* *
* Public: No * Public: No
*/ */
@ -14,18 +14,26 @@
params ["_unit"]; 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]]; private _tourniquets = _unit getVariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
{ {
if (_tourniquets select (_x select 2) == 0) then { _x params ["", "", "_bodyPart", "_percentage", "_bleeeding"];
// total bleeding ratio * percentage of injury left if (_bodyPart == 1) then {
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3)); _bodyBleeding = _bodyBleeding + (_bleeeding * _percentage);
} else {
if (_tourniquets select _bodyPart == 0) then {
_limbBleeding = _limbBleeding + (_bleeeding * _percentage);
};
}; };
} forEach (_unit getVariable [QGVAR(openWounds), []]); } forEach (_unit getVariable [QGVAR(openWounds), []]);
{ private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
} forEach (_unit getVariable [QGVAR(internalWounds), []]);
_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)])

View File

@ -1,6 +1,6 @@
/* /*
* Author: Glowbal * Author: Glowbal
* Calculates the blood volume change and decreases the IVs given to the unit. * Calculate the blood pressure of a unit.
* *
* Arguments: * Arguments:
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
@ -15,17 +15,15 @@
#include "script_component.hpp" #include "script_component.hpp"
// Value is taken because with cardic output and resistance at default values, it will put blood pressure High at 120. // 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. // 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"]; params ["_unit"];
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput); private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
private _resistance = _unit getVariable [QGVAR(peripheralResistance), 100]; private _resistance = _unit getVariable [QGVAR(peripheralResistance), 100];
private _bloodPressure = _cardiacOutput * _resistance;
private _bloodPressureHigh = (_cardiacOutput * MODIFIER_BP_HIGH) * _resistance; [round(_bloodPressure * MODIFIER_BP_LOW), round(_bloodPressure * MODIFIER_BP_HIGH)]
private _bloodPressureLow = (_cardiacOutput * MODIFIER_BP_LOW) * _resistance;
[_bloodPressureLow max 0, _bloodPressureHigh max 0]

View File

@ -4,47 +4,49 @@
* *
* Arguments: * Arguments:
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
* 1: Global Sync Values (bloodbags) <BOOL> * 1: Time since last update <NUMBER>
* 2: Global Sync Values (bloodbags) <BOOL>
* *
* ReturnValue: * ReturnValue:
* Blood volume change (in % total) <NUMBER> * Blood volume change (liters per second) <NUMBER>
* *
* Public: No * Public: No
*/ */
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit", "_syncValues"]; params ["_unit", "_deltaT", "_syncValues"];
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]; 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 (!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 { _bloodBags = _bloodBags apply {
_x params ["_bagVolumeRemaining"]; _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; _bagVolumeRemaining = _bagVolumeRemaining - _bagChange;
_bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000); _bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000);
if (_bagVolumeRemaining < 0.01) then { if (_bagVolumeRemaining < 0.01) then {
[] []
} else { } 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 { } 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 { } else {
_unit setVariable [QGVAR(ivBags), nil, true]; // blood volume = 100% - clear variable (always globaly sync this) _unit setVariable [QGVAR(ivBags), _bloodBags, _syncValues];
}; };
}; };

View File

@ -6,7 +6,7 @@
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
* *
* ReturnValue: * ReturnValue:
* Current cardiac output <NUMBER> * Current cardiac output (liter per second) <NUMBER>
* *
* Public: No * Public: No
*/ */
@ -14,8 +14,7 @@
#include "script_component.hpp" #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 Source: http://en.wikipedia.org/wiki/Cardiac_output
*/ */
@ -24,4 +23,10 @@
params ["_unit"]; 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)

View File

@ -13,15 +13,11 @@
#include "script_component.hpp" #include "script_component.hpp"
#define HEART_RATE_MODIFIER 0.02
params ["_unit"]; params ["_unit"];
private _hrIncrease = 0; 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), []]; private _adjustment = _unit getVariable [QGVAR(heartRateAdjustments), []];
{ {
_x params ["_values", "_time", "_callBack"]; _x params ["_values", "_time", "_callBack"];
@ -49,36 +45,37 @@ if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
_adjustment = _adjustment - [ObjNull]; _adjustment = _adjustment - [ObjNull];
_unit setVariable [QGVAR(heartRateAdjustments), _adjustment]; _unit setVariable [QGVAR(heartRateAdjustments), _adjustment];
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]; if (!(_unit getVariable [QGVAR(inCardiacArrest), false])) then {
if (_bloodVolume > 75) then { private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]);
if (_bloodLoss > 0.0) then { private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME];
if (_bloodLoss < 0.5) then { if (_bloodVolume > BLOOD_VOLUME_CLASS_4_HEMORRHAGE) then {
if (_heartRate < 126) then { private _hrChange = 0;
_hrIncrease = _hrIncrease + 0.05; ([_unit] call FUNC(getBloodPressure)) params ["_bloodPressureL", "_bloodPressureH"];
}; private _meanBP = (2/3) * _bloodPressureH + (1/3) * _bloodPressureL;
} else { private _pain = _unit getVariable [QGVAR(pain), 0];
if (_bloodLoss < 1) then { private _hasPain = _unit getVariable [QGVAR(hasPain), false];
if (_heartRate < 161) then { private _targetBP = 107;
_hrIncrease = _hrIncrease + 0.1; private _targetHR = 80;
}; if (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE) then {
} else { _targetBP = _targetBP * (_bloodVolume / DEFAULT_BLOOD_VOLUME);
if (_heartRate < 220) then { };
_hrIncrease = _hrIncrease + 0.15; 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 { } else {
// Stabalize it _hrIncrease = _hrIncrease - (random 5) * round(_heartRate / 10);
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;
};
};
}; };
} else {
_hrIncrease = _hrIncrease - HEART_RATE_MODIFIER;
}; };
}; };
_hrIncrease _hrIncrease

View 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;
};

View File

@ -17,8 +17,6 @@ params ["_unit"];
if (!local _unit) exitWith {}; if (!local _unit) exitWith {};
_unit setVariable [QGVAR(pain), 0]; _unit setVariable [QGVAR(pain), 0];
if (GVAR(level) >= 2) then { _unit setVariable [QGVAR(heartRate), 0];
_unit setVariable [QGVAR(heartRate), 0]; _unit setVariable [QGVAR(bloodPressure), [0, 0]];
_unit setVariable [QGVAR(bloodPressure), [0, 0]]; _unit setVariable [QGVAR(airwayStatus), 0];
_unit setVariable [QGVAR(airwayStatus), 0];
};

View File

@ -17,17 +17,10 @@
params ["_unit", "_local"]; params ["_unit", "_local"];
if (_local) then { 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 { if ((_unit getVariable ["ACE_isUnconscious",false]) && {count (_unit getVariable [QGVAR(unconsciousArguments), []]) >= 6}) then {
private _arguments = (_unit getVariable [QGVAR(unconsciousArguments), []]); private _arguments = (_unit getVariable [QGVAR(unconsciousArguments), []]);
_arguments set [2, CBA_missionTime]; _arguments set [2, CBA_missionTime];
//[DFUNC(unconsciousPFH), 0.1, _arguments ] call CBA_fnc_addPerFrameHandler;
_unit setVariable [QGVAR(unconsciousArguments), nil, true]; _unit setVariable [QGVAR(unconsciousArguments), nil, true];
}; };
}; };

View File

@ -1,24 +1,19 @@
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit", "_stateName", "_lastTime"]; params ["_unit", "_stateName"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop // If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith { if (!local _unit) exitWith {
if (GVAR(level) >= 2) then { _unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], 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(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
};
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true]; _unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true];
}; };
systemChat format["handling state default for unit: %1", _this]; [_unit] call FUNC(handleUnitVitals);
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
private _pain = _unit getVariable [QGVAR(pain), 0]; private _pain = _unit getVariable [QGVAR(pain), 0];
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then { if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {

View File

@ -1,22 +1,19 @@
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit", "_stateName", "_lastTime"]; params ["_unit", "_stateName"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop // If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith { if (!local _unit) exitWith {
if (GVAR(level) >= 2) then { _unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], 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(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
};
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], 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]; private _pain = _unit getVariable [QGVAR(pain), 0];
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then { if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {

View File

@ -1,22 +1,19 @@
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit", "_stateName", "_lastTime"]; params ["_unit", "_stateName"];
// If the unit died the loop is finished // If the unit died the loop is finished
if (!alive _unit) exitWith {}; if (!alive _unit) exitWith {};
// If locality changed, broadcast the last medical state and finish the local loop // If locality changed, broadcast the last medical state and finish the local loop
if (!local _unit) exitWith { if (!local _unit) exitWith {
if (GVAR(level) >= 2) then { _unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], 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(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
};
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], 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]; private _pain = _unit getVariable [QGVAR(pain), 0];
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then { if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {

View File

@ -12,27 +12,33 @@
*/ */
#include "script_component.hpp" #include "script_component.hpp"
params ["_unit", "_interval"]; params ["_unit"];
TRACE_3("ACE_DEBUG",_unit,_interval,_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 _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 { if (_syncValues) then {
_unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime]; _unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime];
}; };
private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) + ([_unit, _syncValues] call FUNC(getBloodVolumeChange)); private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) + ([_unit, _deltaT, _syncValues] call FUNC(getBloodVolumeChange));
_bloodVolume = (_bloodVolume max 0) min DEFAULT_BLOOD_VOLUME; _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]; _unit setVariable [QGVAR(bloodVolume), _bloodVolume, _syncValues];
TRACE_3("ACE_DEBUG",_bloodVolume,_syncValues,_unit); TRACE_3("ACE_DEBUG",_bloodVolume,_syncValues,_unit);
// Set variables for synchronizing information across the net // Set variables for synchronizing information across the net
if (_bloodVolume < BLOOD_VOLUME_HAS_LOST_SOME) then { if (_bloodVolume < BLOOD_VOLUME_CLASS_1_HEMORRHAGE) then {
if (_bloodVolume < BLOOD_VOLUME_HAS_LOST_MUCH) then { if (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE) then {
if (_unit getVariable [QGVAR(hasLostBlood), 0] != 2) then { if (_unit getVariable [QGVAR(hasLostBlood), 0] != 2) then {
_unit setVariable [QGVAR(hasLostBlood), 2, true]; _unit setVariable [QGVAR(hasLostBlood), 2, true];
}; };
@ -52,7 +58,7 @@ TRACE_3("ACE_DEBUG",_bloodLoss,_unit getVariable QGVAR(isBleeding),_unit);
if (_bloodLoss > 0) then { if (_bloodLoss > 0) then {
_unit setVariable [QGVAR(bloodloss), _bloodLoss, _syncValues]; _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 { if !(_unit getVariable [QGVAR(isBleeding), false]) then {
_unit setVariable [QGVAR(isBleeding), true, true]; _unit setVariable [QGVAR(isBleeding), true, true];
@ -75,75 +81,55 @@ if (_painStatus > (_unit getVariable [QGVAR(painSuppress), 0])) then {
}; };
}; };
if (_bloodVolume < BLOOD_VOLUME_DEAD) exitWith { TRACE_6("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_bloodVolume,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
[_unit, "bloodloss"] call FUNC(setDead);
// 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 { #ifdef DEBUG_MODE_FULL
if (_bloodVolume < BLOOD_VOLUME_UNCONSCIOUS && {random 1 < BLOOD_LOSS_KNOCK_OUT_CHANCE}) exitWith { if (!isPlayer _unit) then {
[_unit, true, BLOOD_LOSS_KNOCK_OUT_DURATION] call FUNC(setUnconscious); 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;
}; };
/* // Handle spontaneous wakeup from unconsciousness
if (GVAR(level) == 1) then { if (_unit getVariable [QGVAR(isUnconscious), false]) then {
TRACE_5("ACE_DEBUG_BASIC_VITALS",_painStatus,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit); if (_unit call FUNC(hasStableVitals)) then {
// reduce pain private _lastWakeUpCheck = _unit getVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
if (_painStatus > 0) then { if (CBA_missionTime - _lastWakeUpCheck > SPONTANEOUS_WAKE_UP_INTERVAL) then {
_unit setVariable [QGVAR(pain), (_painStatus - 0.001 * _interval) max 0, _syncValues]; _unit setVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
}; if ((random 1) < SPONTANEOUS_WAKE_UP_CHANCE) then {
[QGVAR(WakeUp), _unit] call CBA_fnc_localEvent;
//// 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);
}; };
}; };
if (_heartRate > 200 || (_heartRate < 20)) then { } else {
[_unit] call FUNC(setCardiacArrest); // Unstable vitals, procrastinate the next wakeup check
}; _unit setVariable [QGVAR(lastWakeUpCheck), CBA_missionTime];
}; };
}; };
*/

View 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

View File

@ -20,7 +20,8 @@ if (damage _unit > 0) then {
_unit setVariable [QGVAR(pain), 0, true]; _unit setVariable [QGVAR(pain), 0, true];
_unit setVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME, 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 // tourniquets
_unit setVariable [QGVAR(tourniquets), [0,0,0,0,0,0], true]; _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 // wounds and injuries
_unit setVariable [QGVAR(openWounds), [], true]; _unit setVariable [QGVAR(openWounds), [], true];
_unit setVariable [QGVAR(bandagedWounds), [], true]; _unit setVariable [QGVAR(bandagedWounds), [], true];
_unit setVariable [QGVAR(internalWounds), [], true]; _unit setVariable [QGVAR(stitchedWounds), [], true];
// vitals // vitals
_unit setVariable [QGVAR(heartRate), 80]; _unit setVariable [QGVAR(heartRate), 80];
@ -37,9 +38,6 @@ _unit setVariable [QGVAR(heartRateAdjustments), []];
_unit setVariable [QGVAR(bloodPressure), [80, 120]]; _unit setVariable [QGVAR(bloodPressure), [80, 120]];
_unit setVariable [QGVAR(peripheralResistance), 100]; _unit setVariable [QGVAR(peripheralResistance), 100];
// fractures
_unit setVariable [QGVAR(fractures), [], true];
// triage card and logs // triage card and logs
// TODO move to treatment // TODO move to treatment
//_unit setVariable [QGVAR(triageLevel), 0, true]; //_unit setVariable [QGVAR(triageLevel), 0, true];
@ -51,14 +49,8 @@ _unit setVariable [QGVAR(ivBags), nil, true];
// damage storage // damage storage
_unit setVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true]; _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 // generic medical admin
_unit setVariable [QGVAR(addedToUnitLoop), false, true]; // TODO this is replaced by unit state _unit setVariable [QGVAR(inCardiacArrest), false, true];
_unit setVariable [QGVAR(inCardiacArrest), false, true]; // TODO this is no longer present
_unit setVariable [QGVAR(hasLostBlood), 0, true]; _unit setVariable [QGVAR(hasLostBlood), 0, true];
_unit setVariable [QGVAR(isBleeding), false, true]; _unit setVariable [QGVAR(isBleeding), false, true];
_unit setVariable [QGVAR(hasPain), false, true]; _unit setVariable [QGVAR(hasPain), false, true];

View File

@ -15,10 +15,9 @@
params ["_unit"]; params ["_unit"];
private _totalBloodLoss = 0; if (!alive _unit) exitWith { false };
{ if (_unit call FUNC(getBloodLoss) > 0) exitWith { false };
// total bleeding ratio * percentage of injury left if (!(_unit call FUNC(hasStableVitals))) exitWith { false };
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3)); if (_unit getVariable [QGVAR(isUnconscious), false]) exitWith { false };
} forEach (_unit getVariable [QGVAR(openWounds), []]);
(_totalBloodLoss == 0); true

View File

@ -16,13 +16,14 @@
params ["_unit"]; params ["_unit"];
if (_unit getVariable [QGVAR(inCardiacArrest),false]) exitWith {}; if (_unit getVariable [QGVAR(inCardiacArrest), false]) exitWith {};
_unit setVariable [QGVAR(inCardiacArrest), true,true]; _unit setVariable [QGVAR(inCardiacArrest), true, true];
_unit setVariable [QGVAR(heartRate), 0]; _unit setVariable [QGVAR(heartRate), 0, true];
["ace_cardiacArrestEntered", [_unit]] call CBA_fnc_localEvent; ["ace_cardiacArrestEntered", [_unit]] call CBA_fnc_localEvent;
[_unit, true] call FUNC(setUnconscious); [_unit, true] call FUNC(setUnconscious);
[QEGVAR(medical,InjuryCritical), _unit] call CBA_fnc_localEvent;
private _timeInCardiacArrest = 120 + round(random(600)); private _timeInCardiacArrest = 120 + round(random(600));
[{ [{
@ -30,13 +31,13 @@ private _timeInCardiacArrest = 120 + round(random(600));
_args params ["_unit", "_startTime", "_timeInCardiacArrest"]; _args params ["_unit", "_startTime", "_timeInCardiacArrest"];
private _heartRate = _unit getVariable [QGVAR(heartRate), 80]; private _heartRate = _unit getVariable [QGVAR(heartRate), 80];
if (_heartRate > 0 || !alive _unit) exitWith { if (_heartRate > 20 || !alive _unit) exitWith {
[_idPFH] call CBA_fnc_removePerFrameHandler; [_idPFH] call CBA_fnc_removePerFrameHandler;
_unit setVariable [QGVAR(inCardiacArrest), nil,true]; _unit setVariable [QGVAR(inCardiacArrest), nil, true];
}; };
if (CBA_missionTime - _startTime >= _timeInCardiacArrest) exitWith { if (CBA_missionTime - _startTime >= _timeInCardiacArrest) exitWith {
[_idPFH] call CBA_fnc_removePerFrameHandler; [_idPFH] call CBA_fnc_removePerFrameHandler;
_unit setVariable [QGVAR(inCardiacArrest), nil,true]; _unit setVariable [QGVAR(inCardiacArrest), nil, true];
[_unit] call FUNC(setDead); [_unit] call FUNC(setDead);
}; };
}, 1, [_unit, CBA_missionTime, _timeInCardiacArrest] ] call CBA_fnc_addPerFrameHandler; }, 1, [_unit, CBA_missionTime, _timeInCardiacArrest] ] call CBA_fnc_addPerFrameHandler;

View File

@ -5,8 +5,6 @@
* Arguments: * Arguments:
* 0: The unit that will be put in an unconscious state <OBJECT> * 0: The unit that will be put in an unconscious state <OBJECT>
* 1: Set unconsciouns <BOOL> (default: true) * 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: * ReturnValue:
* Success? <BOOLEAN> * Success? <BOOLEAN>
@ -23,20 +21,15 @@ if !(EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(setUnconscious), _this]; 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 (isNull _unit || {!(_unit isKindOf "CAManBase")}) exitWith {false};
if (!local _unit) exitWith { 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 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}; if (_knockOut isEqualTo (_unit getVariable [QGVAR(isUnconscious), false])) exitWith {false};
// --- wake up // --- wake up
@ -55,6 +48,7 @@ if !(_knockOut) exitWith {
// --- knock out // --- knock out
_unit setVariable [QGVAR(isUnconscious), true, true]; _unit setVariable [QGVAR(isUnconscious), true, true];
_unit setVariable [QGVAR(lastWakeUpCheck), CBA_missiontime];
if (_unit == ACE_player) then { if (_unit == ACE_player) then {
if (visibleMap) then {openMap false}; 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); [_unit, true] call EFUNC(medical_engine,setUnconsciousAnim);
[QGVAR(Unconscious), _unit] call CBA_fnc_localEvent; [QGVAR(Unconscious), _unit] call CBA_fnc_localEvent;
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent; ["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 true

View File

@ -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;
};
};

View File

@ -17,28 +17,30 @@
// 0.077 l/kg * 80kg = 6.16l // 0.077 l/kg * 80kg = 6.16l
#define DEFAULT_BLOOD_VOLUME 6.0 // in liters #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_CLASS_1_HEMORRHAGE 6.000 // lost less than 15% blood, Class I Hemorrhage
#define BLOOD_VOLUME_HAS_LOST_MUCH 5.100 // lost 15% blood, Class II 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_UNCONSCIOUS 4.200 // lost 30% blood, Class III Hemorrhage #define BLOOD_VOLUME_CLASS_4_HEMORRHAGE 3.600 // lost more than 40% blood, Class IV Hemorrhage
#define BLOOD_VOLUME_DEAD 3.600 // lost 40% blood, Class IV Hemorrhage
#define BLOOD_VOLUME_CARDIAC_ARREST 1.2 // TBD
// IV Change per second calculation: // IV Change per second calculation:
// 250ml should take 60 seconds to fill. 250ml/60s = 4.166ml/s. // 250 ml should take 60 seconds to fill. 250 ml / 60 s ~ 4.1667 ml/s.
#define IV_CHANGE_PER_SECOND ([1000, 4.166] select GVAR(advancedIVBags)) // in milliliters per second #define IV_CHANGE_PER_SECOND 4.1667 // in milliliters per second
// chance per second to get knocked out due to blood loss // Minimum amount of damage required for penetrating wounds (also minDamage for velocity wounds)
#define BLOOD_LOSS_KNOCK_OUT_CHANCE 0.1 // 10% #define PENETRATION_THRESHOLD 0.35
// duration in seconds to stay knocked out due to blood loss // To be replaced by a proper blood pressure calculation
#define BLOOD_LOSS_KNOCK_OUT_DURATION (15 + random 20) #define BLOOD_LOSS_KNOCK_OUT_THRESHOLD 0.5 // 50% of cardiac output
// --- unconsciousness
#define DEFAULT_KNOCK_OUT_DELAY (5 + random 10)
// --- pain // --- pain
#define PAIN_UNCONSCIOUS 0.7 #define PAIN_UNCONSCIOUS 0.5
// duration in seconds to stay knocked out due to pain // 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

View File

@ -2942,31 +2942,17 @@
<Italian>Coefficiente che modifica l'intensità del dolore</Italian> <Italian>Coefficiente che modifica l'intensità del dolore</Italian>
<Japanese>この係数では痛みの強さを変更できます</Japanese> <Japanese>この係数では痛みの強さを変更できます</Japanese>
</Key> </Key>
<Key ID="STR_ACE_Medical_MedicalSettings_keepLocalSettingsSynced_DisplayName"> <Key ID="STR_ACE_Medical_MedicalSettings_fullHealLocation_PAK_DisplayName">
<English>Sync status</English> <English>Full Heal Locations</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> </Key>
<Key ID="STR_ACE_Medical_MedicalSettings_keepLocalSettingsSynced_Description"> <Key ID="STR_ACE_Medical_MedicalSettings_fullHealLocation_PAK_Description">
<English>Keep unit status synced. Recommended on.</English> <English>Where does the PAK perform a full heal?</English>
<Russian>Синхронизировать статус юнитов. Рекомендуется включить.</Russian> </Key>
<Polish>Utrzymuj synchronizację statusu jednostek. Zalecane zostawienie tej opcji włączonej.</Polish> <Key ID="STR_ACE_Medical_MedicalSettings_fieldEffectiveness_PAK_DisplayName">
<Spanish>Mantener el estado de la unidad sincronizado. Recomendado activado</Spanish> <English>PAK effectiveness</English>
<German>Status der Einheit synchron halten. Sollte aktiviert bleiben.</German> </Key>
<Czech>Udržuje status jednotky synchronizovaný. Doporučeno zapnout.</Czech> <Key ID="STR_ACE_Medical_MedicalSettings_fieldEffectiveness_PAK_Description">
<Portuguese>Mater o estado da unidade sincronizado. Recomendado ativado.</Portuguese> <English>PAK effectiveness when used outside of medical facilities</English>
<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> </Key>
<Key ID="STR_ACE_Medical_MedicalSettings_Module_Description"> <Key ID="STR_ACE_Medical_MedicalSettings_Module_Description">
<English>Provides a medical system for both players and AI.</English> <English>Provides a medical system for both players and AI.</English>

View File

@ -6,7 +6,7 @@
if ((GVAR(enabledFor) == 1) && {!isServer} && {hasInterface}) exitWith {}; // 1: Don't Run on non-hc Clients 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 // 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", { ["ace_firedNonPlayer", {
_unit setVariable [QGVAR(lastFired), CBA_missionTime]; _unit setVariable [QGVAR(lastFired), CBA_missionTime];

View File

@ -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 { class ACE_Medical_Injuries {
// Defines all the possible injury types for advanced medical // Defines all the possible injury types
class wounds { class wounds {
// Source: Scarle // 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). // 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 { class Abrasion {
name = CSTRING(Abrasion); name = CSTRING(Abrasion);
selections[] = {"All"};
bleedingRate = 0.0001;
pain = 0.01;
causes[] = {"falling", "ropeburn", "vehiclecrash", "unknown"}; causes[] = {"falling", "ropeburn", "vehiclecrash", "unknown"};
bleeding = 0.001;
pain = 0.4;
minDamage = 0.01; minDamage = 0.01;
class Minor { maxDamage = 0.30;
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;
};
}; };
// 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. // 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 { class Avulsions {
name = CSTRING(Avulsion); name = CSTRING(Avulsion);
selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.3;
causes[] = {"explosive", "vehiclecrash", "grenade", "shell", "bullet", "backblast", "bite"}; causes[] = {"explosive", "vehiclecrash", "grenade", "shell", "bullet", "backblast", "bite"};
minDamage = 0.2; bleeding = 0.5;
class Minor { pain = 1.0;
name = CSTRING(Avulsion_Minor); minDamage = 4;
minDamage = 0.2; causeLimping = 1;
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;
};
}; };
// 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. // 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 { class Contusion {
name = CSTRING(Contusion); name = CSTRING(Contusion);
selections[] = {"All"};
bleedingRate = 0.0;
pain = 0.05;
causes[] = {"bullet", "backblast", "punch", "vehiclecrash", "falling"}; causes[] = {"bullet", "backblast", "punch", "vehiclecrash", "falling"};
minDamage = 0.01; bleeding = 0.0;
maxDamage = 0.1; pain = 0.3;
class Minor { minDamage = 0.02;
name = CSTRING(Contusion_Minor); maxDamage = 0.35;
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;
};
}; };
// Occur when a heavy object falls onto a person, splitting the skin and shattering or tearing underlying structures. // Occur when a heavy object falls onto a person, splitting the skin and shattering or tearing underlying structures.
class CrushWound { class CrushWound {
name = CSTRING(Crush); name = CSTRING(Crush);
selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.1;
causes[] = {"falling", "vehiclecrash", "punch", "unknown"}; causes[] = {"falling", "vehiclecrash", "punch", "unknown"};
bleeding = 0.1;
pain = 0.8;
minDamage = 0.1; minDamage = 0.1;
class Minor { causeLimping = 1;
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;
};
}; };
// 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. // 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 { class Cut {
name = CSTRING(Cut); name = CSTRING(Cut);
selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.075;
causes[] = {"vehiclecrash", "grenade", "explosive", "shell", "backblast", "stab", "unknown"}; causes[] = {"vehiclecrash", "grenade", "explosive", "shell", "backblast", "stab", "unknown"};
bleeding = 0.04;
pain = 0.1;
minDamage = 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. // 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 { class Laceration {
name = CSTRING(Laceration); name = CSTRING(Laceration);
selections[] = {"All"}; selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.075;
causes[] = {"vehiclecrash", "punch"}; causes[] = {"vehiclecrash", "punch"};
bleeding = 0.05;
pain = 0.2;
minDamage = 0.01; 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. // 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 { class velocityWound {
name = CSTRING(VelocityWound); name = CSTRING(VelocityWound);
selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.2;
causes[] = {"bullet", "grenade","explosive", "shell", "unknown"}; causes[] = {"bullet", "grenade","explosive", "shell", "unknown"};
minDamage = 0.15; bleeding = 1.0;
class Minor { pain = 0.9;
name = CSTRING(VelocityWound_Minor); minDamage = 0.35;
minDamage = 0.15; causeLimping = 1;
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;
};
}; };
// Deep, narrow wounds produced by sharp objects such as nails, knives, and broken glass. // Deep, narrow wounds produced by sharp objects such as nails, knives, and broken glass.
class punctureWound { class punctureWound {
name = CSTRING(PunctureWound); name = CSTRING(PunctureWound);
selections[] = {"All"};
bleedingRate = 0.01;
pain = 0.075;
causes[] = {"stab", "grenade"}; causes[] = {"stab", "grenade"};
minDamage = 0.01; bleeding = 0.1;
class Minor { pain = 0.4;
name = CSTRING(PunctureWound_Minor); minDamage = 0.02;
minDamage = 0.01; causeLimping = 1;
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;
}; };
}; };
class damageTypes { class damageTypes {
// thresholds[] {{<min damage>, <max number of wounds>}, {...}}
thresholds[] = {{0.1, 1}}; thresholds[] = {{0.1, 1}};
selectionSpecific = 1; selectionSpecific = 1;
lethalDamage = 0.01;
class bullet { class bullet {
// above damage, amount. Put the highest threshold to the left and lower the threshold with the elements to the right of it. // 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; selectionSpecific = 0;
}; };
class vehiclecrash { class vehiclecrash {
thresholds[] = {{0.25, 5}, {0.05, 1}}; thresholds[] = {{0.5, 5}, {0.3, 2}, {0.05, 1}};
selectionSpecific = 0; selectionSpecific = 0;
lethalDamage = 0.2;
}; };
class backblast { class backblast {
thresholds[] = {{1, 6}, {0.55, 5}, {0, 2}}; thresholds[] = {{1, 6}, {0.55, 5}, {0, 2}};
selectionSpecific = 0; selectionSpecific = 0;
lethalDamage = 1;
}; };
class stab { class stab {
thresholds[] = {{0.1, 1}}; thresholds[] = {{0.1, 1}};
@ -261,9 +116,8 @@ class ACE_Medical_Injuries {
selectionSpecific = 1; selectionSpecific = 1;
}; };
class falling { class falling {
thresholds[] = {{0.1, 1}}; thresholds[] = {{0.6, 4}, {0.35, 2}, {0.1, 1}};
selectionSpecific = 1; selectionSpecific = 1;
lethalDamage = 0.4;
}; };
class ropeburn { class ropeburn {
thresholds[] = {{0.1, 1}}; thresholds[] = {{0.1, 1}};

View File

@ -2,8 +2,4 @@
PREP(parseConfigForInjuries); PREP(parseConfigForInjuries);
PREP(getTypeOfDamage); PREP(getTypeOfDamage);
PREP(airwayHandler);
PREP(fracturesHandler);
PREP(internalInjuriesHandler);
PREP(woundsHandler); PREP(woundsHandler);
PREP(woundsHandlerSQF);

View File

@ -6,18 +6,11 @@ ADDON = false;
call FUNC(parseConfigForInjuries); 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), { [QEGVAR(medical_engine,woundReceived), {
params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"]; params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"];
private _typeOfDamage = _ammo call FUNC(getTypeOfDamage); 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); [_unit, EGVAR(medical,STATE_MACHINE)] call EFUNC(medical,addStateHandler);
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;

View File

@ -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];
};
};
};

View File

@ -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];
};

View File

@ -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

View File

@ -12,55 +12,6 @@
*/ */
#include "script_component.hpp" #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"; private _injuriesConfigRoot = configFile >> "ACE_Medical_Injuries";
// --- parse wounds // --- parse wounds
@ -74,36 +25,28 @@ private _classID = 0;
private _entry = _x; private _entry = _x;
private _className = configName _entry; private _className = configName _entry;
private _selections = GET_ARRAY(_entry >> "selections",[]); private _selections = GET_ARRAY(_entry >> "selections",["All"]);
private _bleedingRate = GET_NUMBER(_entry >> "bleedingRate",0); private _bleeding = GET_NUMBER(_entry >> "bleeding",0);
private _pain = GET_NUMBER(_entry >> "pain",0); private _pain = GET_NUMBER(_entry >> "pain",0);
private _minDamage = GET_NUMBER(_entry >> "minDamage",0); private _minDamage = GET_NUMBER(_entry >> "minDamage",0);
private _maxDamage = GET_NUMBER(_entry >> "maxDamage",-1); private _maxDamage = GET_NUMBER(_entry >> "maxDamage",-1);
private _causes = GET_ARRAY(_entry >> "causes",[]); private _causes = GET_ARRAY(_entry >> "causes",[]);
private _displayName = GET_STRING(_entry >> "name",_className); // @todo, don't translate in config 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 (count _causes > 0) then {
if !("Minor" call _fnc_parseSubClassWounds || "Medium" call _fnc_parseSubClassWounds || "Large" call _fnc_parseSubClassWounds) then { GVAR(woundClassNames) pushBack _className;
// There were no subclasses, so we will add this one instead. GVAR(woundsData) pushBack [_classID, _selections, _bleeding, _pain, [_minDamage, _maxDamage], _causes, _displayName, _causeLimping];
if (count _selections > 0 && {count _causes > 0}) then { _classID = _classID + 1;
GVAR(woundClassNames) pushBack _className;
GVAR(woundsData) pushBack [_classID, _selections, _bleedingRate, _pain, [_minDamage, _maxDamage], _causes, _displayName];
_classID = _classID + 1;
};
}; };
} forEach configProperties [_woundsConfig, "isClass _x"]; } forEach configProperties [_woundsConfig, "isClass _x"];
// --- parse fractures
//GVAR(fractureClassNames) = []; // unused
// --- parse damage types // --- parse damage types
GVAR(allDamageTypes) = []; // @todo, currently unused by handle damage (was GVAR(allAvailableDamageTypes)) 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; GVAR(allDamageTypesData) = [] call CBA_fnc_createNamespace;
// minimum lethal damage collection, mapped to damageTypes // minimum lethal damage collection, mapped to damageTypes
private _damageTypesConfig = _injuriesConfigRoot >> "damageTypes"; private _damageTypesConfig = _injuriesConfigRoot >> "damageTypes";
private _lethalDamageDefault = getNumber (_damageTypesConfig >> "lethalDamage");
private _thresholdsDefault = getArray (_damageTypesConfig >> "thresholds"); private _thresholdsDefault = getArray (_damageTypesConfig >> "thresholds");
private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionSpecific"); private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionSpecific");
@ -113,7 +56,6 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
private _className = configName _entry; private _className = configName _entry;
GVAR(allDamageTypes) pushBack _className; 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 // 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 = []; private _woundTypes = [];
@ -138,7 +80,7 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
private _extensionArgs = format [ private _extensionArgs = format [
"addDamageType,%1,%2,%3,%4,%5", "addDamageType,%1,%2,%3,%4,%5",
_className, _className,
GVAR(lethalDamages) select _forEachIndex, 1, //@todo remove 'minLethalDamage' from extension
_minDamageThresholds, _minDamageThresholds,
_amountThresholds, _amountThresholds,
_selectionSpecific _selectionSpecific

View File

@ -36,25 +36,43 @@ private _woundsCreated = [];
call compile _extensionOutput; 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; // The higher the nastiness likelihood the higher the change to get a painful and bloody wound
{ private _nastinessLikelihood = if (_damage > 1) then {
// Check if we have an id of the given class on the given bodypart already (_damage ^ 0.33)
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;
} else { } 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. (0.1 max _damage)
private _injury = _openWounds select _foundIndex;
_injury set [3, (_injury select 3) + 1];
}; };
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; } forEach _woundsCreated;
_unit setVariable [QEGVAR(medical,openWounds), _openWounds, true]; _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 // Only update if new wounds have been created
if (count _woundsCreated > 0) then { if (count _woundsCreated > 0) then {
_unit setVariable [QEGVAR(medical,lastUniqueWoundID), _woundID, true]; _unit setVariable [QEGVAR(medical,lastUniqueWoundID), _woundID, true];
[_unit] call EFUNC(medical,handleIncapacitation);
}; };
[_unit, _painToAdd] call EFUNC(medical,addPain); [_unit, _painLevel] call EFUNC(medical,adjustPainLevel);
[_unit, "hit", PAIN_TO_SCREAM(_painToAdd)] call EFUNC(medical_engine,playInjuredSound); [_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);

View File

@ -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);

View File

@ -18,8 +18,8 @@
#ifdef DEBUG_MODE_FULL #ifdef DEBUG_MODE_FULL
[QGVAR(woundReceived), { [QGVAR(woundReceived), {
diag_log _this; //diag_log _this;
systemChat str _this; //systemChat str _this;
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
#endif #endif

View File

@ -104,7 +104,13 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
// Check for falling damage. // Check for falling damage.
if (_ammo isEqualTo "") then { if (_ammo isEqualTo "") then {
if (velocity _unit select 2 < -2) 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"; _ammo = "#falling";
} else { } else {
// Assume collision damage. // Assume collision damage.

View File

@ -44,22 +44,22 @@ switch (toLower _bodyPart) do {
}; };
private _openWounds = _unit getVariable QEGVAR(medical,openWounds); 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; private _partIndex = ALL_BODY_PARTS find toLower _x;
{ {
_x params ["", "", "_bodyPartN", "_amountOf", "_percentageOpen"]; _x params ["", "", "_bodyPartN", "", "_bleeding", "_damage"];
if (_bodyPartN isEqualTo _partIndex) then { if (_bodyPartN isEqualTo _partIndex) then {
_bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _percentageOpen); _damageOnBodyPart = _damageOnBodyPart + _damage;
}; };
} forEach _openWounds; } forEach _openWounds;
// report maximum of both legs or arms // report maximum of both legs or arms
_bloodLossOnAffectedBodyParts = _bloodLossOnAffectedBodyParts max _bloodLossOnBodyPart; _damageOnAffectedBodyParts = _damageOnAffectedBodyParts max _damageOnBodyPart;
} forEach _affectedBodyParts; } forEach _affectedBodyParts;
[_unit, _bodyPart, _bloodLossOnAffectedBodyParts > 0] call FUNC(damageBodyPart); [_unit, _bodyPart, _damageOnAffectedBodyParts > 0.35] call FUNC(damageBodyPart);

View File

@ -48,7 +48,7 @@ class CfgVehicles {
displayName = ECSTRING(medical,Actions_Medical); displayName = ECSTRING(medical,Actions_Medical);
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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"; condition = "true";
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
#include "InteractionBodyParts.hpp" #include "InteractionBodyParts.hpp"

View File

@ -2,7 +2,7 @@ class ACE_Head {
displayName = ECSTRING(interaction,Head); displayName = ECSTRING(interaction,Head);
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,0,_this select 3)] call FUNC(modifyAction));
condition = "true"; condition = "true";
runOnHover = 1; runOnHover = 1;
@ -13,7 +13,7 @@ class ACE_Torso {
condition = "true"; condition = "true";
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,1,_this select 3)] call FUNC(modifyAction));
showDisabled = 1; showDisabled = 1;
priority = 2; priority = 2;
@ -23,7 +23,7 @@ class ACE_ArmLeft {
displayName = ECSTRING(interaction,ArmLeft); displayName = ECSTRING(interaction,ArmLeft);
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,2,_this select 3)] call FUNC(modifyAction));
condition = "true"; condition = "true";
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
@ -32,7 +32,7 @@ class ACE_ArmRight {
displayName = ECSTRING(interaction,ArmRight); displayName = ECSTRING(interaction,ArmRight);
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,3,_this select 3)] call FUNC(modifyAction));
condition = "true"; condition = "true";
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
@ -41,7 +41,7 @@ class ACE_LegLeft {
displayName = ECSTRING(interaction,LegLeft); displayName = ECSTRING(interaction,LegLeft);
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,4,_this select 3)] call FUNC(modifyAction));
condition = "true"; condition = "true";
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);
@ -50,7 +50,7 @@ class ACE_LegRight {
displayName = ECSTRING(interaction,LegRight); displayName = ECSTRING(interaction,LegRight);
runOnHover = 1; runOnHover = 1;
exceptions[] = {"isNotInside", "isNotSitting"}; 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)); modifierFunction = QUOTE([ARR_4(_target,_player,5,_this select 3)] call FUNC(modifyAction));
condition = "true"; condition = "true";
icon = QPATHTOEF(medical,UI\icons\medical_cross.paa); icon = QPATHTOEF(medical,UI\icons\medical_cross.paa);

View File

@ -7,7 +7,7 @@ GVAR(lastOpenedOn) = -1;
GVAR(pendingReopen) = false; GVAR(pendingReopen) = false;
["ace_settingsInitialized", { ["ace_settingsInitialized", {
if (EGVAR(medical,level) > 0 && {EGVAR(medical,menuTypeStyle) == 0}) then { if (EGVAR(medical,menuTypeStyle) == 0) then {
[] call FUNC(collectActions3D); [] call FUNC(collectActions3D);
}; };
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;

View File

@ -4,8 +4,9 @@
* *
* Arguments: * Arguments:
* 0: selection bloodloss <ARRAY> * 0: selection bloodloss <ARRAY>
* 1: damaged (array of bools) <ARRAY> * 1: selection damage <ARRAY>
* 2: display <DISPLAY> * 2: selection torniquet <ARRAY>
* 3: display <DISPLAY>
* *
* Return Value: * Return Value:
* None * None
@ -17,7 +18,7 @@
*/ */
#include "script_component.hpp" #include "script_component.hpp"
params ["_selectionBloodLoss", "_damaged", "_display"]; params ["_selectionBloodLoss", "_selectionDamage", "_selectionTourniquet", "_display"];
// Handle the body image coloring // Handle the body image coloring
private _availableSelections = [50, 51, 52, 53, 54, 55]; private _availableSelections = [50, 51, 52, 53, 54, 55];
@ -26,16 +27,22 @@ private _availableSelections = [50, 51, 52, 53, 54, 55];
private _green = 1; private _green = 1;
private _blue = 1; private _blue = 1;
if (_x > 0) then { private _torniquet = _selectionTourniquet select _forEachIndex;
if (_damaged select _forEachIndex) then { if (_torniquet > 0) then {
_green = (0.9 - _x) max 0; _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; _blue = _green;
} else { } else {
_green = (0.9 - _x) max 0; private _damage = _selectionDamage select _forEachIndex;
_green = 0 max (0.9 - _damage);
_red = _green; _red = _green;
//_blue = _green;
}; };
}; };
(_display displayCtrl (_availableSelections select _forEachIndex)) ctrlSetTextColor [_red, _green, _blue, 1.0]; (_display displayCtrl _x) ctrlSetTextColor [_red, _green, _blue, 1.0];
} forEach _selectionBloodLoss; } forEach _availableSelections;

View File

@ -18,15 +18,13 @@
params ["_target", "_display"]; 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");}; if (isNil "_display" || {isNull _display}) exitWith {ERROR("No display");};
_selectionN = GVAR(selectedBodyPart); private _selectionN = GVAR(selectedBodyPart);
if (_selectionN < 0 || {_selectionN > 5}) exitWith {}; if (_selectionN < 0 || {_selectionN > 5}) exitWith {};
_genericMessages = []; private _genericMessages = [];
_partText = [ELSTRING(medical,Head), ELSTRING(medical,Torso), ELSTRING(medical,LeftArm) ,ELSTRING(medical,RightArm) ,ELSTRING(medical,LeftLeg), ELSTRING(medical,RightLeg)] select _selectionN; 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]]; _genericMessages pushBack [localize _partText, [1, 1, 1, 1]];
if (_target getVariable [QEGVAR(medical,isBleeding), false]) then { 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]]; _genericMessages pushBack [localize ELSTRING(medical,Status_Pain), [1, 1, 1, 1]];
}; };
_totalIvVolume = 0; private _totalIvVolume = 0;
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []]; private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
{ {
_x params ["_bagVolumeRemaining"]; _x params ["_bagVolumeRemaining"];
@ -56,96 +54,64 @@ if (_totalIvVolume >= 1) then {
_genericMessages pushBack [format [localize ELSTRING(medical,receivingIvVolume), floor _totalIvVolume], [1, 1, 1, 1]]; _genericMessages pushBack [format [localize ELSTRING(medical,receivingIvVolume), floor _totalIvVolume], [1, 1, 1, 1]];
}; };
_damaged = [false, false, false, false, false, false]; private _selectionTourniquet = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]];
_selectionBloodLoss = [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))} _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"];
_openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; _selectionBloodLoss set [_bodyPartN, (_selectionBloodLoss select _bodyPartN) + (20 * (_bleeding * _amountOf))];
private "_amountOf"; _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage];
{ if (_selectionN == _bodyPartN) then {
_amountOf = _x select 3; // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this]
// Find how much this bodypart is bleeding
if (_amountOf > 0) then { if (_amountOf > 0) then {
_damaged set [_x select 2, true]; if (_amountOf >= 1) then {
_selectionBloodLoss set [_x select 2, (_selectionBloodLoss select (_x select 2)) + (20 * ((_x select 4) * _amountOf))]; // TODO localization
_allInjuryTexts pushBack [format["%2x %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6, ceil _amountOf], [1,1,1,1]];
if (_selectionN == (_x select 2)) then { } else {
// Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] // TODO localization
if (_amountOf >= 1) then { _allInjuryTexts pushBack [format["Partial %1", (EGVAR(medical_damage,woundsData) select _woundClassID) select 6], [1,1,1,1]];
// 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]];
};
}; };
}; };
} 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, _genericMessages, _allInjuryTexts] call FUNC(updateInformationLists);
[_display, _target getVariable [QEGVAR(medical,logFile_activity_view), []]] call FUNC(updateActivityLog); [_display, _target getVariable [QEGVAR(medical,logFile_activity_view), []]] call FUNC(updateActivityLog);

View File

@ -13,7 +13,6 @@ class GVAR(Actions) {
treatmentTimeSelfCoef = 1; treatmentTimeSelfCoef = 1;
items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}}; items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}};
condition = QUOTE(!EGVAR(medical,advancedBandages)); condition = QUOTE(!EGVAR(medical,advancedBandages));
patientStateCondition = 0;
itemConsumed = 1; itemConsumed = 1;
callbackSuccess = QFUNC(treatmentBandage); callbackSuccess = QFUNC(treatmentBandage);
callbackFailure = ""; callbackFailure = "";
@ -76,7 +75,7 @@ class GVAR(Actions) {
displayNameProgress = ECSTRING(medical,Applying_Tourniquet); displayNameProgress = ECSTRING(medical,Applying_Tourniquet);
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"}; allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
items[] = {"ACE_tourniquet"}; items[] = {"ACE_tourniquet"};
treatmentTime = 4; treatmentTime = 5;
callbackSuccess = QFUNC(treatmentTourniquet); callbackSuccess = QFUNC(treatmentTourniquet);
condition = QUOTE(EGVAR(medical,advancedBandages) && {!([ARR_2(_target,_bodyPart)] call EFUNC(medical,hasTourniquetAppliedTo))}); condition = QUOTE(EGVAR(medical,advancedBandages) && {!([ARR_2(_target,_bodyPart)] call EFUNC(medical,hasTourniquetAppliedTo))});
litter[] = {}; litter[] = {};
@ -97,7 +96,7 @@ class GVAR(Actions) {
category = "medication"; category = "medication";
items[] = {"ACE_morphine"}; items[] = {"ACE_morphine"};
condition = ""; condition = "";
treatmentTime = 10; treatmentTime = 9;
callbackSuccess = QFUNC(treatmentMedication); callbackSuccess = QFUNC(treatmentMedication);
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
litter[] = { {"All", "", {"ACE_MedicalLitter_morphine"}} }; litter[] = { {"All", "", {"ACE_MedicalLitter_morphine"}} };
@ -106,12 +105,14 @@ class GVAR(Actions) {
class Adenosine: Morphine { class Adenosine: Morphine {
displayName = ECSTRING(medical,Inject_Adenosine); displayName = ECSTRING(medical,Inject_Adenosine);
displayNameProgress = ECSTRING(medical,Injecting_Adenosine); displayNameProgress = ECSTRING(medical,Injecting_Adenosine);
condition = QEGVAR(medical,advancedMedication);
items[] = {"ACE_adenosine"}; items[] = {"ACE_adenosine"};
litter[] = { {"All", "", {"ACE_MedicalLitter_adenosine"}} }; litter[] = { {"All", "", {"ACE_MedicalLitter_adenosine"}} };
}; };
class Atropine: Morphine { class Atropine: Morphine {
displayName = ECSTRING(medical,Inject_Atropine); displayName = ECSTRING(medical,Inject_Atropine);
displayNameProgress = ECSTRING(medical,Injecting_Atropine); displayNameProgress = ECSTRING(medical,Injecting_Atropine);
condition = QEGVAR(medical,advancedMedication);
items[] = {"ACE_atropine"}; items[] = {"ACE_atropine"};
litter[] = { {"All", "", {"ACE_MedicalLitter_atropine"}} }; litter[] = { {"All", "", {"ACE_MedicalLitter_atropine"}} };
}; };
@ -205,6 +206,7 @@ class GVAR(Actions) {
class CheckBloodPressure: CheckPulse { class CheckBloodPressure: CheckPulse {
displayName = ECSTRING(medical,Actions_CheckBloodPressure); displayName = ECSTRING(medical,Actions_CheckBloodPressure);
displayNameProgress = ECSTRING(medical,Check_Bloodpressure_Content); displayNameProgress = ECSTRING(medical,Check_Bloodpressure_Content);
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
callbackSuccess = QFUNC(actionCheckBloodPressure); callbackSuccess = QFUNC(actionCheckBloodPressure);
}; };
class CheckResponse: CheckPulse { class CheckResponse: CheckPulse {
@ -258,48 +260,42 @@ class GVAR(Actions) {
litter[] = {}; litter[] = {};
}; };
/* class SurgicalKit: fieldDressing {
class Advanced { displayName = ECSTRING(medical,Use_SurgicalKit);
class SurgicalKit: fieldDressing { displayNameProgress = ECSTRING(medical,Stitching);
displayName = ECSTRING(medical,Use_SurgicalKit); category = "advanced";
displayNameProgress = ECSTRING(medical,Stitching); items[] = {"ACE_surgicalKit"};
category = "advanced"; treatmentLocations[] = {QEGVAR(medical,useLocation_SurgicalKit)};
items[] = {"ACE_surgicalKit"}; allowSelfTreatment = 0;
treatmentLocations[] = {QEGVAR(medical,useLocation_SurgicalKit)}; requiredMedic = QEGVAR(medical,medicSetting_SurgicalKit);
allowSelfTreatment = 0; treatmentTime = QUOTE(count (_target getVariable [ARR_2('EGVAR(medical,bandagedWounds)',[])]) * 5);
requiredMedic = QEGVAR(medical,medicSetting_SurgicalKit); callbackSuccess = "";
patientStateCondition = QEGVAR(medical,useCondition_SurgicalKit); callbackProgress = QFUNC(treatmentSurgicalKit_onProgress);
treatmentTime = QUOTE(count (_target getVariable [ARR_2('EGVAR(medical,bandagedWounds)',[])]) * 5); itemConsumed = QEGVAR(medical,consumeItem_SurgicalKit);
callbackSuccess = ""; animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
callbackProgress = QFUNC(treatmentSurgicalKit_onProgress); litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"} }};
itemConsumed = QEGVAR(medical,consumeItem_SurgicalKit); };
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1"; class PersonalAidKit: BasicBandage {
litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"} }}; displayName = ECSTRING(medical,Use_Aid_Kit);
}; displayNameProgress = ECSTRING(medical,TreatmentAction);
class PersonalAidKit: fieldDressing { category = "advanced";
displayName = ECSTRING(medical,Use_Aid_Kit); condition = QUOTE(_target call EFUNC(medical,isInStableCondition));
displayNameProgress = ECSTRING(medical,TreatmentAction); items[] = {"ACE_personalAidKit"};
category = "advanced"; treatmentLocations[] = {QEGVAR(medical,useLocation_PAK)};
items[] = {"ACE_personalAidKit"}; requiredMedic = QEGVAR(medical,medicSetting_PAK);
treatmentLocations[] = {QEGVAR(medical,useLocation_PAK)}; treatmentTime = QUOTE(_target call FUNC(treatmentFullHealTreatmentTime));
allowSelfTreatment = 0; callbackSuccess = QFUNC(treatmentFullHeal);
requiredMedic = QEGVAR(medical,medicSetting_PAK); itemConsumed = QEGVAR(medical,consumeItem_PAK);
patientStateCondition = QEGVAR(medical,useCondition_PAK); animationPatient = "";
treatmentTime = QUOTE(_target call FUNC(treatmentFullHealTreatmentTime)); animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback";
callbackSuccess = QFUNC(treatmentFullHeal); animationCaller = "AinvPknlMstpSlayW[wpn]Dnon_medicOther";
itemConsumed = QEGVAR(medical,consumeItem_PAK); animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther";
animationPatient = ""; animationCallerSelf = "";
animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback"; animationCallerSelfProne = "";
animationCaller = "AinvPknlMstpSlayW[wpn]Dnon_medicOther"; litter[] = { {"All", "", {"ACE_MedicalLitter_gloves"}},
animationCallerProne = "AinvPpneMstpSlayW[wpn]Dnon_medicOther"; {"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
animationCallerSelf = ""; {"All", "_bloodLossOnBodyPart > 0", {{"ACE_MedicalLitterBase", "ACE_MedicalLitter_bandage1", "ACE_MedicalLitter_bandage2", "ACE_MedicalLitter_bandage3"}}},
animationCallerSelfProne = ""; {"All", "_bloodLossOnBodyPart <= 0", {"ACE_MedicalLitter_clean"}}
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"}}
};
}; };
}; };
*/
}; };

View File

@ -75,18 +75,6 @@ if (isText (_config >> "condition")) then {
if !(_condition) exitWith {false}; 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 // check allowed locations
private _locations = getArray (_config >> "treatmentLocations") apply {toLower _x}; private _locations = getArray (_config >> "treatmentLocations") apply {toLower _x};

View File

@ -20,38 +20,19 @@ _unit removeItems "FirstAidKit";
private _countMedikit = {_x == "Medikit"} count items _unit; private _countMedikit = {_x == "Medikit"} count items _unit;
_unit removeItems "Medikit"; _unit removeItems "Medikit";
if (EGVAR(medical,level) >= 2) then { for "_i" from 1 to _countFirstAidKit do {
// --- advanced _unit addItem "ACE_fieldDressing";
for "" from 1 to _countFirstAidKit do { _unit addItem "ACE_packingBandage";
_unit addItem "ACE_fieldDressing"; _unit addItem "ACE_morphine";
_unit addItem "ACE_packingBandage"; _unit addItem "ACE_tourniquet";
_unit addItem "ACE_morphine"; };
_unit addItem "ACE_tourniquet";
}; for "_i" from 1 to _countMedikit do {
_unit addItemToBackpack "ACE_fieldDressing";
for "" from 1 to _countMedikit do { _unit addItemToBackpack "ACE_packingBandage";
_unit addItemToBackpack "ACE_fieldDressing"; _unit addItemToBackpack "ACE_packingBandage";
_unit addItemToBackpack "ACE_packingBandage"; _unit addItemToBackpack "ACE_epinephrine";
_unit addItemToBackpack "ACE_packingBandage"; _unit addItemToBackpack "ACE_morphine";
_unit addItemToBackpack "ACE_epinephrine"; _unit addItemToBackpack "ACE_salineIV_250";
_unit addItemToBackpack "ACE_morphine"; _unit addItemToBackpack "ACE_tourniquet";
_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";
};
}; };

View File

@ -4,7 +4,7 @@
* *
* Arguments: * Arguments:
* 0: The Unit <OBJECT> * 0: The Unit <OBJECT>
* 1: Show <BOOL> (default: true) * 1: Show <NUMBER> (default: 0)
* 2: Selection <NUMBER> (default: 0) * 2: Selection <NUMBER> (default: 0)
* *
* ReturnValue: * ReturnValue:
@ -16,15 +16,12 @@
#include "script_component.hpp" #include "script_component.hpp"
#define MAX_DISTANCE 10 #define MAX_DISTANCE 10
// Exit for basic medical params ["_target", ["_show", 0], ["_selectionN", 0]];
if (EGVAR(medical,level) < 2) exitWith {};
params ["_target", ["_show", true], ["_selectionN", 0]];
GVAR(currentSelectedSelectionN) = [0, _selectionN] select (IS_SCALAR(_selectionN)); GVAR(currentSelectedSelectionN) = [0, _selectionN] select (IS_SCALAR(_selectionN));
GVAR(displayPatientInformationTarget) = [ObjNull, _target] select _show; GVAR(displayPatientInformationTarget) = [ObjNull, _target] select _show;
if (_show) then { if (_show == 1) then {
("ACE_MedicalRscDisplayInformation" call BIS_fnc_rscLayer) cutRsc [QGVAR(DisplayInformation),"PLAIN"]; ("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] // 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 { if (_amountOf >= 1) then {
// TODO localization // 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 { } else {
// TODO localization // 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 > 0) then {
if (_amountOf >= 1) then { if (_amountOf >= 1) then {
// TODO localization // 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 { } else {
// TODO localization // 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]];
}; };
}; };
}; };

View File

@ -74,8 +74,9 @@ private _bandagedInjury = [];
} forEach _bandagedWounds; } forEach _bandagedWounds;
if !(_exist) then { if !(_exist) then {
// [ID, classID, bodypart, percentage treated, bloodloss rate] // [ID, classID, bodypart, percentage treated, bloodloss, damage]
_bandagedInjury = [_injury select 0, _injury select 1, _injury select 2, _impact, _injury select 4]; _bandagedInjury = +_injury;
_bandagedInjury set [3, _impact];
_bandagedWounds pushBack _bandagedInjury; _bandagedWounds pushBack _bandagedInjury;
}; };

View File

@ -43,7 +43,7 @@ if (!_foundEntry) then {
private _usedMeds = _target getVariable [_variable, 0]; 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); [_target] call EFUNC(medical,setDead);
}; };
@ -58,7 +58,7 @@ private _hasOverDosed = 0;
} forEach _allUsedMedication; } forEach _allUsedMedication;
} forEach _incompatabileMeds; } forEach _incompatabileMeds;
if (_hasOverDosed > 0 && GVAR(enableOverdosing)) then { if (_hasOverDosed > 0) then {
private _medicationConfig = (configFile >> "ace_medical_treatment" >> "Medication"); private _medicationConfig = (configFile >> "ace_medical_treatment" >> "Medication");
private _onOverDose = getText (_medicationConfig >> "onOverDose"); private _onOverDose = getText (_medicationConfig >> "onOverDose");
if (isClass (_medicationConfig >> _className)) then { if (isClass (_medicationConfig >> _className)) then {

View File

@ -156,6 +156,8 @@ if (isNumber (_config >> "treatmentTime")) then {
}; };
TRACE_1("",_treatmentTime); TRACE_1("",_treatmentTime);
if (_treatmentTime == 0) exitWith { false };
// speed up animation depending on treatment time // speed up animation depending on treatment time
if (!isNil "_animDuration") then { if (!isNil "_animDuration") then {
[QEGVAR(common,setAnimSpeedCoef), [_caller, _animDuration / _treatmentTime]] call CBA_fnc_globalEvent; [QEGVAR(common,setAnimSpeedCoef), [_caller, _animDuration / _treatmentTime]] call CBA_fnc_globalEvent;

View File

@ -99,96 +99,9 @@ _openWounds set [_mostEffectiveSpot, _mostEffectiveInjury];
_target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; _target setVariable [QEGVAR(medical,openWounds), _openWounds, true];
[_target, _bodyPart] call EFUNC(medical_engine,updateBodyPartVisuals);
// Handle the reopening of bandaged wounds // 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); [_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 true

View File

@ -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,inCardiacArrest), nil,true];
_target setVariable [QEGVAR(medical,heartRate), 40]; _target setVariable [QEGVAR(medical,heartRate), 40];
_target setVariable [QEGVAR(medical,bloodPressure), [50,70]]; _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); [_target, "activity", ELSTRING(medical,Activity_CPR), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog);

View File

@ -15,7 +15,42 @@
params ["_caller", "_target"]; 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,pain), 0, true];
_target setVariable [QEGVAR(medical,morphine), 0, true]; _target setVariable [QEGVAR(medical,morphine), 0, true];
_target setVariable [QEGVAR(medical,bloodVolume), DEFAULT_BLOOD_VOLUME, true]; _target setVariable [QEGVAR(medical,bloodVolume), DEFAULT_BLOOD_VOLUME, true];
@ -26,7 +61,7 @@ if (alive _target) exitWith {
// wounds and injuries // wounds and injuries
_target setVariable [QEGVAR(medical,openWounds), [], true]; _target setVariable [QEGVAR(medical,openWounds), [], true];
_target setVariable [QEGVAR(medical,bandagedWounds), [], true]; _target setVariable [QEGVAR(medical,bandagedWounds), [], true];
_target setVariable [QEGVAR(medical,internalWounds), [], true]; _target setVariable [QEGVAR(medical,stitchedWounds), [], true];
// vitals // vitals
_target setVariable [QEGVAR(medical,heartRate), 80]; _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,bloodPressure), [80, 120]];
_target setVariable [QEGVAR(medical,peripheralResistance), 100]; _target setVariable [QEGVAR(medical,peripheralResistance), 100];
// fractures
_target setVariable [QEGVAR(medical,fractures), []];
// IVs // IVs
_target setVariable [QEGVAR(medical,ivBags), nil, true]; _target setVariable [QEGVAR(medical,ivBags), nil, true];
// damage storage // damage storage
_target setVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0], true]; _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 // generic medical admin
_target setVariable [QEGVAR(medical,addedToUnitLoop), false, true];
_target setVariable [QEGVAR(medical,inCardiacArrest), false, true]; _target setVariable [QEGVAR(medical,inCardiacArrest), false, true];
_target setVariable [QEGVAR(medical,inReviveState), 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,hasLostBlood), 0, true];
_target setVariable [QEGVAR(medical,isBleeding), false, true]; _target setVariable [QEGVAR(medical,isBleeding), false, true];
_target setVariable [QEGVAR(medical,hasPain), false, true]; _target setVariable [QEGVAR(medical,hasPain), false, true];
_target setVariable [QEGVAR(medical,painSuppress), 0, true]; _target setVariable [QEGVAR(medical,painSuppress), 0, true];
_target setVariable [QGVAR(partialHealCounter), 0, true];
// medication // medication
private _allUsedMedication = _target getVariable [QEGVAR(medical,allUsedMedication), []]; private _allUsedMedication = _target getVariable [QEGVAR(medical,allUsedMedication), []];
@ -65,9 +92,13 @@ if (alive _target) exitWith {
_target setVariable [_x select 0, nil]; _target setVariable [_x select 0, nil];
} forEach _allUsedMedication; } forEach _allUsedMedication;
[_unit, false] call EFUNC(medical_engine,setLimping);
// Resetting damage // Resetting damage
_target setDamage 0; _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

View File

@ -32,7 +32,7 @@ if !(EGVAR(medical,advancedMedication)) exitWith {
}; };
if (_className == "Epinephrine") exitWith { if (_className == "Epinephrine") exitWith {
[_target, false] call EFUNC(medical,setUnconscious); [QEGVAR(medical,WakeUp), _target] call CBA_fnc_localEvent;
}; };
}; };

View File

@ -20,14 +20,17 @@ params ["_args", "_elapsedTime", "_totalTime"];
_args params ["_caller", "_target"]; _args params ["_caller", "_target"];
private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; 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 //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 }; if (count _bandagedWounds == 0) exitWith { false };
//Has enough time elapsed that we can close another wound? //Has enough time elapsed that we can close another wound?
if (_totalTime - _elapsedTime <= (count _bandagedWounds - 1) * 5) then { 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,bandagedWounds), _bandagedWounds, true];
_target setVariable [QEGVAR(medical,stitchedWounds), _stitchedWounds, true];
}; };
true true

View File

@ -16,9 +16,6 @@
params ["_target", "_tourniquetItem", "_bodyPart"]; 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; private _partIndex = ALL_BODY_PARTS find toLower _bodyPart;
// Place a tourniquet on the bodypart // Place a tourniquet on the bodypart

View File

@ -68,9 +68,4 @@ _args call _callback;
_args pushBack _bloodLossOnBodyPart; _args pushBack _bloodLossOnBodyPart;
_args call FUNC(litterCreate); _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; ["ace_treatmentSucceded", [_caller, _target, _bodyPart, _className]] call CBA_fnc_localEvent;