mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
742626ff1a
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
140 lines
6.4 KiB
Plaintext
140 lines
6.4 KiB
Plaintext
#include "..\script_component.hpp"
|
|
/*
|
|
* Author: alganthe
|
|
* Internal function used by ace_ai_fnc_garrison to make the units move to the positions it picked.
|
|
*
|
|
* Arguments:
|
|
* 0: Array of arrays <ARRAY>
|
|
* 0: Unit needing to be placed <UNIT>
|
|
* 1: Position the unit need to be placed at <POSITION>
|
|
*
|
|
* Return Value:
|
|
* Nothing
|
|
*
|
|
* Example:
|
|
* [ [unit1, [10, 10, 10]], [unit2, [30, 30, 30]], [unitN, getPos player] ] call ace_ai_fnc_garrisonMove
|
|
*
|
|
* Public: No
|
|
*/
|
|
|
|
params [ ["_unitMoveList", nil, [[]]] ];
|
|
|
|
if (isNil "_unitMoveList") exitWith {};
|
|
|
|
// Start initial movement
|
|
private _unitMoveListUnits = (_unitMoveList apply {_x select 0});
|
|
[QGVAR(setBehaviour), [(_unitMoveListUnits select {leader _x == _x}), "AWARE"], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
|
[QGVAR(AISection), [_unitMoveListUnits, ["FSM"], false], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
|
[QGVAR(doMove), [_unitMoveList], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
|
[QGVAR(enableAttack), [_unitMoveListUnits select {leader _x == _x}, false], _unitMoveListUnits] call CBA_fnc_targetEvent;
|
|
|
|
{
|
|
_x setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
|
_x setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
|
} foreach _unitMoveListUnits;
|
|
|
|
// Avoid duplicate PFHs
|
|
if (isNil QGVAR(garrison_moveUnitPFH)) then {
|
|
missionNameSpace setVariable [QGVAR(garrison_moveUnitPFH), true, true];
|
|
|
|
// PFH checking if the units have reached their destination
|
|
[{
|
|
params ["_args", "_pfhID"];
|
|
|
|
private _unitMoveList = missionNameSpace getVariable [QGVAR(garrison_unitMoveList), []];
|
|
|
|
// End PFH if all units are placed / unable to reach position
|
|
if (_unitMoveList isEqualTo []) then {
|
|
missionNameSpace setVariable [QGVAR(garrison_moveUnitPFH), nil, true];
|
|
LOG("garrisonMove PFH: PFH finished it's job | deleting PFH");
|
|
_pfhID call CBA_fnc_removePerFrameHandler;
|
|
|
|
} else {
|
|
{
|
|
_x params ["_unit", "_pos"];
|
|
|
|
private _fnc_attemptFailed = {
|
|
if (_failSafeRemainingAttemps == 0 ) then {
|
|
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
|
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
|
[QGVAR(unGarrison), [[_unit]], _unit] call CBA_fnc_targetEvent;
|
|
_unitMoveList deleteAt (_unitMoveList find _x);
|
|
LOG("garrisonMove PFH: all moving commands failed | restoring AI capabilities");
|
|
|
|
} else {
|
|
_unit setVariable [QGVAR(garrisonMove_failSafe), [_failSafeTimer + 15, _failSafeRemainingAttemps - 1]];
|
|
[QGVAR(doMove), [[[_unit, _pos]]], _unit] call CBA_fnc_targetEvent;
|
|
LOG("garrisonMove PFH unitReady: unit not close enough | Sending another doMove command");
|
|
};
|
|
};
|
|
|
|
private _fnc_attemptSuccessful = {
|
|
_unit setVariable [QGVAR(garrisonMove_failSafe), nil, true];
|
|
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), nil, true];
|
|
_unit setVariable [QGVAR(garrisonned), true, true];
|
|
_unitMoveList deleteAt (_unitMoveList find _x);
|
|
|
|
[QGVAR(AISection), [[_unit], ["PATH"], false], _unit] call CBA_fnc_targetEvent;
|
|
[QGVAR(AISection), [[_unit], ["FSM"], true], _unit] call CBA_fnc_targetEvent;
|
|
|
|
if ({(_x select 0) in units _unit && {!isPlayer (_x select 0)}} count _unitMoveList == 0) then {
|
|
[QGVAR(enableAttack), [[_unit], true], _unit] call CBA_fnc_targetEvent;
|
|
};
|
|
|
|
LOG(format [ARR_2("garrisonMove PFH: unit in position | %1 units left", count _unitMoveList)]);
|
|
};
|
|
|
|
// Check if unit is alive or even existing
|
|
if (!alive _unit || {_unit getVariable [QGVAR(garrisoned), false]}) then {
|
|
_unitMoveList deleteAt (_unitMoveList find _x);
|
|
LOG(format [ARR_2("garrisonMove PFH: unit dead, deleted or garrisoned via TP | %1 units left", count _unitMoveList)]);
|
|
|
|
} else {
|
|
private _unitPos = getPos _unit;
|
|
if (surfaceisWater _unitPos) then {
|
|
_unitPos = getPosASL _unit;
|
|
} else {
|
|
_unitPos = getPosATL _unit;
|
|
};
|
|
|
|
if (unitReady _unit) then {
|
|
// Check for distance, doMove and AI are moody and may stop for no reason, within 6 meters and ready should be fine
|
|
if (_unitPos distance _pos < 1.5) then {
|
|
call _fnc_attemptSuccessful;
|
|
|
|
} else {
|
|
// Tell the unit to move if an order wasn't given within 30s, avoid doMove spam
|
|
(_unit getVariable [QGVAR(garrisonMove_failSafe), [CBA_missionTime, 5]]) params ["_failSafeTimer", "_failSafeRemainingAttemps"];
|
|
|
|
if (_failSafeTimer <= CBA_missionTime) then {
|
|
call _fnc_attemptFailed;
|
|
};
|
|
};
|
|
} else {
|
|
(_unit getVariable [QGVAR(garrisonMove_unitPosMemory), [CBA_missionTime, [0,0,0]]]) params ["_unitPosTimer", "_unitOldPos"];
|
|
|
|
// AI may sometimes not be able to report unitReady, this is to avoid the PFH running forever
|
|
switch true do {
|
|
case ((_unitPos distance _pos) < 1.5) : {
|
|
call _fnc_attemptSuccessful;
|
|
};
|
|
|
|
case ((_unitPosTimer + 5) < CBA_missionTime && {_unitOldPos distance _unitPos < 0.5}) : {
|
|
call _fnc_attemptFailed;
|
|
};
|
|
|
|
case (_unitOldPos distance _unitPos < 0.5) : {};
|
|
|
|
default {
|
|
_unit setVariable [QGVAR(garrisonMove_unitPosMemory), [CBA_missionTime, _unitPos]];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
} foreach _unitMoveList;
|
|
|
|
missionNameSpace setVariable [QGVAR(garrison_unitMoveList), _unitMoveList, true];
|
|
};
|
|
}, 0.5, []] call CBA_fnc_addPerFrameHandler;
|
|
};
|