manual merge

This commit is contained in:
commy2 2016-12-05 20:18:15 +01:00
commit 9cba0baade
23 changed files with 256 additions and 301 deletions

View File

@ -1,80 +1,102 @@
class ACE_Medical_StateMachine {
list = "allUnits select {local _x}";
skipNull = 1;
class Default {
onState = QUOTE(DFUNC(handleStateDefault));
class Injury {
targetState = "Injured";
events[] = {"TakenInjury"};
events[] = {QGVAR(TakenInjury)};
};
class CriticalInjuryOrVitals {
targetState = "Unconscious";
events[] = {"InjuryCritical", "CriticalVitals"};
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)};
};
class FatalInjuryOrVitals {
targetState = "Dead";
events[] = {"FatalVitals", "InjuryFatal"};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)};
};
};
class Injured {
onState = QUOTE(DFUNC(handleStateInjured));
class FullHeal {
targetState = "Default";
events[] = {"FullHeal"};
events[] = {QGVAR(FullHeal)};
};
class LastWoundTreated {
targetState = "Default";
events[] = {"LastWoundTreated"};
events[] = {QGVAR(LastWoundTreated)};
};
class CriticalInjuryOrVitals {
targetState = "Unconscious";
events[] = {"InjuryCritical", "CriticalVitals"};
events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)};
};
class FatalInjuryOrVitals {
targetState = "Dead";
events[] = {"FatalVitals", "InjuryFatal"};
class FatalVitals {
targetState = "CardiacArrest";
events[] = {QGVAR(FatalVitals)};
};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)};
};
};
class Unconscious {
onState = QUOTE(DFUNC(handleStateUnconscious));
onStateEntered = QUOTE(DFUNC(enteredUnconsciousState));
onStateLeaving = "_unit setVariable ['ACE_isUnconscious', false, true];";
onStateLeaving = "_this setVariable ['ACE_isUnconscious', false, true];";
class WakeUpFromKnockDown {
targetState = "Injured";
condition = QUOTE(_unit call FUNC(hasStableVitals));
events[] = {"MinUnconsciousTimer"};
condition = QUOTE(_this call FUNC(hasStableVitals));
events[] = {QGVAR(MinUnconsciousTimer)};
};
class WakeUpStable {
targetState = "Injured";
condition = "unitUnconsciousTimer >= MinUnconsciousTimer";
events[] = {"VitalsWentStable"};
events[] = {QGVAR(VitalsWentStable)};
};
class FatalTransitions {
targetState = "CardiacArrest";
events[] = {QGVAR(FatalVitals), QGVAR(UnconsciousTimerRanOut)};
};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QGVAR(InjuryFatal)};
};
};
class FatalInjury {
// Transition state for handling instant death
// This state raises the next transition in the same frame
onStateEntered = QUOTE(DFUNC(enteredStateFatalInjury));
class SecondChance {
events[] = {QGVAR(FatalInjuryInstantTransition)};
targetState = "CardiacArrest";
condition = QUOTE(GVAR(fatalInjuryCondition) > 0);
onTransition = QUOTE(DFUNC(transitionSecondChance));
};
class Death {
events[] = {QGVAR(FatalInjuryInstantTransition)};
targetState = "Dead";
events[] = {"InjuryFatal", "FatalVitals", "UnconsciousTimerRanOut"};
condition = "true";
};
};
class CardiacArrest {
onStateEntered = QUOTE(DFUNC(enteredStateCardiacArrest));
onStateLeaving = '_this setVariable [QGVAR(cardiacArrestStart), nil]';
class TimerRanOut {
targetState = "Dead";
condition = QUOTE(DFUNC(conditionCardiacArrestTimer));
};
class Reanimated {
targetState = "Unconscious";
events[] = {QGVAR(CPRSucceeded)};
};
class Execution {
targetState = "Dead";
condition = QUOTE(DFUNC(conditionExecutionDeath));
events[] = {QGVAR(InjuryFatal)};
};
};
class Dead {
onStateEntered = "(_this select 0) setDamage 1"; // killing a unit also exits the state machine for this unit
};
class Revive {
onState = QUOTE(DFUNC(handleStateRevive));
onStateEntered = QUOTE(DFUNC(enteredRevive)); // set unconscious animation & state
onStateLeaving = QUOTE(DFUNC(leavingRevive)); // leave unconscious animation & state
class FullHeal {
targetState = "Default";
events[] = {"fullyHealed"};
};
class Revived {
targetState = "Injured";
events[] = {"Revived"};
};
class TimerRanOut {
targetState = "Dead";
events[] = {"ReviveTimer", "NoLives"};
};
class FatalTransitions {
targetState = "Dead";
condition = QGVAR(killOnFatalDamageInRevive);
events[] = {"FatalInjury"};
};
onStateEntered = "_this setDamage 1"; // killing a unit also exits the state machine for this unit
};
};

View File

@ -1,7 +1,4 @@
PREP(addStateHandler);
PREP(adjustPainLevel);
PREP(createStateMachine);
PREP(getBloodLoss);
PREP(getBloodPressure);
PREP(getBloodVolumeChange);
@ -14,17 +11,22 @@ PREP(isInMedicalVehicle);
PREP(isInStableCondition);
PREP(isMedic);
PREP(isMedicalVehicle);
PREP(stateEvent);
PREP(stateMachine);
// PREP(hasMedicalEnabled);
PREP(enteredStateCardiacArrest);
PREP(leavingStateCardiacArrest);
PREP(enteredStateFatalInjury);
PREP(conditionExecutionDeath);
PREP(transitionSecondChance);
PREP(handleStateDefault);
PREP(handleStateInjured);
PREP(handleStateUnconscious);
PREP(handleUnitVitals);
PREP(handleMedications);
// PREP(handleStateRevive);
PREP(addPain);
PREP(setUnconscious);

View File

@ -1,12 +1,9 @@
#include "script_component.hpp"
GVAR(heartBeatSounds_Fast) = ["ACE_heartbeat_fast_1", "ACE_heartbeat_fast_2", "ACE_heartbeat_fast_3"];
GVAR(heartBeatSounds_Normal) = ["ACE_heartbeat_norm_1", "ACE_heartbeat_norm_2"];
GVAR(heartBeatSounds_Slow) = ["ACE_heartbeat_slow_1", "ACE_heartbeat_slow_2"];
call FUNC(stateMachine);
//Handle Deleting Bodies and creating litter on Server:
if (isServer) then {
["ace_placedInBodyBag", FUNC(serverRemoveBody)] call CBA_fnc_addEventHandler;
@ -35,3 +32,29 @@ if (!hasInterface) exitWith {};
linearConversion [0, 1, _pain, 1, 5, true];
}] call EFUNC(common,arithmeticSetSource);
#ifdef DEBUG_MODE_FULL
if (hasInterface) then {
private _ctrl = findDisplay 46 ctrlCreate ["RscText", -1];
_ctrl ctrlSetPosition [
safeZoneX,
safeZoneY,
safeZoneW,
40 * pixelH
];
_ctrl ctrlSetFontHeight (40 * pixelH);
_ctrl ctrlSetTextColor [0.6, 0, 0, 1];
_ctrl ctrlCommit 0;
uiNamespace setVariable [QGVAR(debugControl), _ctrl];
[{
private _playerState = [ACE_player, GVAR(STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
(uiNamespace getVariable [QGVAR(debugControl), controlNull]) ctrlSetText format ["Player state: %1", _playerState];
if (!isNull cursorTarget && {cursorTarget isKindOf "CAManBase"}) then {
private _targetState = [cursorTarget, GVAR(STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
drawIcon3D ["", [0.6, 0, 0, 1], cursorTarget modelToWorld (cursorTarget selectionPosition "pelvis"), 0, 0, 0, format ["State: %1", _targetState], 2, 40 * pixelH, "RobotoCondensed"];
};
}] call CBA_fnc_addPerFrameHandler;
};
#endif

View File

@ -9,7 +9,7 @@ PREP_RECOMPILE_END;
GVAR(HITPOINTS) = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"];
GVAR(SELECTIONS) = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"];
GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call FUNC(createStateMachine);
GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call CBA_statemachine_fnc_createFromConfig;
// @todo, ACE_Settings
[
@ -39,4 +39,26 @@ GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call FUNC(creat
true
] call CBA_Settings_fnc_init;
[
QGVAR(fatalInjuryCondition),
"LIST",
["Allow Fatal Injury", "Governs when a fatal injury can occur."], //@todo
"ACE Medical", // @todo
[
[0, 1, 2],
["Always", "In Cardiac Arrest", "Never"],
0
],
true
] call CBA_Settings_fnc_init;
[
QGVAR(cardiacArrestTime),
"SLIDER",
["Cardiac Arrest Time", "Sets how long cardiac arrest will last for (in minutes)."], //@todo
"ACE Medical", // @todo
[0, 30, 2, 0],
true
] call CBA_Settings_fnc_init;
ADDON = true;

View File

@ -0,0 +1,18 @@
/*
* Author: BaerMitUmlaut
* Checks if the cardiac arrest timer ran out.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
private _startTime = _unit getVariable [QGVAR(cardiacArrestStart), CBA_missionTime];
(CBA_missionTime - _startTime) > (GVAR(cardiacArrestTime) * 60)

View File

@ -0,0 +1,16 @@
/*
* Author: BaerMitUmlaut
* Condition for an execution caused death.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
(GVAR(fatalInjuryCondition) < 2) && {!(_unit getVariable [QGVAR(deathBlocked), false])}

View File

@ -1,59 +0,0 @@
#include "script_component.hpp"
params ["_stateMachineConfig"];
private _getCode = {
params ["_config", "_attribute"];
private _value = getText (_config >> _attribute);
if (isNil {missionNamespace getVariable _value}) exitWith {
if (_value == "") then {_value = "true"};
systemChat format ["getCode (%1) is returning nil: %3", _attribute, missionnamespace getVariable _value, _value];
diag_log format ["getCode (%1) is returning nil: %3", _attribute, missionnamespace getVariable _value, _value];
compile _value;
};
missionNamespace getVariable _value;
};
private _stateMachine = call CBA_fnc_createNamespace;
private _states = [];
{
private _stateName = configName _x;
private _onState = [_x, "onState"] call _getCode;
private _onEntry = [_x, "onEntry"] call _getCode;
private _onExit = [_x, "onExit"] call _getCode;
// Collect all the transitions for the state
private _transitions = [];
{
private _transitionName = configName _x;
private _targetState = getText (_x >> "targetState");
private _events = getArray (_x >> "events") apply { toLower _x};
private _condition = [_x, "condition"] call _getCode;
private _onTransition = [_x, "onTransition"] call _getCode;
_transitions pushBack [_transitionName, _condition, _events, _onTransition, _targetState];
} forEach ("true" configClasses _x);
_states pushBack [_stateName, _onState, _onEntry, _onExit, _transitions];
} forEach ("true" configClasses _stateMachineConfig);
// Helper method for finding the desired state when linking (See below)
private _getState = {
params ["_stateName"];
private _state = ["Invalid", {}, {}, {}, []];
{
if (_stateName == (_x select 0)) exitWith {_state = _x};
} forEach _states;
_state;
};
_stateMachine setvariable [QGVAR(allStates), _states];
// Now we have collected all the states, link them in transitions so we do not have to look them up on state transitions
{
_x params ["_stateName"];
_stateMachine setvariable [_stateName, _x];
} forEach _states;
_stateMachine;

View File

@ -1,24 +0,0 @@
#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

@ -0,0 +1,16 @@
/*
* Author: BaerMitUmlaut
* Handles a unit entering cardiac arrest.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
_unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime];

View File

@ -0,0 +1,16 @@
/*
* Author: BaerMitUmlaut
* Raises the transition to the next state instantly when fatally injured.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
[QGVAR(FatalInjuryInstantTransition), _unit] call CBA_fnc_localEvent;

View File

@ -1,55 +0,0 @@
#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), DEFAULT_BLOOD_VOLUME], 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];
if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then {
[_unit, "moan", PAIN_TO_MOAN(_pain)] call EFUNC(medical_engine,playInjuredSound);
};

View File

@ -52,7 +52,7 @@ 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);
[QGVAR(TakenInjury), _unit] call CBA_fnc_localEvent;
if !(_unit getVariable [QGVAR(isBleeding), false]) then {
_unit setVariable [QGVAR(isBleeding), true, true];

View File

@ -0,0 +1,16 @@
/*
* Author: BaerMitUmlaut
* Handles a unit entering cardiac arrest.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
_unit setVariable [QGVAR(cardiacArrestStart), nil];

View File

@ -81,7 +81,7 @@ if (_isDead) exitWith {};
*/
[_unit, true] call EFUNC(medical_engine,setUnconsciousAnim);
[_unit, "Unconscious", []] call FUNC(stateEvent);
[QGVAR(Unconscious), _unit] call CBA_fnc_localEvent;
["ace_unconscious", [_unit, true]] call CBA_fnc_globalEvent;
// auto wake up

View File

@ -1,52 +0,0 @@
/*
* Author: Glowbal
*
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Event name <STRING>
* 2: Event Arguments
*
* ReturnValue:
* Name of the state after handling the state event <STRING>
*
* Example:
* [unit, "TakenInjury", []] call ace_medical_stateEvent;
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_event", "_args"];
diag_log format["ace_medical_stateEvent: %1", _this];
_event = toLower _event;
private _unitState = _unit getVariable [QGVAR(state), [CBA_missionTime, GVAR(STATE_MACHINE) getVariable "Default"]];
_unitState params ["_lastTime", "_state"];
_state params ["_name", "_handler", "_onEntry", "_onExit", "_transitions"];
private _newStateName = _name;
{
_x params ["_transitionName", "_condition", "_events", "_onTransition", "_targetStateName"];
if (_event in _events && {[_unit, _event, _args] call _condition}) exitWith {
private _targetState = GVAR(STATE_MACHINE) getVariable _targetStateName;
_targetState params ["_targetStateName", "_targetStateHandler", "_targetStateOnEntry", "_targetStateOnExit", "_targetStateTansitions"];
_newStateName = _targetStateName;
// Handle state leaving
[_unit, _event, _args] call _onExit;
[_unit, _event, _args] call _onTransition;
// Switch the state
_unitState set [1, _targetState];
_unit setvariable [QGVAR(state), _unitState];
// Enter the state
[_unit, _event, _args] call _targetStateOnEntry;
};
} forEach _transitions;
_newStateName;

View File

@ -1,45 +0,0 @@
#include "script_component.hpp"
// Delay between state runs
#define DELAY 1
#define DEFAULT_STATE [0, "Default", {}, {}, {}, []]
GVAR(monitoredUnitsList) = [];
GVAR(monitoredUnitsListIsSorted) = false;
[{
params ["_args", "_pfhId"];
if (!GVAR(monitoredUnitsListIsSorted)) then {
GVAR(monitoredUnitsList) sort true;
GVAR(monitoredUnitsListIsSorted) = true;
};
private _delete = false;
private _exit = false;
{
_x params ["_unit"];
if (!isNull _unit && alive _unit) then {
private _unitState = _unit getVariable [QGVAR(state), [-1, DEFAULT_STATE]];
_unitState params ["_lastTime", "_state"];
if (CBA_missionTime - _lastTime < DELAY) exitWith { _exit = true; };
_state params ["_name", "_handler", "_onEntry", "_onExit", "_transitions"];
_unitState set [0, CBA_missionTime];
_unit setvariable [QGVAR(state), _unitState];
[_unit, _name, _lastTime] call _handler;
} else {
_delete = true;
GVAR(monitoredUnitsList) set [_forEachIndex, objNull];
};
if (_exit) exitWith {};
} forEach GVAR(monitoredUnitsList);
if (_delete) then {
GVAR(monitoredUnitsList) = GVAR(monitoredUnitsList) - [objNull];
};
}, 0, []] call CBA_fnc_addPerFrameHandler;

View File

@ -0,0 +1,19 @@
/*
* Author: BaerMitUmlaut
* Gives the unit a second chance and prevents death for 1 second.
*
* Arguments:
* 0: The Unit <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
_unit setVariable [QGVAR(deathBlocked), true];
[{
_this setVariable [QGVAR(deathBlocked), false];
}, _unit, 1] call CBA_fnc_waitAndExecute;

View File

@ -140,6 +140,6 @@ 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];
[_unit, "MinUnconsciousTimer", []] call FUNC(stateEvent);
[QGVAR(MinUnconsciousTimer), _unit] call CBA_fnc_localEvent;
};
};

View File

@ -2,7 +2,7 @@
#define COMPONENT_BEAUTIFIED Medical Core
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
#define DEBUG_MODE_FULL
#define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

View File

@ -3,4 +3,5 @@ PREP(handleWoundReceived);
PREP(isBleeding);
PREP(onBleeding);
PREP(createBlood);
PREP(serverCleanupBlood);
PREP(spurt);

View File

@ -10,37 +10,33 @@ if (isServer) then {
[QGVAR(bloodDropCreated), {
params ["_bloodDrop"];
GVAR(bloodDrops) pushBack _bloodDrop;
// Add to created queue with format [expireTime, object]
private _index = GVAR(bloodDrops) pushBack [(CBA_missionTime + BLOOD_OBJECT_LIFETIME), _bloodDrop];
if (count GVAR(bloodDrops) >= MAX_BLOOD_OBJECTS) then {
private _deletedBloodDrop = GVAR(bloodDrops) deleteAt 0;
(GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"];
deleteVehicle _deletedBloodDrop;
};
[{deleteVehicle _this}, _bloodDrop, BLOOD_OBJECT_LIFETIME] call CBA_fnc_waitAndExecute;
if (_index == 1) then { // Start the waitAndExecute loop
[FUNC(serverCleanupBlood), [], BLOOD_OBJECT_LIFETIME] call CBA_fnc_waitAndExecute;
};
}] call CBA_fnc_addEventHandler;
};
["ace_settingsInitialized", {
TRACE_1("settingsInitialized", GVAR(enabledFor));
if (GVAR(enabledFor) == 0) exitWith {}; // 0: disabled
if (GVAR(enabledFor) == 1 && {!hasInterface}) exitWith {}; // 1: enabledFor_OnlyPlayers
if ((GVAR(enabledFor) == 1) && {!hasInterface}) exitWith {}; // 1: enabledFor_OnlyPlayers
private _listcode = if (GVAR(enabledFor) == 1) then {
{[ACE_player] select {[_x] call FUNC(isBleeding)}} // ace_player is only possible local player
} else {
{allUnits select {(local _x) && {[_x] call FUNC(isBleeding)}}}; // filter all local bleeding units
};
private _stateMachine = [_listcode, true] call CBA_statemachine_fnc_create;
[_stateMachine, {call FUNC(onBleeding)}, {}, {}, "Bleeding"] call CBA_statemachine_fnc_addState;
[QEGVAR(medical_engine,woundReceived), FUNC(handleWoundReceived)] call CBA_fnc_addEventHandler;
/*["CAManBase", "hit", { @todo, remove?
params ["_unit"];
if (GVAR(enabledFor) == 1 && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {};
_this call FUNC(hit);
}] call CBA_fnc_addClassEventHandler;*/
}] call CBA_fnc_addEventHandler;

View File

@ -16,7 +16,7 @@
params ["_unit", "", "_damage", "_shooter"];
if (GVAR(enabledFor) == 1 && {!isPlayer _unit || {_unit == ACE_player}}) exitWith {};
if (GVAR(enabledFor) == 1 && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {};
if (vehicle _unit != _unit && {!((vehicle _unit) isKindOf "StaticWeapon")}) exitWith {}; // Don't bleed on ground if mounted
_damage = _damage min 1;

View File

@ -0,0 +1,23 @@
/*
* Author: PabstMirror
* Loop that cleans up blood
*
* Arguments:
* None
*
* ReturnValue:
* None
*
* Public: No
*/
#include "script_component.hpp"
(GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"];
deleteVehicle _deletedBloodDrop;
// If we cleaned out the array, exit loop
if (GVAR(bloodDrops) isEqualTo []) exitWith {};
// Wait until the next blood drop in the queue will expire
(GVAR(bloodDrops) select 0) params ["_expireTime"];
[FUNC(serverCleanupBlood), [], (_expireTime - CBA_missionTime)] call CBA_fnc_waitAndExecute;