Add handle revive and Unconscious states

This commit is contained in:
Glowbal 2016-07-07 12:04:26 +02:00
parent d0236a007a
commit 2daee60d0c
7 changed files with 214 additions and 105 deletions

View File

@ -76,13 +76,13 @@ class ACE_Medical_StateMachine {
};
class TimerRanOut {
targetState = "Dead";
condition = "timerValue >= maxReviveTime";
condition = "";
events[] = {"ReviveTimer"};
onTransition = "";
};
class FatalTransitions {
targetState = "Dead";
condition = "killOnFatalDamageInRevive && inReviveState >= 10";
condition = QGVAR(killOnFatalDamageInRevive);
events[] = {"FatalInjury"};
};
};

View File

@ -0,0 +1,24 @@
#include "script_component.hpp"
params ["_unit"];
private _reviveVal = _unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)];
if (_reviveVal == 1 && {[_unit] call EFUNC(common,isPlayer)} || _reviveVal == 2) then {
if (_unit getVariable [QGVAR(inReviveState), false]) exitWith {
// Error, already in revive state
false;
};
private _lifesLeft = _unit getVariable[QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives)];
if (GVAR(amountOfReviveLives) > 0 && _lifesLeft == 0) exitWith {
[_unit, "NoLives", []] call FUNC(stateEvent);
};
_unit setVariable [QGVAR(inReviveState), true, true];
_unit setVariable [QGVAR(reviveStartTime), CBA_missionTime];
[_unit, true] call FUNC(setUnconscious);
} else {
[_unit, "NoLives", []] call FUNC(stateEvent);
};

View File

@ -20,95 +20,4 @@
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;
[_unit, true] call FUNC(setUnconscious);

View File

@ -3,12 +3,11 @@
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 (!local _unit) eexitWith{
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];
@ -16,6 +15,38 @@ if (!local _unit) exitWith {
_unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), 100], true];
};
private _startTime = _unit getVariable [QGVAR(reviveStartTime), 0];
// If we are in revive state in a blown up vehicle, try to unload so that people can access the body
if ((alive _unit) && {(vehicle _unit) != _unit} && {!alive (vehicle _unit)}) then {
TRACE_2("Unloading", _unit, vehicle _unit);
[_unit] call EFUNC(common,unloadPerson);
};
// Revive timer ran out
if (GVAR(maxReviveTime) > 0 && {CBA_missionTime - _startTime > GVAR(maxReviveTime)}) exitWith
[_unit, "ReviveTimer", []] call FUNC(stateEvent);
_unit setVariable [QGVAR(inReviveState), nil, true];
_unit setVariable [QGVAR(reviveStartTime), nil];
};
// If the unit was taken out from revive state, exit the loop
if !(_unit getVariable [QGVAR(inReviveState), false]) exitWith {
// Revived without dieing, so in case we have lifes, remove one.
if (GVAR(amountOfReviveLives) > 0) then {
_lifesLeft = _unit getVariable[QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives)];
_unit setVariable [QGVAR(amountOfReviveLives), _lifesLeft - 1, true];
};
_unit setVariable [QGVAR(reviveStartTime), nil];
};
// Remove heartbeat
if (GVAR(level) >= 2) then {
if (_unit getVariable [QGVAR(heartRate), 60] > 0) then {
_unit setVariable [QGVAR(heartRate), 0];
};
};
[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals);
private _pain = _unit getVariable [QGVAR(pain), 0];

View File

@ -0,0 +1,127 @@
/*
* Author: Glowbal
* Sets a unit in the 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
*
* Example:
* [bob, true] call ace_medical_fnc_setUnconscious;
*
* Public: yes
*/
#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];
};
private ["_animState", "_originalPos", "_startingTime", "_isDead"];
params ["_unit", ["_set", true], ["_minWaitingTime", DEFAULT_DELAY], ["_force", false]];
// No change, fuck off. (why is there no xor?)
if (_set isEqualTo (_unit getVariable ["ACE_isUnconscious", false])) exitWith {};
if !(_set) exitWith {
_unit setVariable ["ACE_isUnconscious", false, true];
};
if !(!(isNull _unit) && {(_unit isKindOf "CAManBase") && ([_unit] call EFUNC(common,isAwake))}) exitWith{};
if (!local _unit) exitWith {
[QGVAR(setUnconscious), [_unit, _set, _minWaitingTime, _force], _unit] call CBA_fnc_targetEvent;
};
_unit setVariable ["ACE_isUnconscious", true, true];
_unit setUnconscious true;
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);
_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;
[_unit, "Unconscious", []] call FUNC(stateEvent);
[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;

View File

@ -35,7 +35,7 @@ GVAR(monitoredUnitsListIsSorted) = false;
_delete = true;
GVAR(monitoredUnitsList) set [_forEachIndex, objNull];
};
if (_exit) exitwith {};
if (_exit) exitWith {};
} forEach GVAR(monitoredUnitsList);
if (_delete) then {

View File

@ -1,12 +1,31 @@
/*
* 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"
params ["_unit", "_args"];
_args params ["_originalPos", "_startingTime", "_minWaitingTime", "_hasMovedOut", "_parachuteCheck"];
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_handling",_unit, _originalPos, _startingTime, _minWaitingTime, _hasMovedOut, _parachuteCheck);
TRACE_6("ACE_DEBUG_Unconscious_PFH",_unit, _originalPos, _startingTime, _minWaitingTime, _hasMovedOut, _parachuteCheck);
if (!alive _unit) exitWith { // TODO on exit unconscious
if (!alive _unit) exitWith {
if ("ACE_FakePrimaryWeapon" in (weapons _unit)) then {
TRACE_1("Removing fake weapon [on death]",_unit);
_unit removeWeapon "ACE_FakePrimaryWeapon";
@ -17,12 +36,13 @@ if (!alive _unit) exitWith { // TODO on exit unconscious
[_unit, "setCaptive", "ace_unconscious", false] call EFUNC(common,statusEffect_set);
[_unit, false] call EFUNC(common,disableAI);
//_unit setUnitPos _originalPos;
//_unit setUnconscious false;
_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;
};
@ -76,12 +96,10 @@ if !(_unit getVariable ["ACE_isUnconscious",false]) exitWith {
};
_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);