## Recommended Posts

I am trying to get an armed blackfish to circle a position counterclockwise and get the gunners do dump rounds on anything near the position.

By default, an AI piloted armed blackfish is USELESS, as it attempts to line its nose up with enemies like a normal jet.

So I took up the challenge.  Shouldn't be too hard, right?  Just a counterclockwise loiter, put the driver in his own group and set him up to ignore combat so he flies smoothly in a circle, then set the gunners to engage everything they see.

Nope.  It isn't that simple.  I can't get the pilot to fly smoothly.  He goes counterclockwise in a circle around the position, but he rolls a lot which gives the gunners very little gun time.  I would be fine with that if the gunners could actually hit anything and actually fired their weapons.  Most of the time, the left gunner doesn't use the 20mm or 105mm at all, and the right gunner just fires a couple of 40mm rounds here and there.  To top it off, they wont engage infantry unless they have somehow miraculously spotted a vehicle in the area AND THEN disabled it, then they will start shooting at infantry.  And that's not all, apparently the 40mm gun doesn't do splash damage, so nothing ever gets killed unless its a direct hit with a 40mm round.  Since the AI don't compensate for the speed of the plane, that pretty much doesn't happen unless by accident.

Ok, so here is what I have so far.  I want a function that takes a Blackfish object, a position, and a duration as arguments.  The function should add a waypoint.  When that waypoint becomes active, the fish should fly to it, circle it counterclockwise, and fire all of it's guns at everything in the area in a way that is at least visually impressive.  It should remain in the area until the duration specified in the arguments has elapsed.  Then, it needs to resume normal operation.

```params [
["_fish", objNull, [objNull], 1],
["_pos", [0,0,0], [[]], 3],
["_dur", 60, [0], 1]
];

_alt = 400;

_grp = (group (driver _fish));
_wp = _grp addWaypoint [_pos, 0];
_wpi = _wp call JWL_fnc_indexWaypoint;
_wp setWaypointType "LOITER";
_wp setWaypointLoiterType "CIRCLE_L";
_wp setWaypointSpeed "FULL";

[_grp, _wpi, _pos, _fish, _dur, _alt] spawn {
params [
"_grp",
"_wpi",
"_pos",
"_fish",
"_dur",
"_alt"
];
_phase = 0;
_time = 0;
_plt = ["TARGET","AUTOTARGET","AUTOCOMBAT","FSM"];
_gnrs = ["AIMINGERROR"];
_rgpd = false;
/*
Start main loop.  Run every 3 seconds.
*/
while {true} do {
sleep 3;
/*
check to see if the Blackfish is alive.  If not, terminate the script.
*/
if (!(alive _fish)) then {
systemChat "BLACKFISH DESTROYED - TERMINATING";
terminate _thisScript;
};
/*
Start the main IF statement.
Check to see if the current waypoint is in fact the waypoint that was created
earlier in the script, if yes then proceed with the phase.
Otherwise, check to see if the waypoint exists.
If yes, reset the phase, else terminate the loop.
*/
if ((waypointName [_grp, (currentWaypoint _grp)]) == _wpi) then {
systemChat "WAYPOINT ACTIVE - EVALUATING...";
_fish flyInHeight _alt;
/*
Check distance of blackfish to the waypoint.
Only perform this check before in range.
Limit speed and regroup the crew once in range and start a new check.
*/
if (_phase == 0) then {
if (((position _fish) distance _pos) <= 1750) then {
systemChat "SPEED LIMITED - AI REGROUPED";
_grp2 = createGroup west;
{
if (_x != (driver _fish)) then {
_unit = _x;
[_x] joinSilent _grp2;
{
_unit disableAI _x
} forEach _gnrs;
};
} forEach (crew _fish);
{
(driver _fish) disableAI _x
} forEach _plt;
_grp2 setCombatMode "RED";
_grp2 setBehaviour "AWARE";
_grp setBehaviour "CARELESS";
_grp setSpeedMode "LIMITED";  //Barely helps
_fish limitSpeed 10;  //Doesn't seem to work during loiter
_rgpd = true;
_phase = 1;
};
};
/*
If previous range check passed and speed limited, start checking a shorter range.
Only perform this check until the fish is in range.
Once in range, flip a bool and start the "timer" check to limit the loiter time.
*/
if (_phase == 1) then {
if (((position _fish) distance _pos) <= 1250) then {
systemChat "BLACKFISH IN RANGE - TIMER STARTED";
_time = diag_tickTime + _dur;
_phase = 2;
};
};
/*
If previous range check passed and speed limited, start checking current time.
if time limit reached, reform the group and do some cleanup, and delete the WP.
*/
if (_phase == 2) then {
systemChat "BLACKFISH IN RANGE - ENGAGING";
//maybe do some targetting stuff
if (diag_tickTime >= _time) then {
systemChat "WAYPOINT TIMED OUT";
{
if (_x != (driver _fish)) then {
_unit = _x;
[_x] joinSilent _grp;
{
_unit enableAI _x
} forEach _gnrs;
};
} forEach (crew _fish);
{
(driver _fish) enableAI _x
} forEach _plt;
_grp setCombatMode "YELLOW";
_grp setBehaviour "AWARE";
_grp setSpeedMode "FULL";
_fish limitSpeed 600;
terminate _thisScript;
};
};
/*
ELSE statement for main IF statement.  If current waypoint is not the created
loiter waypoint, then check to see if that waypoint still exists.  If not,
end the script, if yes, then reset the phase to 0.
*/
} else {
_wpValid = false;
{
if (waypointName _x == _wpi) then {_wpValid = true};
}forEach (waypoints _grp);
if (_wpValid) then {
systemChat "WAYPOINT INACTIVE - WAITING";
_rgpd = false;
_phase = 0;
} else {
systemChat "WAYPOINT DELETED - TERMINATING";
if (_rgpd) then {
{
if (_x != (driver _fish)) then {
_unit = _x;
[_x] joinSilent _grp;
{
_unit enableAI _x
} forEach _gnrs;
};
} forEach (crew _fish);
{
(driver _fish) enableAI _x
} forEach _plt;
_grp setCombatMode "YELLOW";
_grp setBehaviour "AWARE";
_grp setSpeedMode "FULL";
_fish limitSpeed 600;
};
terminate _thisScript;
};
};
};
};
```

This function psuedo-works, but isn't giving me the desired effect.

Also, JWL_fnc_indexWaypoint is a short little function that takes a waypoint, assigns a number unique to that group to the waypoint, and sets the waypoint name as that number and returns the number as a string.

```comment "-------------------------------------------------------------------------------------------------------------
Helper function to index a waypoints for reference in custom waypoint functions..
The index is stored as the waypoint name.
Useful to check identity of self-deleting unique waypoints of the same type.

Arguments: waypoint
Return: index
---------------------------------------------------------------------------------------------------------------------";
_grp = (_this select 0);
_curVal = _grp getVariable "JWL_WPCount";
_name = 0;
if (isNil "_curVal") then [{
_grp setVariable ["JWL_WPCount",0,true];
_name = str 0;
},{
_grp setVariable ["JWL_WPCount",(_curVal + 1),true];
_name = str (_curVal + 1);
}];
_this setWaypointName _name;
_name

```

Anyone want to run these functions and see what I am talking about, and maybe give some input on what to do about it?  There are only so many commands to call on the AI, and most of them make it worse.  I am thinking I am going to have to create helipad objects and force the gunners to fire at it manually which will be some really heavy scripting.