Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add localUnits array and use that inside medical statemachines #4836

Merged
merged 19 commits into from
Feb 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions addons/common/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ PREP(getFirstObjectIntersection);
PREP(getFirstTerrainIntersection);
PREP(getGunner);
PREP(getInPosition);
PREP(getLocalUnits);
PREP(getMapData);
PREP(getMapGridData);
PREP(getMapGridFromPos);
Expand Down Expand Up @@ -156,6 +157,7 @@ PREP(setPitchBankYaw);
PREP(setPlayerOwner);
PREP(setProne);
PREP(setSetting);
PREP(setupLocalUnitsHandler);
PREP(setVariableJIP);
PREP(setVariablePublic);
PREP(setVolume);
Expand Down
2 changes: 2 additions & 0 deletions addons/common/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ GVAR(statusEffect_isGlobal) = [];

GVAR(setHearingCapabilityMap) = [];

[] call FUNC(setupLocalUnitsHandler); // Add local units event handlers (ace_common_localUnits)

//////////////////////////////////////////////////
// Set up PlayerChanged eventhandler for pre init (EH is installed in postInit)
//////////////////////////////////////////////////
Expand Down
23 changes: 23 additions & 0 deletions addons/common/functions/fnc_getLocalUnits.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "script_component.hpp"
/*
* Author: dedmen
* Gets localUnits array filtering out nullObjects.
* If you can handle null objects you can use the array `ace_common_localUnits` directly.
* Should be equivalent to `allUnits select {local _x}`
*
* Arguments:
* Nothing
*
* Return Value:
* Array of local Units <ARRAY>
*
* Example:
* [] call ace_common_fnc_getLocalUnits
*
* Public: Yes
*/

// Remove null objects
GVAR(localUnits) = GVAR(localUnits) - [objNull];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can check diag_frameNo against a global variable so we only remove null objects once a frame to get us a little more perf.
But I'm not sure if GVAR(localUnits) = GVAR(localUnits) - [objNull]; is really that expensive that it's worth it. Needs profiling with atleast a hundred local units.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we only need to run this if there was a deletedEH in the last 2-3 frames. But I don't think it hurts.
Considering this will already be about a 100x improvement vs iterating through allUnits everytime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also to checking diag_frameNo objects are deleted in simulation cycle. Draw3D runs after that in the same frame. So that could cause Draw3D to still get null objects.


GVAR(localUnits)
76 changes: 76 additions & 0 deletions addons/common/functions/fnc_setupLocalUnitsHandler.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "script_component.hpp"
/*
* Author: dedmen
* Adds the local unit event handlers.
* Access with function `ace_common_fnc_getLocalUnits` or array `ace_common_localUnits`
*
* Arguments:
* Nothing
*
* Return Value:
* Nothing
*
* Example:
* [] call ace_common_fnc_setupLocalUnitsHandler
*
* Public: No
*/

GVAR(localUnits) = [];

// Eventhandlers to maintain array of localUnits
["CAManBase", "init", {
params ["_unit"];
TRACE_2("unit init",_unit,local _unit);

if (local _unit) then {
if (!alive _unit) exitWith {};
GVAR(localUnits) pushBack _unit;
};
}] call CBA_fnc_addClassEventHandler;

["CAManBase", "respawn", {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't "init" also fire for respawning units?
But I guess they might be !alive at init?

Respawning in MP should be tested.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Init does not fire for respawned objects.

params ["_unit"];
TRACE_2("unit respawn",_unit,local _unit);

if (local _unit) then {
if (!alive _unit) exitWith {};
GVAR(localUnits) pushBack _unit;
};
}] call CBA_fnc_addClassEventHandler;

["CAManBase", "local", {
params ["_unit", "_local"];
TRACE_2("unit local",_unit,_local);

if (_local) then {
if (!alive _unit) exitWith {};
GVAR(localUnits) pushBack _unit;
} else {
GVAR(localUnits) deleteAt (GVAR(localUnits) find _unit);
};
}] call CBA_fnc_addClassEventHandler;

["CAManBase", "deleted", {
params ["_unit"];
TRACE_2("unit deleted",_unit,local _unit);

if (local _unit) then {
[{
params ["_unit"];
TRACE_3("unit deleted nextFrame",_unit,local _unit,isNull _unit);
if (isNull _unit) then { // If it is not null then the deleted EH was Fake.
GVAR(localUnits) = GVAR(localUnits) - [objNull];
Copy link
Contributor Author

@dedmen dedmen Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I delete all objNull here as using find to find a null object will find the first null object and not the one the deleted EH belongs to anyway.
I would prefer to just call FUNC(getLocalUnits) here in case we add a check to getLocalUnits so it only removes null objects once per frame.
But it would hurt readability.

};
}, [_unit]] call CBA_fnc_execNextFrame;
};
}] call CBA_fnc_addClassEventHandler;

["CAManBase", "killed", {
params ["_unit"];
TRACE_2("unit killed",_unit,local _unit);

if (local _unit) then {
GVAR(localUnits) deleteAt (GVAR(localUnits) find _unit);
};
}] call CBA_fnc_addClassEventHandler;
2 changes: 1 addition & 1 deletion addons/medical_ai/StateMachine.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class GVAR(stateMachine) {
list = "allUnits select {local _x}";
list = QUOTE(call EFUNC(common,getLocalUnits));
skipNull = 1;

class Initial {
Expand Down
4 changes: 2 additions & 2 deletions addons/medical_blood/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ if (isServer) then {
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
{[ACE_player]} // ace_player is only possible local player
} else {
{allUnits select {(local _x) && {[_x] call FUNC(isBleeding)}}}; // filter all local bleeding units
EFUNC(common,getLocalUnits) // filter all local units
};

private _stateMachine = [_listcode, true] call CBA_statemachine_fnc_create;
Expand Down
1 change: 1 addition & 0 deletions addons/medical_blood/functions/fnc_onBleeding.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

params ["_unit"];

if (!([_unit] call FUNC(isBleeding))) exitWith {};
if (((vehicle _unit) != _unit) && {!((vehicle _unit) isKindOf "StaticWeapon")}) exitWith {}; // Don't bleed on ground if mounted

private _lastTime = _unit getVariable [QGVAR(lastTime), -10];
Expand Down