mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Work done on medical states
This commit is contained in:
parent
e8eb729e04
commit
d0236a007a
@ -1,6 +1,6 @@
|
||||
class ACE_Medical_StateMachine {
|
||||
class Default {
|
||||
onState = QUOTE(DFUNC(handleDefaultState));
|
||||
onState = QUOTE(DFUNC(handleStateDefault));
|
||||
onStateEntered = "";
|
||||
onStateLeaving = "";
|
||||
class Injury {
|
||||
@ -17,7 +17,7 @@ class ACE_Medical_StateMachine {
|
||||
};
|
||||
};
|
||||
class Injured {
|
||||
onState = QUOTE(DFUNC(handleInjuredState));
|
||||
onState = QUOTE(DFUNC(handleStateInjured));
|
||||
onStateEntered = "";
|
||||
onStateLeaving = "";
|
||||
|
||||
@ -39,7 +39,7 @@ class ACE_Medical_StateMachine {
|
||||
};
|
||||
};
|
||||
class Unconscious {
|
||||
onState = QUOTE(DFUNC(handleUnconciousState));
|
||||
onState = QUOTE(DFUNC(handleStateUnconscious));
|
||||
onStateEntered = QUOTE(DFUNC(enteredUnconscious)); // set unconscious animation & state
|
||||
onStateLeaving = QUOTE(DFUNC(leavingUnconscious)); // leave unconscious animation & state
|
||||
class WakeUpFromKnockDown {
|
||||
@ -61,7 +61,7 @@ class ACE_Medical_StateMachine {
|
||||
onStateEntered = "(_this select 0) setDamage 1"; // killing a unit also exits the state machine for this unit
|
||||
};
|
||||
class Revive {
|
||||
onState = QUOTE(DFUNC(handleReviveState));
|
||||
onState = QUOTE(DFUNC(handleStateRevive));
|
||||
onStateEntered = QUOTE(DFUNC(enteredRevive)); // set unconscious animation & state
|
||||
onStateLeaving = QUOTE(DFUNC(leavingRevive)); // leave unconscious animation & state
|
||||
class FullHeal {
|
||||
|
114
addons/medical/functions/fnc_enteredUnconsciousState.sqf
Normal file
114
addons/medical/functions/fnc_enteredUnconsciousState.sqf
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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"];
|
||||
|
||||
private ["_animState", "_originalPos", "_startingTime", "_isDead"];
|
||||
//params ["_unit", ["_set", true], ["_minWaitingTime", DEFAULT_DELAY], ["_force", false]];
|
||||
|
||||
if !(!(isNull _unit) && {(_unit isKindOf "CAManBase") && ([_unit] call EFUNC(common,isAwake))}) exitWith{
|
||||
// TODO log error, already in an unconsicous state or dead?
|
||||
};
|
||||
|
||||
_unit setVariable ["ACE_isUnconscious", true, true];
|
||||
// Disabled to not run with the 1.62 vanilla medical changes.
|
||||
// _unit setUnconscious true;
|
||||
|
||||
// Ensure the map is closed when entering the unconscious state
|
||||
if (_unit == ACE_player) then {
|
||||
if (visibleMap) then {openMap false};
|
||||
while {dialog} do {
|
||||
closeDialog 0;
|
||||
};
|
||||
};
|
||||
|
||||
// if we have unconsciousness for AI disabled, we will kill the unit instead
|
||||
_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);
|
||||
// TODO raise fatal event
|
||||
_isDead = true;
|
||||
};
|
||||
};
|
||||
if (_isDead) exitWith {};
|
||||
|
||||
// If a unit has the launcher out, it will sometimes start selecting the primairy weapon while unconscious,
|
||||
// therefor we force it to select the primairy weapon before going unconscious
|
||||
if ((vehicle _unit) isKindOf "StaticWeapon") then {
|
||||
[_unit] call EFUNC(common,unloadPerson);
|
||||
};
|
||||
if (animationState _unit in ["ladderriflestatic","laddercivilstatic"]) then {
|
||||
_unit action ["ladderOff", (nearestBuilding _unit)];
|
||||
};
|
||||
if (vehicle _unit == _unit) then {
|
||||
if (primaryWeapon _unit == "") then {
|
||||
_unit addWeapon "ACE_FakePrimaryWeapon";
|
||||
};
|
||||
_unit selectWeapon (primaryWeapon _unit);
|
||||
};
|
||||
|
||||
// We are storing the current animation, so we can use it later on when waking the unit up inside a vehicle
|
||||
if (vehicle _unit != _unit) then {
|
||||
_unit setVariable [QGVAR(vehicleAwakeAnim), [(vehicle _unit), (animationState _unit)]];
|
||||
};
|
||||
|
||||
//Save current stance:
|
||||
_originalPos = unitPos _unit;
|
||||
|
||||
_unit setUnitPos "DOWN";
|
||||
[_unit, true] call EFUNC(common,disableAI);
|
||||
|
||||
// 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);
|
||||
};
|
||||
// Delay Unconscious so the AI dont instant stop shooting on the unit #3121
|
||||
if (GVAR(delayUnconCaptive) == 0) then {
|
||||
[_unit, "setCaptive", "ace_unconscious", true] call EFUNC(common,statusEffect_set);
|
||||
} else {
|
||||
[{
|
||||
params ["_unit"];
|
||||
if (_unit getVariable ["ACE_isUnconscious", false]) then {
|
||||
[_unit, "setCaptive", "ace_unconscious", true] call EFUNC(common,statusEffect_set);
|
||||
};
|
||||
},[_unit], GVAR(delayUnconCaptive)] call CBA_fnc_waitAndExecute;
|
||||
};
|
||||
|
||||
_anim = [_unit] call EFUNC(common,getDeathAnim);
|
||||
[_unit, _anim, 1, true] call EFUNC(common,doAnimation);
|
||||
[{
|
||||
params ["_unit", "_anim"];
|
||||
if ((_unit getVariable "ACE_isUnconscious") and (animationState _unit != _anim)) then {
|
||||
[_unit, _anim, 2, true] call EFUNC(common,doAnimation);
|
||||
};
|
||||
}, [_unit, _anim], 0.5, 0] call CBA_fnc_waitAndExecute;
|
||||
|
||||
_startingTime = CBA_missionTime;
|
||||
|
||||
// gets started in the handle unconscious state
|
||||
// [DFUNC(unconsciousPFH), 0.1, [_unit, _originalPos, _startingTime, _minWaitingTime, false, vehicle _unit isKindOf "ParachuteBase"] ] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
// unconscious can't talk
|
||||
[_unit, "isUnconscious"] call EFUNC(common,muteUnit);
|
||||
|
||||
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent;
|
25
addons/medical/functions/fnc_handleKilled.sqf
Normal file
25
addons/medical/functions/fnc_handleKilled.sqf
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Called when a unit is killed
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
private "_openWounds";
|
||||
params ["_unit"];
|
||||
if (!local _unit) exitWith {};
|
||||
|
||||
_unit setVariable [QGVAR(pain), 0];
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), 0];
|
||||
_unit setVariable [QGVAR(bloodPressure), [0, 0]];
|
||||
_unit setVariable [QGVAR(airwayStatus), 0];
|
||||
};
|
34
addons/medical/functions/fnc_handleLocal.sqf
Normal file
34
addons/medical/functions/fnc_handleLocal.sqf
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Called when a unit switched locality
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Is local <BOOL>
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_local"];
|
||||
if (_local) then {
|
||||
// If the unit had a loop tracking its vitals, restart it locally
|
||||
if (_unit getVariable[QGVAR(addedToUnitLoop),false]) then {
|
||||
[_unit, true] call FUNC(addVitalLoop);
|
||||
};
|
||||
|
||||
if ((_unit getVariable ["ACE_isUnconscious",false]) && {count (_unit getVariable [QGVAR(unconsciousArguments), []]) >= 6}) then {
|
||||
private "_arguments";
|
||||
_arguments = (_unit getVariable [QGVAR(unconsciousArguments), []]);
|
||||
_arguments set [2, CBA_missionTime];
|
||||
|
||||
[DFUNC(unconsciousPFH), 0.1, _arguments ] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
_unit setVariable [QGVAR(unconsciousArguments), nil, true];
|
||||
};
|
||||
};
|
42
addons/medical/functions/fnc_handleMedications.sqf
Normal file
42
addons/medical/functions/fnc_handleMedications.sqf
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Author: Glowbal, esteldunedain
|
||||
* Medication effect loop for an injection.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
* 1: Name of the Variable that is affected <STRING>
|
||||
* 2: Proportion of the effect applied <NUMBER>
|
||||
* 3: Rate at which the effect is applied <NUMBER>
|
||||
* 4: Viscosity adjustment rate <NUMBER>
|
||||
* 5: Pain reduction rate <NUMBER>
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_variableName", "_amountDecreased","_decreaseRate", "_viscosityAdjustmentRate", "_painReduceRate"];
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed finish the local loop
|
||||
if (!local _unit) exitWith {};
|
||||
|
||||
// Apply medicinal effect
|
||||
private _usedMeds = (_unit getVariable [_variableName, 0]) - _decreaseRate;
|
||||
_unit setVariable [_variableName, _usedMeds];
|
||||
|
||||
// Restore the viscosity while the medication is leaving the system
|
||||
_unit setVariable [QGVAR(peripheralResistance), ((_unit getVariable [QGVAR(peripheralResistance), 100]) - _viscosityAdjustmentRate) max 0];
|
||||
_unit setVariable [QGVAR(painSuppress), ((_unit getVariable [QGVAR(painSuppress), 0]) - _painReduceRate) max 0];
|
||||
|
||||
// Exit if the medication has finished it's effect
|
||||
_amountDecreased = _amountDecreased + _decreaseRate;
|
||||
if (_amountDecreased >= 1 || (_usedMeds <= 0) || !alive _unit) exitWith {};
|
||||
|
||||
// Schedule the loop to be executed again 1 sec later
|
||||
[DFUNC(medicationEffectLoop), [_unit, _variableName, _amountDecreased, _decreaseRate, _viscosityAdjustmentRate, _painReduceRate], 1] call CBA_fnc_waitAndExecute;
|
24
addons/medical/functions/fnc_handleStateDefault.sqf
Normal file
24
addons/medical/functions/fnc_handleStateDefault.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), 100], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
[_unit, _pain] call FUNC(playInjuredSound);
|
||||
};
|
24
addons/medical/functions/fnc_handleStateInjured.sqf
Normal file
24
addons/medical/functions/fnc_handleStateInjured.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), 100], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
[_unit, _pain] call FUNC(playInjuredSound);
|
||||
};
|
24
addons/medical/functions/fnc_handleStateRevive.sqf
Normal file
24
addons/medical/functions/fnc_handleStateRevive.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), 100], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
[_unit, _pain] call FUNC(playInjuredSound);
|
||||
};
|
24
addons/medical/functions/fnc_handleStateUnconscious.sqf
Normal file
24
addons/medical/functions/fnc_handleStateUnconscious.sqf
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_stateName", "_lastTime"];
|
||||
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
|
||||
// If locality changed, broadcast the last medical state and finish the local loop
|
||||
if (!local _unit) exitWith {
|
||||
if (GVAR(level) >= 2) then {
|
||||
_unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true];
|
||||
_unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true];
|
||||
};
|
||||
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), 100], true];
|
||||
};
|
||||
|
||||
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
|
||||
|
||||
private _pain = _unit getVariable [QGVAR(pain), 0];
|
||||
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
[_unit, _pain] call FUNC(playInjuredSound);
|
||||
};
|
126
addons/medical/functions/fnc_handleUnconscious.sqf
Normal file
126
addons/medical/functions/fnc_handleUnconscious.sqf
Normal file
@ -0,0 +1,126 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_args"];
|
||||
_args params ["_originalPos", "_startingTime", "_minWaitingTime", "_hasMovedOut", "_parachuteCheck"];
|
||||
|
||||
TRACE_6("ACE_DEBUG_Unconscious_handling",_unit, _originalPos, _startingTime, _minWaitingTime, _hasMovedOut, _parachuteCheck);
|
||||
|
||||
if (!alive _unit) exitWith { // TODO on exit unconscious
|
||||
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 FUNC(isBeingCarried), [_unit] call FUNC(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 FUNC(isBeingCarried)) || ([_unit] call FUNC(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];
|
||||
|
||||
// Now we can leave our unconsicous state
|
||||
["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];
|
||||
};
|
||||
};
|
156
addons/medical/functions/fnc_handleUnitVitals.sqf
Normal file
156
addons/medical/functions/fnc_handleUnitVitals.sqf
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Updates the vitals. Is expected to be called every second.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* ReturnValue:
|
||||
* <NIL>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
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));
|
||||
if (_syncValues) then {
|
||||
_unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime];
|
||||
};
|
||||
|
||||
private _bloodVolume = (_unit getVariable [QGVAR(bloodVolume), 100]) + ([_unit] call FUNC(getBloodVolumeChange));
|
||||
_bloodVolume = _bloodVolume max 0;
|
||||
|
||||
_unit setVariable [QGVAR(bloodVolume), _bloodVolume, _syncValues];
|
||||
|
||||
TRACE_3("ACE_DEBUG",_bloodVolume,_syncValues,_unit);
|
||||
// Set variables for synchronizing information across the net
|
||||
if (_bloodVolume < 100) then {
|
||||
if (_bloodVolume < 90) then {
|
||||
TRACE_4("ACE_DEBUG",_bloodVolume,_unit getVariable QGVAR(hasLostBlood),_syncValues,_unit);
|
||||
if (_unit getVariable [QGVAR(hasLostBlood), 0] != 2) then {
|
||||
_unit setVariable [QGVAR(hasLostBlood), 2, true];
|
||||
};
|
||||
} else {
|
||||
TRACE_4("ACE_DEBUG", _bloodVolume,_unit getVariable QGVAR(hasLostBlood),_syncValues,_unit);
|
||||
if (_unit getVariable [QGVAR(hasLostBlood), 0] != 1) then {
|
||||
_unit setVariable [QGVAR(hasLostBlood), 1, true];
|
||||
};
|
||||
};
|
||||
} else {
|
||||
TRACE_4("ACE_DEBUG",_bloodVolume,_unit getVariable QGVAR(hasLostBlood),_syncValues,_unit);
|
||||
if (_unit getVariable [QGVAR(hasLostBlood), 0] != 0) then {
|
||||
_unit setVariable [QGVAR(hasLostBlood), 0, true];
|
||||
};
|
||||
};
|
||||
|
||||
TRACE_3("ACE_DEBUG",[_unit] call FUNC(getBloodLoss),_unit getVariable QGVAR(isBleeding),_unit);
|
||||
if (([_unit] call FUNC(getBloodLoss)) > 0) then {
|
||||
if !(_unit getVariable [QGVAR(isBleeding), false]) then {
|
||||
_unit setVariable [QGVAR(isBleeding), true, true];
|
||||
};
|
||||
} else {
|
||||
if (_unit getVariable [QGVAR(isBleeding), false]) then {
|
||||
_unit setVariable [QGVAR(isBleeding), false, true];
|
||||
};
|
||||
};
|
||||
|
||||
private _painStatus = _unit getVariable [QGVAR(pain), 0];
|
||||
TRACE_4("ACE_DEBUG",_painStatus,_unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(painSuppress),_unit);
|
||||
if (_painStatus > (_unit getVariable [QGVAR(painSuppress), 0])) then {
|
||||
if !(_unit getVariable [QGVAR(hasPain), false]) then {
|
||||
_unit setVariable [QGVAR(hasPain), true, true];
|
||||
};
|
||||
} else {
|
||||
if (_unit getVariable [QGVAR(hasPain), false]) then {
|
||||
_unit setVariable [QGVAR(hasPain), false, true];
|
||||
};
|
||||
};
|
||||
|
||||
if (_bloodVolume < 30) exitWith {
|
||||
[_unit] call FUNC(setDead);
|
||||
};
|
||||
|
||||
if ([_unit] call EFUNC(common,isAwake)) then {
|
||||
if (_bloodVolume < 60) then {
|
||||
if (random(1) > 0.9) then {
|
||||
[_unit, true, 15 + random(20)] 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
|
||||
if (_painStatus > 0) then {
|
||||
_unit setVariable [QGVAR(pain), (_painStatus - 0.001 * _interval) max 0, _syncValues];
|
||||
};
|
||||
|
||||
// reduce painkillers
|
||||
if (_unit getVariable [QGVAR(morphine), 0] > 0) then {
|
||||
_unit setVariable [QGVAR(morphine), ((_unit getVariable [QGVAR(morphine), 0]) - 0.0015 * _interval) max 0, _syncValues];
|
||||
};
|
||||
};
|
||||
|
||||
// handle advanced medical, with vitals
|
||||
if (GVAR(level) >= 2) then {
|
||||
TRACE_6("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_bloodVolume, _unit getVariable QGVAR(hasPain),_unit getVariable QGVAR(morphine),_syncValues,_unit);
|
||||
|
||||
// Handle pain due tourniquets, that have been applied more than 120 s ago
|
||||
private _oldTourniquets = (_unit getVariable [QGVAR(tourniquets), []]) select {_x > 0 && {CBA_missionTime - _x > 120}};
|
||||
// Increase pain at a rate of 0.001 units/s per old tourniquet
|
||||
_painStatus = _painStatus + (count _oldTourniquets) * 0.001 * _interval;
|
||||
|
||||
// Set the vitals
|
||||
private _heartRate = (_unit getVariable [QGVAR(heartRate), 80]) + (([_unit] call FUNC(getHeartRateChange)) * _interval);
|
||||
_unit setVariable [QGVAR(heartRate), _heartRate max 0, _syncValues];
|
||||
|
||||
private _bloodPressure = [_unit] call FUNC(getBloodPressure);
|
||||
_unit setVariable [QGVAR(bloodPressure), _bloodPressure, _syncValues];
|
||||
|
||||
_painReduce = [0.001, 0.002] select (_painStatus > 5);
|
||||
|
||||
// @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic)
|
||||
_unit setVariable [QGVAR(pain), (_painStatus - _painReduce * _interval) max 0, _syncValues];
|
||||
|
||||
TRACE_8("ACE_DEBUG_ADVANCED_VITALS",_painStatus,_painReduce,_heartRate,_bloodVolume,_bloodPressure,_interval,_syncValues,_unit);
|
||||
|
||||
// Check vitals for medical status
|
||||
// TODO check for in revive state instead of variable
|
||||
_bloodPressure params ["_bloodPressureL", "_bloodPressureH"];
|
||||
|
||||
if (!(_unit getVariable [QGVAR(inCardiacArrest),false])) then {
|
||||
if (_heartRate < 10 || _bloodPressureH < 30 || _bloodVolume < 20) 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 {
|
||||
[_unit] call FUNC(setCardiacArrest);
|
||||
};
|
||||
};
|
||||
|
||||
// syncing any remaining values
|
||||
if (_syncValues) then {
|
||||
TRACE_3("ACE_DEBUG_IVBAGS_SYNC",GVAR(IVBags),_syncValues,_unit);
|
||||
{
|
||||
private "_value";
|
||||
_value = _unit getVariable _x;
|
||||
if !(isNil "_value") then {
|
||||
_unit setVariable [_x,(_unit getVariable [_x, 0]), true];
|
||||
};
|
||||
} forEach GVAR(IVBags);
|
||||
};
|
||||
};
|
81
addons/medical/functions/fnc_playInjuredSound.sqf
Normal file
81
addons/medical/functions/fnc_playInjuredSound.sqf
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Play the injured sound for a unit if the unit is damaged. The sound broadcasted across MP.
|
||||
* Will not play if the unit has already played a sound within to close a time frame.
|
||||
* Delay: With minimal damage (below 1), the delay is (10 + random(50)) seconds. Otherwise it is 60 seconds / damage.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
* 1: Amount of Pain <NUMBER>
|
||||
*
|
||||
* ReturnValue:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_pain"];
|
||||
if (!local _unit || !GVAR(enableScreams)) exitWith{};
|
||||
|
||||
// Lock if the unit is already playing a sound.
|
||||
if ((_unit getVariable [QGVAR(playingInjuredSound),false])) exitWith {};
|
||||
_unit setVariable [QGVAR(playingInjuredSound),true];
|
||||
|
||||
// Play the sound if there is any damage present.
|
||||
if (_pain > 0 && {[_unit] call EFUNC(common,isAwake)}) exitWith {
|
||||
// Classnames of the available sounds.
|
||||
private _availableSounds_A = [
|
||||
"WoundedGuyA_01",
|
||||
"WoundedGuyA_02",
|
||||
"WoundedGuyA_03",
|
||||
"WoundedGuyA_04",
|
||||
"WoundedGuyA_05",
|
||||
"WoundedGuyA_06",
|
||||
"WoundedGuyA_07",
|
||||
"WoundedGuyA_08"
|
||||
];
|
||||
private _availableSounds_B = [
|
||||
"WoundedGuyB_01",
|
||||
"WoundedGuyB_02",
|
||||
"WoundedGuyB_03",
|
||||
"WoundedGuyB_04",
|
||||
"WoundedGuyB_05",
|
||||
"WoundedGuyB_06",
|
||||
"WoundedGuyB_07",
|
||||
"WoundedGuyB_08"
|
||||
];
|
||||
private _availableSounds_C = [
|
||||
"WoundedGuyC_01",
|
||||
"WoundedGuyC_02",
|
||||
"WoundedGuyC_03",
|
||||
"WoundedGuyC_04",
|
||||
"WoundedGuyC_05"
|
||||
];
|
||||
private _sound = "";
|
||||
|
||||
// Select the to be played sound based upon damage amount.
|
||||
if (_pain > 0.5) then {
|
||||
if (random(1) > 0.5) then {
|
||||
_sound = selectRandom _availableSounds_A;
|
||||
} else {
|
||||
_sound = selectRandom _availableSounds_B;
|
||||
};
|
||||
} else {
|
||||
_sound = selectRandom _availableSounds_B;
|
||||
};
|
||||
// Play the sound
|
||||
playSound3D [(getArray(configFile >> "CfgSounds" >> _sound >> "sound") select 0) + ".wss", objNull, false, getPos _unit, 15, 1, 25]; // +2db, 15 meters.
|
||||
|
||||
// Figure out what the delay will be before it is possible to play a sound again.
|
||||
private _delay = (30 - (random(25) * _pain)) max (3.5 + random(2));
|
||||
|
||||
// Clean up the lock
|
||||
[{
|
||||
(_this select 0) setVariable [QGVAR(playingInjuredSound), nil];
|
||||
}, [_unit], _delay, _delay] call CBA_fnc_waitAndExecute;
|
||||
};
|
||||
|
||||
// Clean up in case there has not been played any sounds.
|
||||
_unit setVariable [QGVAR(playingInjuredSound), nil];
|
@ -1,7 +1,7 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Delay between state runs
|
||||
#define DELAY 10
|
||||
#define DELAY 1
|
||||
#define DEFAULT_STATE [0, "Default", {}, {}, {}, []]
|
||||
|
||||
GVAR(monitoredUnitsList) = [];
|
||||
@ -30,7 +30,7 @@ GVAR(monitoredUnitsListIsSorted) = false;
|
||||
|
||||
_unit setvariable [QGVAR(state), _unitState];
|
||||
|
||||
[_unit, _name] call _handler;
|
||||
[_unit, _name, _lastTime] call _handler;
|
||||
} else {
|
||||
_delete = true;
|
||||
GVAR(monitoredUnitsList) set [_forEachIndex, objNull];
|
||||
|
Loading…
Reference in New Issue
Block a user