blood and unconsciousness fixes

This commit is contained in:
commy2 2016-10-12 21:59:32 +02:00
parent be71e6fa7b
commit a5d070f829
11 changed files with 93 additions and 82 deletions

View File

@ -257,11 +257,6 @@ class ACE_Settings {
typeName = "BOOL";
value = 0;
};
class GVAR(moveUnitsFromGroupOnUnconscious) {
category = CSTRING(Category_Medical);
typeName = "BOOL";
value = 0;
};
class GVAR(menuTypeStyle) {
category = CSTRING(Category_Medical);
displayName = CSTRING(menuTypeDisplay);

View File

@ -10,19 +10,17 @@
*
* Public: No
*/
#include "script_component.hpp"
// TODO Only use this calculation if medium or higher, otherwise use vanilla calculations (for basic medical).
params ["_unit"];
private _totalBloodLoss = 0;
private _tourniquets = _unit getVariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
{
if ((_tourniquets select (_x select 2)) == 0) then {
if (_tourniquets select (_x select 2) == 0) then {
// total bleeding ratio * percentage of injury left
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
// (((BLOODLOSS_SMALL_WOUNDS * (_x select 0))) + ((BLOODLOSS_MEDIUM_WOUNDS * (_x select 1))) + ((BLOODLOSS_LARGE_WOUNDS * (_x select 2))) * (_cardiacOutput / DEFAULT_CARDIAC_OUTPUT));
};
} forEach (_unit getVariable [QGVAR(openWounds), []]);

View File

@ -11,29 +11,33 @@
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_syncValues"];
private _bloodVolume = _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME];
private _bloodVolumeChange = -([_unit] call FUNC(getBloodLoss));
private _bloodVolumeChange = -(_unit call FUNC(getBloodLoss));
if (!isNil {_unit getVariable QGVAR(ivBags)}) then {
if (_bloodVolume < 100) then {
if (_bloodVolume < DEFAULT_BLOOD_VOLUME) then {
private _bloodBags = _unit getVariable [QGVAR(ivBags), []];
_bloodBags = _bloodBags apply {
_x params ["_bagVolumeRemaining"];
private _bagChange = IV_CHANGE_PER_SECOND min _bagVolumeRemaining; // absolute value of the change in miliLiters
_bagVolumeRemaining = _bagVolumeRemaining - _bagChange;
_bloodVolumeChange = _bloodVolumeChange + _bagChange;
_bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000);
if (_bagVolumeRemaining < 0.01) then {
[]
} else {
[_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 {
@ -44,4 +48,4 @@ if (!isNil {_unit getVariable QGVAR(ivBags)}) then {
};
};
_bloodVolumeChange;
_bloodVolumeChange

View File

@ -14,16 +14,18 @@
params ["_unit", "_interval"];
TRACE_3("ACE_DEBUG",_unit,_interval,_unit);
if (_interval == 0) exitWith {};
private _lastTimeValuesSynced = _unit getVariable [QGVAR(lastMomentValuesSynced), 0];
private _syncValues = (CBA_missionTime - _lastTimeValuesSynced >= (10 + floor(random(10))) && GVAR(keepLocalSettingsSynced));
private _syncValues = (CBA_missionTime - _lastTimeValuesSynced >= 10 + floor(random(10))) && GVAR(keepLocalSettingsSynced);
if (_syncValues) then {
_unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime];
};
private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME]) + ([_unit, _syncValues] call FUNC(getBloodVolumeChange));
_bloodVolume = _bloodVolume max 0;
_bloodVolume = (_bloodVolume max 0) min DEFAULT_BLOOD_VOLUME;
_unit setVariable [QGVAR(bloodVolume), _bloodVolume, _syncValues];
@ -45,12 +47,13 @@ if (_bloodVolume < BLOOD_VOLUME_HAS_LOST_SOME) then {
};
};
TRACE_3("ACE_DEBUG",[_unit] call FUNC(getBloodLoss),_unit getVariable QGVAR(isBleeding),_unit);
private _bloodLoss = [_unit] call FUNC(getBloodLoss);
private _bloodLoss = _unit call FUNC(getBloodLoss);
TRACE_3("ACE_DEBUG",_bloodLoss,_unit getVariable QGVAR(isBleeding),_unit);
if (_bloodLoss > 0) then {
_unit setVariable [QGVAR(bloodloss), _bloodLoss, _syncValues];
[_unit, "TakenInjury"] call FUNC(stateEvent);
if !(_unit getVariable [QGVAR(isBleeding), false]) then {
_unit setVariable [QGVAR(isBleeding), true, true];
};
@ -77,13 +80,12 @@ if (_bloodVolume < BLOOD_VOLUME_DEAD) exitWith {
};
if ([_unit] call EFUNC(common,isAwake)) then {
if (_bloodVolume < BLOOD_VOLUME_UNCONSCIOUS) then {
if (random(1) > 0.9) then {
[_unit, true, 15 + random(20)] call FUNC(setUnconscious);
};
if (_bloodVolume < BLOOD_VOLUME_UNCONSCIOUS && {random 1 < BLOOD_LOSS_KNOCK_OUT_CHANCE}) exitWith {
[_unit, true, BLOOD_LOSS_KNOCK_OUT_DURATION] call FUNC(setUnconscious);
};
};
/*
if (GVAR(level) == 1) then {
TRACE_5("ACE_DEBUG_BASIC_VITALS",_painStatus,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
// reduce pain
@ -96,8 +98,10 @@ if (GVAR(level) == 1) 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);
@ -142,3 +146,4 @@ if (GVAR(level) >= 2) then {
};
};
};
*/

View File

@ -9,7 +9,7 @@
* 3: Force AI Unconscious (skip random death chance) <BOOL> (default: false)
*
* ReturnValue:
* nil
* Success? <BOOLEAN>
*
* Example:
* [bob, true] call ace_medical_fnc_setUnconscious;
@ -19,36 +19,43 @@
#include "script_component.hpp"
#define DEFAULT_DELAY (round(random(10)+5))
// only run this after the settings are initialized
if !(EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(setUnconscious), _this];
};
params ["_unit", ["_set", true], ["_minUnconsciousTime", DEFAULT_DELAY], ["_force", false]];
params ["_unit", ["_knockOut", true], ["_minUnconsciousTime", DEFAULT_KNOCK_OUT_DELAY], ["_force", false]];
if (_set isEqualTo (_unit getVariable ["ACE_isUnconscious", false])) exitWith {};
if (isNull _unit || {!(_unit isKindOf "CAManBase")}) exitWith {false};
if !(_set) exitWith {
_unit setVariable ["ACE_isUnconscious", false, true];
if (!local _unit) exitWith {
[QGVAR(setUnconscious), [_unit, _knockOut, _minUnconsciousTime, _force], _unit] call CBA_fnc_targetEvent;
true
};
// use maximum for wake up time
if (_knockOut) then {
_unit setVariable [QGVAR(wakeUpTime), (CBA_missionTime + _minUnconsciousTime) max (_unit getVariable [QGVAR(wakeUpTime), 0])];
};
if (_knockOut isEqualTo (_unit getVariable [QGVAR(isUnconscious), false])) exitWith {false};
// --- wake up
if !(_knockOut) exitWith {
_unit setVariable [QGVAR(isUnconscious), false, true];
if (_unit getVariable [QGVAR(inReviveState), false]) then {
_unit setVariable [QGVAR(inReviveState), nil, true];
};
[_unit, false] call EFUNC(medical_engine,setUnconsciousAnim);
["ace_unconscious", [_unit, false]] call CBA_fnc_globalEvent;
true
};
if (isNull _unit || {!(_unit isKindOf "CAManBase")}) exitWith {};
if (!local _unit) exitWith {
[QGVAR(setUnconscious), [_unit, _set, _minUnconsciousTime, _force], _unit] call CBA_fnc_targetEvent;
};
_unit setVariable ["ACE_isUnconscious", true, true];
// --- knock out
_unit setVariable [QGVAR(isUnconscious), true, true];
if (_unit == ACE_player) then {
if (visibleMap) then {openMap false};
@ -59,6 +66,7 @@ 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 {
@ -71,37 +79,25 @@ if (!([_unit, GVAR(remoteControlledAI)] call EFUNC(common,isPlayer)) && !_force)
};
if (_isDead) exitWith {};
*/
// So the AI does not get stuck, we are moving the unit to a temp group on its own.
// Unconscious units shouldn't be put in another group #527:
if (GVAR(moveUnitsFromGroupOnUnconscious)) then {
[_unit, true, "ACE_isUnconscious", side group _unit] call EFUNC(common,switchToGroupSide);
};
[_unit, true] call EFUNC(medical_engine,setUnconsciousAnim);
[_unit, "Unconscious", []] call FUNC(stateEvent);
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent;
// Delay Unconscious so the AI dont instant stop shooting on the unit #3121
// auto wake up
[{
params ["_unit"];
if (_unit getVariable ["ACE_isUnconscious", false]) then {
[_unit, "setCaptive", "ace_unconscious", true] call EFUNC(common,statusEffect_set);
};
}, _unit, 3] call CBA_fnc_waitAndExecute;
private _time = _unit getVariable [QGVAR(wakeUpTime), 0];
[_unit, true] call EFUNC(medical_engine,setUnconsciousAnim);
[_unit, "Unconscious", []] call FUNC(stateEvent);
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent;
// auto wake up, testing @todo
[{
params ["_unit", "_time"];
!(_unit getVariable ["ACE_isUnconscious", false]) || {CBA_missionTime > _time}
!(_unit getVariable [QGVAR(isUnconscious), false]) || {CBA_missionTime > _time}
}, {
params ["_unit"];
if (_unit getVariable ["ACE_isUnconscious", false]) then {
if (_unit getVariable [QGVAR(isUnconscious), false]) then {
[_unit, false] call FUNC(setUnconscious);
};
}, [_unit, CBA_missionTime + _minUnconsciousTime]] call CBA_fnc_waitUntilAndExecute;
}, _unit] call CBA_fnc_waitUntilAndExecute;
true

View File

@ -19,14 +19,22 @@
// 0.077 l/kg * 80kg = 6.16l
#define DEFAULT_BLOOD_VOLUME 6.0 // in liters
#define BLOOD_VOLUME_HAS_LOST_SOME 5.900 // lost 100ml
#define BLOOD_VOLUME_HAS_LOST_MUCH 5.500 // lost 500ml
#define BLOOD_VOLUME_HAS_LOST_SOME 5.700 // lost 5% blood, Class I Hemorrhage
#define BLOOD_VOLUME_HAS_LOST_MUCH 5.100 // lost 15% blood, Class II Hemorrhage
#define BLOOD_VOLUME_UNCONSCIOUS 3.6 // in liters
#define BLOOD_VOLUME_DEAD 1.8 // in liters
#define BLOOD_VOLUME_CARDIAC_ARREST 1.2 // in liters
#define BLOOD_VOLUME_UNCONSCIOUS 4.200 // lost 30% blood, Class III Hemorrhage
#define BLOOD_VOLUME_DEAD 3.600 // lost 40% blood, Class IV Hemorrhage
#define BLOOD_VOLUME_CARDIAC_ARREST 1.2 // TBD
// IV Change per second calculation:
// 250ml should take 60 seconds to fill. 250/60 = 4.166.
// Basic medical is 10x (will take 6 seconds for 250ml)
#define IV_CHANGE_PER_SECOND ([41.66, 4.166] select (GVAR(level) >= 2))
// 250ml should take 60 seconds to fill. 250ml/60s = 4.166ml/s.
#define IV_CHANGE_PER_SECOND 4.166 // in milliliters per second
// chance per second to get knocked out due to blood loss
#define BLOOD_LOSS_KNOCK_OUT_CHANCE 0.1 // 10%
// duration in seconds to stay knocked out due to blood loss
#define BLOOD_LOSS_KNOCK_OUT_DURATION (15 + random 20)
// --- unconsciousness
#define DEFAULT_KNOCK_OUT_DELAY (5 + random 10)

View File

@ -50,6 +50,6 @@ if (_isUnconscious) then {
if (animationState _unit == "unconscious" && {lifeState _unit != "INCAPACITATED"}) then {
[_unit, "AmovPpneMstpSnonWnonDnon", 2] call EFUNC(common,doAnimation);
};
}, _unit] call CBA_fnc_execNextFrame;
}, _unit, 0.5] call CBA_fnc_waitAndExecute;
};
};

View File

@ -1,5 +1,5 @@
class ACE_Medical_Treatment {
class ADDON {
class Bandaging {
// Field dressing is normal average treatment
// packing bandage is average treatment, higher reopen change, longer reopening delay

View File

@ -54,7 +54,7 @@ class GVAR(Actions) {
treatmentLocations[] = {QGVAR(useLocation_basicEpi)};
};
class BloodIV: Bandage {
displayName = ECSTRING(medical,Transfuse_Blood);
displayName = ECSTRING(medical,Actions_Blood4_1000);
displayNameProgress = ECSTRING(medical,Transfusing_Blood);
allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"};
allowSelfTreatment = 0;
@ -62,17 +62,16 @@ class GVAR(Actions) {
requiredMedic = 1;
treatmentTime = 12;
items[] = {"ACE_bloodIV"};
callbackSuccess = QFUNC(treatmentBloodbag);
// callbackSuccess = QFUNC(treatmentIV);
callbackSuccess = QFUNC(treatmentIV);
animationCaller = "AinvPknlMstpSnonWnonDnon_medic1";
litter[] = {};
};
class BloodIV_500: BloodIV {
category = "advanced";
displayName = ECSTRING(medical,Actions_Blood4_500);
items[] = {"ACE_bloodIV_500"};
};
class BloodIV_250: BloodIV {
category = "advanced";
displayName = ECSTRING(medical,Actions_Blood4_250);
items[] = {"ACE_bloodIV_250"};
};
class BodyBag: Bandage {

View File

@ -12,7 +12,6 @@ if (isServer) then {
[QGVAR(treatmentMorphineLocal), FUNC(treatmentMorphineLocal)] call CBA_fnc_addEventHandler;
//[QGVAR(treatmentEpipenLocal), FUNC(treatmentEpipenLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentMedicationLocal), FUNC(treatmentMedicationLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentBloodbagLocal), FUNC(treatmentBloodbagLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentIVLocal), FUNC(treatmentIVLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentCPRLocal), FUNC(treatmentCPRLocal)] call CBA_fnc_addEventHandler;
[QGVAR(treatmentFullHealLocal), FUNC(treatmentFullHealLocal)] call CBA_fnc_addEventHandler;

View File

@ -22,18 +22,25 @@ private _bloodVolume = _target getVariable [QEGVAR(medical,bloodVolume), DEFAULT
if (_bloodVolume >= DEFAULT_BLOOD_VOLUME) exitWith {};
// Find the proper attributes for the used IV
private _config = (configFile >> "ace_medical_treatment" >> "IV");
private _config = configFile >> QUOTE(ADDON) >> "IV";
private _volumeAdded = getNumber (_config >> "volume");
private _typeOf = getText (_config >> "type");
private _type = getText (_config >> "type");
if (isClass (_config >> _treatmentClassname)) then {
_config = (_config >> _treatmentClassname);
if (isNumber (_config >> "volume")) then { _volumeAdded = getNumber (_config >> "volume");};
if (isText (_config >> "type")) then { _typeOf = getText (_config >> "type"); };
_config = _config >> _treatmentClassname;
if (isNumber (_config >> "volume")) then {
_volumeAdded = getNumber (_config >> "volume");
};
if (isText (_config >> "type")) then {
_type = getText (_config >> "type");
};
} else {
ERROR("IV Treatment Classname not found");
};
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
_bloodBags pushBack [_volumeAdded]; // Future BagType: [_volumeAdded, _typeOf]
_bloodBags pushBack [_volumeAdded]; // Future BagType: [_volumeAdded, _type]
_target setVariable [QEGVAR(medical,ivBags), _bloodBags, true];