diff --git a/addons/medical_blood/CfgEventHandlers.hpp b/addons/medical_blood/CfgEventHandlers.hpp index becf3950523..0d3301d6e0a 100644 --- a/addons/medical_blood/CfgEventHandlers.hpp +++ b/addons/medical_blood/CfgEventHandlers.hpp @@ -1,4 +1,3 @@ - class Extended_PreStart_EventHandlers { class ADDON { init = QUOTE(call COMPILE_FILE(XEH_preStart)); diff --git a/addons/medical_blood/README.md b/addons/medical_blood/README.md index 29632ffd29e..848f8f0308c 100644 --- a/addons/medical_blood/README.md +++ b/addons/medical_blood/README.md @@ -1,7 +1,7 @@ ace_medical_blood -=============== +================= -Adds blood visual effect on the ground near a bleeding player. +Creates blood drops on the ground near bleeding units. ## Maintainers diff --git a/addons/medical_blood/XEH_PREP.hpp b/addons/medical_blood/XEH_PREP.hpp index aa7d3583888..ebed657cc57 100644 --- a/addons/medical_blood/XEH_PREP.hpp +++ b/addons/medical_blood/XEH_PREP.hpp @@ -1,7 +1,7 @@ - +PREP(cleanupLoop); +PREP(createBlood); PREP(handleWoundReceived); +PREP(init); PREP(isBleeding); PREP(onBleeding); -PREP(createBlood); -PREP(serverCleanupBlood); PREP(spurt); diff --git a/addons/medical_blood/XEH_postInit.sqf b/addons/medical_blood/XEH_postInit.sqf index 11f86fdaca7..02201f5506f 100644 --- a/addons/medical_blood/XEH_postInit.sqf +++ b/addons/medical_blood/XEH_postInit.sqf @@ -10,33 +10,18 @@ if (isServer) then { [QGVAR(bloodDropCreated), { params ["_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 { + // Add to created queue with format: [expire time, blood object] + private _index = GVAR(bloodDrops) pushBack [CBA_missionTime + GVAR(bloodLifetime), _bloodDrop]; + + if (count GVAR(bloodDrops) >= GVAR(maxBloodObjects)) then { (GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"]; deleteVehicle _deletedBloodDrop; }; - if (_index == 1) then { // Start the waitAndExecute loop - [FUNC(serverCleanupBlood), [], BLOOD_OBJECT_LIFETIME] call CBA_fnc_waitAndExecute; + // Start the cleanup loop + if (_index == 0) then { + [FUNC(cleanupLoop), [], GVAR(bloodLifetime)] 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 - - private _listcode = if (GVAR(enabledFor) == 1) then { - {if (alive ACE_player) then {[ACE_player]} else {[]}} // ace_player is only possible local player - } else { - EFUNC(common,getLocalUnits) // filter all local units - }; - - private _stateMachine = [_listcode, true] call CBA_statemachine_fnc_create; - [_stateMachine, LINKFUNC(onBleeding), {}, {}, "Bleeding"] call CBA_statemachine_fnc_addState; - - [QEGVAR(medical,woundReceived), FUNC(handleWoundReceived)] call CBA_fnc_addEventHandler; -}] call CBA_fnc_addEventHandler; diff --git a/addons/medical_blood/config.cpp b/addons/medical_blood/config.cpp index 5c133b94568..3e5d5227daa 100644 --- a/addons/medical_blood/config.cpp +++ b/addons/medical_blood/config.cpp @@ -14,5 +14,5 @@ class CfgPatches { }; }; -#include "ACE_Settings.hpp" #include "CfgEventHandlers.hpp" +#include "ACE_Settings.hpp" diff --git a/addons/medical_blood/functions/fnc_serverCleanupBlood.sqf b/addons/medical_blood/functions/fnc_cleanupLoop.sqf similarity index 55% rename from addons/medical_blood/functions/fnc_serverCleanupBlood.sqf rename to addons/medical_blood/functions/fnc_cleanupLoop.sqf index 5a1762a7a80..e8461b2e316 100644 --- a/addons/medical_blood/functions/fnc_serverCleanupBlood.sqf +++ b/addons/medical_blood/functions/fnc_cleanupLoop.sqf @@ -1,23 +1,26 @@ #include "script_component.hpp" /* * Author: PabstMirror - * Loop that cleans up blood + * Handles cleaning up blood objects that have reached the end of their lifetime. * * Arguments: * None * - * ReturnValue: + * Return Value: * None * + * Example: + * [] call ace_medical_blood_fnc_cleanupLoop + * * Public: No */ - + (GVAR(bloodDrops) deleteAt 0) params ["", "_deletedBloodDrop"]; deleteVehicle _deletedBloodDrop; -// If we cleaned out the array, exit loop +// Exit the loop if we have cleaned out the array 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; +[FUNC(cleanupLoop), [], _expireTime - CBA_missionTime] call CBA_fnc_waitAndExecute; diff --git a/addons/medical_blood/functions/fnc_createBlood.sqf b/addons/medical_blood/functions/fnc_createBlood.sqf index 8d3fbc8776e..e54247d02ef 100644 --- a/addons/medical_blood/functions/fnc_createBlood.sqf +++ b/addons/medical_blood/functions/fnc_createBlood.sqf @@ -1,15 +1,15 @@ #include "script_component.hpp" /* * Author: Glowbal - * Spawn a blood drop. + * Creates a blood object and handles its cleanup. * Available blood drop classes are blooddrop_1 through blooddrop_4. * * Arguments: - * 0: classname of blood drop + * 0: Blood Drop Type * 1: Position * * Return Value: - * Created blood drop + * Blood Drop * * Example: * ["blooddrop_2", getPos player] call ace_medical_blood_fnc_createBlood @@ -17,15 +17,15 @@ * Public: No */ -params ["_type", "_pos"]; -TRACE_2("creating blood",_type,_pos); +params ["_type", "_position"]; +TRACE_2("Creating blood",_type,_position); private _model = GVAR(models) getVariable _type; -private _object = createSimpleObject [_model, [0,0,0]]; -_object setDir random 360; -_object setPos _pos; +private _bloodDrop = createSimpleObject [_model, [0, 0, 0]]; +_bloodDrop setDir random 360; +_bloodDrop setPos _position; -[QGVAR(bloodDropCreated), [_object]] call CBA_fnc_serverEvent; +[QGVAR(bloodDropCreated), _bloodDrop] call CBA_fnc_serverEvent; -_object +_bloodDrop diff --git a/addons/medical_blood/functions/fnc_handleWoundReceived.sqf b/addons/medical_blood/functions/fnc_handleWoundReceived.sqf index 20abbd4621c..7447cac52fb 100644 --- a/addons/medical_blood/functions/fnc_handleWoundReceived.sqf +++ b/addons/medical_blood/functions/fnc_handleWoundReceived.sqf @@ -1,13 +1,13 @@ #include "script_component.hpp" /* * Author: Glowbal, commy2 - * Handle wounds received event. + * Handles the wounds received event by triggering any needed blood creation. * * Arguments: - * 0: unit - * 1: bodyPart - * 2: damage - * 3: shooter + * 0: Unit + * 1: Body Part (not used) + * 2: Damage + * 3: Shooter * * Return Value: * None @@ -20,16 +20,16 @@ params ["_unit", "", "_damage", "_shooter"]; -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 +// Don't bleed when players only and a non-player unit is wounded +if (GVAR(enabledFor) == BLOOD_ONLY_PLAYERS && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {}; -_damage = _damage min 1; +// Don't bleed on the ground if in a vehicle +if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")}) exitWith {}; -if (isNull _shooter) exitWith { // won't be able to calculate the direction properly, so instead we pick something at random - [QGVAR(spurt), [_unit, random 360, _damage]] call CBA_fnc_serverEvent; +private _bulletDir = if (isNull _shooter) then { + random 360 // Cannot calculate the direction properly, pick a random direction +} else { + _shooter getDir _unit // Calculate the bullet direction }; -// Calculate bulletDirection -private _bulletDir = _shooter getDir _unit; - -[QGVAR(spurt), [_unit, _bulletDir, _damage]] call CBA_fnc_serverEvent; +[QGVAR(spurt), [_unit, _bulletDir, _damage min 1]] call CBA_fnc_serverEvent; diff --git a/addons/medical_blood/functions/fnc_init.sqf b/addons/medical_blood/functions/fnc_init.sqf new file mode 100644 index 00000000000..336d964de76 --- /dev/null +++ b/addons/medical_blood/functions/fnc_init.sqf @@ -0,0 +1,65 @@ +#include "script_component.hpp" +/* + * Author: mharis001 + * Initializes the medical blood system based on the given mode. + * Should only be called from the CBA setting changed script. + * + * Arguments: + * 0: Mode + * + * Return Value: + * None + * + * Example: + * [2] call ace_medical_blood_fnc_init + * + * Public: No + */ + +params ["_mode"]; + +// Exit if setting is refreshed to the same value +if (!isNil QGVAR(currentSetup) && {_mode == GVAR(currentSetup)}) exitWith { + TRACE_2("Setting refreshed to current setup",GVAR(currentSetup),_mode); +}; + +// Track this new configuration that will be set up +GVAR(currentSetup) = _mode; + +// Delete current state machine if it exists +if (!isNil QGVAR(stateMachine)) then { + GVAR(stateMachine) call CBA_statemachine_fnc_delete; + GVAR(stateMachine) = nil; +}; + +// Remove wound received if it was previously added +if (!isNil QGVAR(woundReceivedEH)) then { + [QEGVAR(medical,woundReceived), GVAR(woundReceivedEH)] call CBA_fnc_removeEventHandler; + GVAR(woundReceivedEH) = nil; +}; + +// Don't need to set up anything if blood is disabled or players only on a non-player machine +if (_mode == BLOOD_DISABLED || {_mode == BLOOD_ONLY_PLAYERS && {!hasInterface}}) exitWith { + TRACE_1("Mode does not require any setup",_mode); +}; + +private _listCode = if (_mode == BLOOD_ONLY_PLAYERS) then { + // ACE_player is the only possible local player + { + if (alive ACE_player) then { + [ACE_player] + } else { + [] + }; + } +} else { + // Filter all local units + EFUNC(common,getLocalUnits) +}; + +GVAR(stateMachine) = [_listCode, true] call CBA_statemachine_fnc_create; +[GVAR(stateMachine), LINKFUNC(onBleeding), {}, {}, "Bleeding"] call CBA_statemachine_fnc_addState; + +GVAR(woundReceivedEH) = [QEGVAR(medical,woundReceived), FUNC(handleWoundReceived)] call CBA_fnc_addEventHandler; + +TRACE_3("Set up state machine and wounds event",_mode,GVAR(stateMachine),GVAR(woundReceivedEH)); diff --git a/addons/medical_blood/functions/fnc_isBleeding.sqf b/addons/medical_blood/functions/fnc_isBleeding.sqf index b063c52ab0b..14aecbb55b6 100644 --- a/addons/medical_blood/functions/fnc_isBleeding.sqf +++ b/addons/medical_blood/functions/fnc_isBleeding.sqf @@ -1,13 +1,13 @@ #include "script_component.hpp" /* * Author: Glowbal - * Check if is bleeding + * Checks if the given unit is bleeding. Handles both ACE Medical and Vanilla. * * Arguments: - * 0: unit + * 0: Unit * * Return Value: - * is Bleeding + * Is Bleeding * * Example: * [player] call ace_medical_blood_fnc_isBleeding diff --git a/addons/medical_blood/functions/fnc_onBleeding.sqf b/addons/medical_blood/functions/fnc_onBleeding.sqf index 2fe7b340438..8b6bcbb8f6b 100644 --- a/addons/medical_blood/functions/fnc_onBleeding.sqf +++ b/addons/medical_blood/functions/fnc_onBleeding.sqf @@ -1,13 +1,14 @@ #include "script_component.hpp" /* * Author: Glowbal - * handle bleeding state (state machine) + * Handles periodically creating blood for a bleeding unit. + * Called from the medical_blood state machine. * * Arguments: - * 0: unit + * 0: Unit * * Return Value: - * is Bleeding + * None * * Example: * [player] call ace_medical_blood_fnc_onBleeding @@ -17,20 +18,20 @@ params ["_unit"]; -if (!([_unit] call FUNC(isBleeding))) exitWith {}; -if (((vehicle _unit) != _unit) && {!((vehicle _unit) isKindOf "StaticWeapon")}) exitWith {}; // Don't bleed on ground if mounted +// Nothing to do if unit is not bleeding +if !(_unit call FUNC(isBleeding)) exitWith {}; + +// Don't bleed on the ground if in a vehicle +if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")}) exitWith {}; if (CBA_missionTime > (_unit getVariable [QGVAR(nextTime), -10])) then { private _bloodLoss = (if (GVAR(useAceMedical)) then {GET_BLOOD_LOSS(_unit) * 2.5} else {getDammage _unit * 2}) min 6; - TRACE_2("",_unit,_bloodLoss); _unit setVariable [QGVAR(nextTime), CBA_missionTime + 8 + random 2 - _bloodLoss]; + TRACE_2("Creating blood drop for bleeding unit",_unit,_bloodLoss); + private _position = getPosASL _unit; - _position = _position vectorAdd [ - random 0.4 - 0.2, - random 0.4 - 0.2, - 0 - ]; + _position = _position vectorAdd [random 0.4 - 0.2, random 0.4 - 0.2, 0]; _position set [2, 0]; private _bloodDrop = ["blooddrop_1", "blooddrop_2", "blooddrop_3", "blooddrop_4"] select floor (_bloodLoss min 3); diff --git a/addons/medical_blood/functions/fnc_spurt.sqf b/addons/medical_blood/functions/fnc_spurt.sqf index 9e3a1bf5e24..fd5c7a9fc0d 100644 --- a/addons/medical_blood/functions/fnc_spurt.sqf +++ b/addons/medical_blood/functions/fnc_spurt.sqf @@ -1,18 +1,18 @@ #include "script_component.hpp" /* * Author: Sickboy - * Spurt blood on the ground + * Spurts blood on the ground based on the direction and damage. * * Arguments: - * 0: unit - * 1: direction - * 2: damage + * 0: Unit + * 1: Direction + * 2: Damage * * Return Value: * None * * Example: - * [UNIT, random 360, 1] call ace_medical_blood_fnc_spurt + * [player, random 360, 1] call ace_medical_blood_fnc_spurt * * Public: No */ @@ -21,20 +21,20 @@ #define DISTANCE_BETWEEN_DROPS 0.20 #define OFFSET 0.25 -params ["_unit", "_dir", "_damage"]; +params ["_unit", "_direction", "_damage"]; private _distanceBetweenDrops = DISTANCE_BETWEEN_DROPS * _damage; private _offset = OFFSET + _distanceBetweenDrops; -private _pos = _unit getPos [_offset, _dir]; +private _position = _unit getPos [_offset, _direction]; -["blooddrop_2", _pos, _dir] call FUNC(createBlood); +["blooddrop_2", _position, _direction] call FUNC(createBlood); private _dropAmount = ceil (MAXIMUM_DROPS * _damage); -TRACE_2("spurt blood",_dropAmount,_damage); +TRACE_2("Spurting blood",_dropAmount,_damage); if (_dropAmount > 1) then { for "_i" from 2 to _dropAmount do { - _pos = _pos getPos [_distanceBetweenDrops, _dir]; - ["blooddrop_1", _pos, _dir] call FUNC(createBlood); + _position = _position getPos [_distanceBetweenDrops, _direction]; + ["blooddrop_1", _position, _direction] call FUNC(createBlood); }; }; diff --git a/addons/medical_blood/initSettings.sqf b/addons/medical_blood/initSettings.sqf index c47372c5e29..c2c52f93b89 100644 --- a/addons/medical_blood/initSettings.sqf +++ b/addons/medical_blood/initSettings.sqf @@ -2,9 +2,26 @@ QGVAR(enabledFor), "LIST", [LSTRING(EnabledFor_DisplayName), LSTRING(EnabledFor_Description)], - ELSTRING(medical,Category), - [[0, 1, 2], [ELSTRING(Common,Disabled), LSTRING(OnlyPlayers), ELSTRING(Common,Enabled)], 2], + [ELSTRING(medical,Category), LSTRING(SubCategory)], + [[BLOOD_DISABLED, BLOOD_ONLY_PLAYERS, BLOOD_ENABLED], [ELSTRING(Common,Disabled), LSTRING(OnlyPlayers), ELSTRING(Common,Enabled)], 2], true, - {[QGVAR(enabledFor), _this] call EFUNC(common,cbaSettings_settingChanged)}, + LINKFUNC(init) +] call CBA_settings_fnc_init; + +[ + QGVAR(maxBloodObjects), + "LIST", + [LSTRING(MaxBloodObjects_DisplayName), LSTRING(MaxBloodObjects_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory)], + [[50, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000], [/* settings function will auto create names */], 5], + true +] call CBA_settings_fnc_init; + +[ + QGVAR(bloodLifetime), + "TIME", + [LSTRING(BloodLifetime_DisplayName), LSTRING(BloodLifetime_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory)], + [1, 3600, 900], true ] call CBA_settings_fnc_init; diff --git a/addons/medical_blood/script_component.hpp b/addons/medical_blood/script_component.hpp index ef72e2fdd5a..d2bcbf9599b 100644 --- a/addons/medical_blood/script_component.hpp +++ b/addons/medical_blood/script_component.hpp @@ -2,7 +2,7 @@ #define COMPONENT_BEAUTIFIED Medical Blood #include "\z\ace\addons\main\script_mod.hpp" -// #define DEBUG_ENABLED_MEDICAL_BLOOD +// #define DEBUG_MODE_FULL // #define DISABLE_COMPILE_CACHE // #define ENABLE_PERFORMANCE_COUNTERS @@ -17,5 +17,6 @@ #include "\z\ace\addons\medical_engine\script_macros_medical.hpp" #include "\z\ace\addons\main\script_macros.hpp" -#define MAX_BLOOD_OBJECTS 500 -#define BLOOD_OBJECT_LIFETIME 900 +#define BLOOD_DISABLED 0 +#define BLOOD_ONLY_PLAYERS 1 +#define BLOOD_ENABLED 2 diff --git a/addons/medical_blood/stringtable.xml b/addons/medical_blood/stringtable.xml index ee3a064f4da..4ffda9919e1 100644 --- a/addons/medical_blood/stringtable.xml +++ b/addons/medical_blood/stringtable.xml @@ -2,10 +2,17 @@ - Bleeding Effect - Blutungseffekt - 出血中の効果 - Эффекты кровотечения + Blood + Sang + Sangre + Sangue + Krew + Кровь + Blut + Krev + Sangue + 혈흔 + Enable Blood Drops @@ -22,6 +29,18 @@ Enables the creation of blood drops when units are bleeding or take damage. + + Max Blood Objects + + + Sets the maximum number of blood drop objects which can be spawned, excessive amounts can cause FPS lag. + + + Blood Lifetime + + + Controls the lifetime of blood drop objects. + Only Players プレイヤーのみ