Skip to content

Commit

Permalink
Aircraft - Drone "Follow Unit" Waypoint Action (acemod#9889)
Browse files Browse the repository at this point in the history
* Fix "Recharge" interaction showing on destroyed drone

* Add "Follow Unit" action

* Improve condition check

* UGV Following via PFH that updates WP Pos

* Use HOLD WP for all Follow Actions

Since FOLLOW WP would stop working on AI Soldiers after some time.

* Allow selecting a follow distance

* Follow Distance under separate interaction, just like Loiter Alt

Only visible when a HOLD waypoint is selected, which is pretty much always going to have been created by the "Follow" interaction.

* Localize "Follow" Interaction

* Show structuredText Hint when following/changing distance

* Variable for cursorTarget Reuse

* Better isKindOf condition use

* Make "Ship"-kind vehicles followable

* Clean up Comments and systemChat Debugs

* Comment explanation for custom PFH solution over vanilla "Follow"-WP

* Trim excess brackets from setWaypointPosition argument

Co-Authored-By: johnb432 <58661205+johnb432@users.noreply.github.com>

* Broader determination for UGV follow distances

Co-Authored-By: PabstMirror <pabstmirror@gmail.com>

* Prevent infinite PFH loop if follow target is deleted

Co-Authored-By: PabstMirror <pabstmirror@gmail.com>

* Delete Follow WP when PFH terminates

* The ternary rules

Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>

* Various requested changes

Co-Authored-By: johnb432 <58661205+johnb432@users.noreply.github.com>

---------

Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
Co-authored-by: PabstMirror <pabstmirror@gmail.com>
  • Loading branch information
3 people authored and blake8090 committed Aug 18, 2024
1 parent 08bf8a4 commit 9cddb16
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 10 deletions.
61 changes: 55 additions & 6 deletions addons/aircraft/functions/fnc_droneAddActions.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ if (!alive _vehicle) exitWith {};
if (_vehicle getVariable [QGVAR(droneActionsAdded), false]) exitWith {};
_vehicle setVariable [QGVAR(droneActionsAdded), true];

// move to location
// Move to location
private _condition = {
params ["_vehicle"];
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
Expand All @@ -37,14 +37,63 @@ private _action = [QGVAR(droneSetWaypointMove), localize "$STR_AC_MOVE",
"\a3\3DEN\Data\CfgWaypoints\Move_ca.paa", _statement, _condition] call EFUNC(interact_menu,createAction);
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);

// Follow unit/vehicle at turret location
_condition = {
params ["_vehicle"];
private _target = cursorTarget;
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]} && {!isNull _target} && {["CAManBase", "LandVehicle", "Ship"] findIf {_target isKindOf _x} != -1}
};
_statement = {
params ["_vehicle"];
private _group = group driver _vehicle;
private _pos = ([_vehicle, [0]] call FUNC(droneGetTurretTargetPos)) select 0;
[QGVAR(droneSetWaypoint), [_vehicle, _group, _pos, "FOLLOW", cursorTarget], _group] call CBA_fnc_targetEvent;
private _followDistance = _vehicle getVariable [QGVAR(wpFollowDistance), 0];
[[LLSTRING(DroneFollowHint), _followDistance], 3] call EFUNC(common,displayTextStructured);
};
_action = [QGVAR(droneSetWaypointFollow), localize "$STR_AC_FOLLOW", "\a3\3DEN\Data\CfgWaypoints\Follow_ca.paa", _statement, _condition] call EFUNC(interact_menu,createAction);
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);

// Set drone follow distance
_condition = {
params ["_vehicle"];
private _group = group driver _vehicle;
private _index = (currentWaypoint _group) min count waypoints _group;
private _waypoint = [_group, _index];
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]} && {(waypointType _waypoint) == "HOLD"}
};
_statement = {
params ["_vehicle", "", "_value"];
_vehicle setVariable [QGVAR(wpFollowDistance), _value];
[[LLSTRING(DroneFollowHint), _value], 3] call EFUNC(common,displayTextStructured);
};
_action = [QGVAR(droneSetFollowDistance), LLSTRING(DroneFollowDistance), "", {}, _condition] call EFUNC(interact_menu,createAction);
private _base = [_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);
private _followDistances = if (_vehicle isKindOf "Car_F") then {
[0, 25, 50, 100, 200]
} else {
[0, 100, 200, 300, 400, 500]
};
{
_action = [
QGVAR(droneSetFollowDistance_) + str _x,
str _x,
"",
_statement,
{true},
{},
_x
] call EFUNC(interact_menu,createAction);
[_vehicle, 1, _base, _action] call EFUNC(interact_menu,addActionToObject);
} forEach _followDistances;

if (_vehicle isKindOf "Air") then {
// loiter at location
// Loiter at location
_condition = {
params ["_vehicle"];
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
};
_statement = {
_statement = {
params ["_vehicle"];
private _group = group driver _vehicle;
private _pos = ([_vehicle, [0]] call FUNC(droneGetTurretTargetPos)) select 0;
Expand All @@ -55,7 +104,7 @@ if (_vehicle isKindOf "Air") then {
[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject);


// set height
// Set height
_condition = {
params ["_vehicle"];
(missionNamespace getVariable [QGVAR(droneWaypoints), true]) && {waypointsEnabledUAV _vehicle} && {(ACE_controlledUAV select 2) isEqualTo [0]}
Expand All @@ -74,7 +123,7 @@ if (_vehicle isKindOf "Air") then {
} forEach [20, 50, 200, 500, 2000];


// set loiter radius
// Set loiter radius
_condition = {
params ["_vehicle"];
private _group = group driver _vehicle;
Expand All @@ -97,7 +146,7 @@ if (_vehicle isKindOf "Air") then {
} forEach [500, 750, 1000, 1250, 1500];


// set loiter direction
// Set loiter direction
_condition = {
params ["_vehicle", "", "_args"];
private _group = group driver _vehicle;
Expand Down
32 changes: 29 additions & 3 deletions addons/aircraft/functions/fnc_droneSetWaypoint.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* 1: Group <GROUP>
* 2: Pos 2D <ARRAY>
* 3: Type <STRING>
* 4: Target to follow <OBJECT> (default: objNull)
*
* Return Value:
* None
Expand All @@ -18,7 +19,7 @@
* Public: No
*/

params ["_vehicle", "_group", "_pos", "_type"];
params ["_vehicle", "_group", "_pos", "_type", ["_target", objNull]];
TRACE_4("droneSetWaypoint",_vehicle,_group,_pos,_type);

private _index = (currentWaypoint _group) min count waypoints _group;
Expand All @@ -34,9 +35,34 @@ _pos set [
[0, _currentHeight] select (_currentHeight >= 50)
];

// [_group] call CBA_fnc_clearWaypoints;
_waypoint = _group addWaypoint [_pos, 0];
_waypoint setWaypointType _type;
// The Vanilla "FOLLOW"-type waypoint is not used directly, due to 2 main issues (as of v2.16):
// - It does not work at all for UGVs, which is a known issue https://feedback.bistudio.com/T126283;
// - No clear scripting way was found to mimic the UAV Terminal's "Follow Distance" functionality;
// Instead, the solution for both UAV and UGV following consists of a CBA PFH that moves a "HOLD"-type Waypoint every 3 seconds.
// Either on the target itself, or on the Drone's current position if the target is within the desired follow distance.
if (_type == "FOLLOW" && {["CAManBase", "LandVehicle", "Ship"] findIf {_target isKindOf _x} != -1}) then {
_waypoint setWaypointType "HOLD";
[{
params ["_args", "_handle"];
_args params ["_vehicle", "_group", "_waypoint", "_target"];

if ( // Abort PFH if a new waypoint is created via UAV Terminal or ACE Interaction
_waypoint select 1 != currentWaypoint _group ||
{!alive _vehicle} || {isNull _target}
) exitWith {
deleteWaypoint _waypoint;
[_handle] call CBA_fnc_removePerFrameHandler;
};

private _followDistance = _vehicle getVariable [QGVAR(wpFollowDistance), 0];
if ((_vehicle distance2D _target) < _followDistance) then {
_waypoint setWaypointPosition [getPosASL _vehicle, -1];
} else {
_waypoint setWaypointPosition [getPosASL _target, -1];
};
}, 3, [_vehicle, _group, _waypoint, _target]] call CBA_fnc_addPerFrameHandler;
};

TRACE_3("",_currentHeight,_currentLoiterRadius,_currentLoiterType);
if (_currentHeight > 1) then { _vehicle flyInHeight _currentHeight; };
Expand Down
10 changes: 10 additions & 0 deletions addons/aircraft/stringtable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,15 @@
<Russian>30мм СБ 5:1</Russian>
<Korean>30mm CM 5:1</Korean>
</Key>
<Key ID="STR_ACE_Aircraft_DroneFollowDistance">
<English>Follow Distance</English>
<Italian>Distanza di seguimento</Italian>
<German>Folge-Entfernung</German>
</Key>
<Key ID="STR_ACE_Aircraft_DroneFollowHint">
<English>Following unit within %1m</English>
<Italian>Seguendo unità entro %1m</Italian>
<German>Folgt Einheit bis zu %1m</German>
</Key>
</Package>
</Project>
2 changes: 1 addition & 1 deletion addons/logistics_uavbattery/functions/fnc_canRefuelUAV.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@

params ["_caller", "_target"];

("ACE_UAVBattery" in (_caller call EFUNC(common,uniqueItems))) && {(fuel _target) < 1} && {(speed _target) < 1} && {!(isEngineOn _target)} && {(_target distance _caller) <= 4}
(alive _target) && {"ACE_UAVBattery" in (_caller call EFUNC(common,uniqueItems))} && {(fuel _target) < 1} && {(speed _target) < 1} && {!(isEngineOn _target)} && {(_target distance _caller) <= 4}

0 comments on commit 9cddb16

Please sign in to comment.