Skip to content

Commit

Permalink
Merge pull request #333 from SilentSpike/master
Browse files Browse the repository at this point in the history
Update AI functions
  • Loading branch information
Killswitch00 committed May 21, 2016
2 parents 8e72061 + 3d7f518 commit 3d8ed8b
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 107 deletions.
6 changes: 6 additions & 0 deletions addons/ai/CfgFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ class CfgFunctions
description = "A function used to add a waypoint to a group. Parameters: - Group (Group or Object) - Position (XYZ, Object, Location or Group) Optional: - Radius (Scalar) - Waypoint Type (String) - Behaviour (String) - Combat Mode (String) - Speed Mode (String) - Formation (String) - Code To Execute at Each Waypoint (String) - TimeOut at each Waypoint (Array [Min, Med, Max]) - Waypoint Completion Radius (Scalar) Example: [this, this, 300, ""MOVE"", ""AWARE"", ""YELLOW"", ""FULL"", ""STAG COLUMN"", ""this spawn CBA_fnc_searchNearby"", [3,6,9]] Returns: Waypoint Author: Rommel";
file = "\x\cba\addons\ai\fnc_addWaypoint.sqf";
};
// CBA_fnc_clearWaypoints
class clearWaypoints
{
description = "A function used to correctly clear all waypoints from a group.";
file = "\x\cba\addons\ai\fnc_clearWaypoints.sqf";
};
// CBA_fnc_searchNearby
class searchNearby
{
Expand Down
34 changes: 34 additions & 0 deletions addons/ai/fnc_clearWaypoints.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_clearWaypoints
Description:
A function used to correctly clear all waypoints from a group.
Parameters:
- Group (Group or Object)
Example:
(begin example)
[group player] call CBA_fnc_clearWaypoints
(end)
Returns:
None
Author:
SilentSpike
---------------------------------------------------------------------------- */
#include "script_component.hpp"
params [["_group", grpNull, [grpNull,objNull]]];
_group = _group call CBA_fnc_getGroup;

private _waypoints = waypoints _group;
{
// Waypoint index changes with each deletion, so don't delete _x
deleteWaypoint [_group,0];
} forEach _waypoints;

// Create a self-deleting waypoint at the leader position to halt all planned movement (based on old waypoints)
private _wp = _group addWaypoint [getPosATL (leader _group), 0];
_wp setWaypointStatements ["true", "deleteWaypoint [group this,currentWaypoint (group this)]"];
85 changes: 48 additions & 37 deletions addons/ai/fnc_searchNearby.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,66 @@ Description:
A function for a group to search a nearby building.
Parameters:
Group (Group or Object)
- Group (Group or Object)
Example:
(begin example)
[group player] spawn CBA_fnc_searchNearby
[group player] call CBA_fnc_searchNearby
(end)
Returns:
Nil
Author:
Rommel
Rommel, SilentSpike
---------------------------------------------------------------------------- */

params ["_group"];
_group = _group call CBA_fnc_getgroup;
_group lockwp true;
private ["_leader","_behaviour"];
_leader = leader _group;
_behaviour = behaviour _leader;
_group setbehaviour "combat";

(_leader call CBA_fnc_getnearestbuilding) params ["_building", "_indices"];
_group setformdir ([_leader, _building] call bis_fnc_dirto);

if (_leader distance _building > 500) exitwith {_group lockwp false};

private ["_count","_units"];
_units = units _group;
_count = (count _units) - 1;

while {_indices > 0 && {_count > 0}} do {
sleep 10;
while {_indices > 0 && {_count > 0}} do {
private "_unit";
_unit = _units select _count;
if (unitready _unit) then {
_unit commandmove (_building buildingpos _indices);
_indices = _indices - 1;
};
_count = _count - 1;
_group = _group call CBA_fnc_getGroup;

private _building = nearestBuilding (leader _group);
if ((leader _group) distanceSqr _building > 250e3) exitwith {};

[_group,_building] spawn {
params ["_group","_building"];
private _leader = leader _group;

// Add a waypoint to regroup after the search
_group lockWP true;
private _wp = _group addWaypoint [getPos _leader, 0, currentWaypoint _group];
private _cond = "({unitReady _x || !(alive _x)} count thisList) == count thisList";
private _comp = format ["this setFormation %1; this setBehaviour %2; deleteWaypoint [group this, currentWaypoint (group this)];",formation _group,behaviour _leader];
_wp setWaypointStatements [_cond,_comp];

// Prepare group to search
_group setBehaviour "Combat";
_group setFormDir ([_leader, _building] call BIS_fnc_dirTo);

// Leader will only wait outside if group larger than 2
if (count (units _group) <= 2) then {
_leader = objNull;
};
_units = units _group;
_count = (count _units) - 1;

// Search while there are still available positions
private _positions = _building buildingPos -1;
while {!(_positions isEqualTo [])} do {
// Update units in case of death
private _units = (units _group) - [_leader];

// Abort search if the group has no units left
if (_units isEqualTo []) exitWith {};

// Send all available units to the next available position
{
if (_positions isEqualTo []) exitWith {};
if (unitReady _x) then {
private _pos = _positions deleteAt 0;
_x commandMove _pos;
sleep 2;
};
} forEach _units;
};

_group lockWP false;
};
waituntil {sleep 3; {unitready _x} count _units >= count (units _group) - 1};
{
_x dofollow _leader;
} foreach _units;
_group setbehaviour _behaviour;
_group lockwp false;
122 changes: 71 additions & 51 deletions addons/ai/fnc_taskDefend.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -25,78 +25,98 @@ Returns:
Nil
Author:
Rommel
Rommel, SilentSpike
---------------------------------------------------------------------------- */

params ["_group", ["_position",[]], ["_radius",50], ["_threshold",2]];
params ["_group", ["_position",[]], ["_radius",50,[0]], ["_threshold",2,[0]], ["_patrol",true,[true]]];

_group = _group call CBA_fnc_getGroup;
if !(local _group) exitWith {}; // Don't create waypoints on each machine

_position = [_position,_group] select (_position isEqualTo []);
_position = _position call CBA_fnc_getPos;

_group enableattack false;
[_group] call CBA_fnc_clearWaypoints;
_group enableAttack false;

private ["_count", "_list", "_list2", "_units", "_i"];
_statics = [_position, vehicles, _radius, {(_x iskindof "StaticWeapon") && {(_x emptypositions "Gunner" > 0)}}] call CBA_fnc_getnearest;
_buildings = _position nearObjects ["building",_radius];
_units = units _group;
_count = count _units;
private _statics = _position nearObjects ["StaticWeapon", _radius];
private _buildings = _position nearObjects ["Building", _radius];

// Filter out occupied statics
[_statics,{(_x emptyPositions "Gunner") > 0},true] call CBA_fnc_filter;

// Filter out buildings below the size threshold (and store positions for later use)
{
if (str(_x buildingpos _threshold) == "[0,0,0]") then {_buildings = _buildings - [_x]};
} foreach _buildings;
_i = 0;
if ((_x buildingPos _threshold) isEqualto [0,0,0]) then {
_buildings set [_forEachIndex,nil];
} else {
private _positions = _x buildingPos -1;

if (isNil {_x getVariable "CBA_taskDefend_positions"}) then {
_x setVariable ["CBA_taskDefend_positions",_positions];
};
};
} forEach _buildings;
_buildings = _buildings arrayIntersect _buildings;

// v1.56 version of the above
/*_buildings = _buildings select {
private _positions = _x buildingPos -1;
if (isNil {_x getVariable "CBA_taskDefend_positions"}) then {
_x setVariable ["CBA_taskDefend_positions",_positions];
};
count (_positions) > _threshold
};*/

private _units = units _group;
private _assigned = 0;
{
_count = (count _statics) - 1;
if (random 1 < 0.31 && {_count > -1}) then {
_x assignasgunner (_statics select _count);
_statics resize _count;
[_x] ordergetin true;
_i = _i + 1;
// 31% chance to occupy nearest free static weapon
if ((random 1 < 0.31) && { !(_statics isEqualto []) }) then {
_x assignAsGunner (_statics deleteAt 0);
[_x] orderGetIn true;

_assigned = _assigned + 1;
} else {
if (random 1 < 0.93 && {count _buildings > 0}) then {
private ["_building","_p","_array"];
_building = _buildings call BIS_fnc_selectRandom;
_array = _building getvariable "CBA_taskDefend_positions";
if (isnil "_array") then {
private "_k"; _k = 0;
_building setvariable ["CBA_taskDefend_positions",[]];
while {str(_building buildingpos _k) != "[0,0,0]"} do {
_building setvariable ["CBA_taskDefend_positions",(_building getvariable "CBA_taskDefend_positions") + [_k]];
_k = _k + 1;
};
_array = _building getvariable "CBA_taskDefend_positions";
};
if (count _array > 0) then {
_p = (_building getvariable "CBA_taskDefend_positions") call BIS_fnc_selectRandom;
_array = _array - [_p];
if (count _array == 0) then {
// 93% chance to occupy a random nearby building position
if ((random 1 < 0.93) && { !(_buildings isEqualto []) }) then {
private _building = _buildings call BIS_fnc_selectRandom;
private _array = _building getVariable ["CBA_taskDefend_positions",[]];

if !(_array isEqualTo []) then {
private _pos = _array deleteAt (floor(random(count _array)));

// If building positions are all taken remove from possible buildings
if (_array isEqualTo []) then {
_buildings = _buildings - [_building];
_building setvariable ["CBA_taskDefend_positions",nil];
_building setVariable ["CBA_taskDefend_positions",nil];
};
_building setvariable ["CBA_taskDefend_positions",_array];
[_x,_building buildingpos _p] spawn {
if (surfaceIsWater (_this select 1)) exitwith {};
(_this select 0) domove (_this select 1);
_building setVariable ["CBA_taskDefend_positions",_array];

// AI manipulation trickey to keep them in position until commanded to move
[_x, _pos] spawn {
params ["_unit","_pos"];
if (surfaceIsWater _pos) exitwith {};

_unit doMove _pos;
sleep 5;
waituntil {unitready (_this select 0)};
(_this select 0) disableai "move";
dostop _this;
waituntil {not (unitready (_this select 0))};
(_this select 0) enableai "move";
waituntil {unitReady _unit};
_unit disableAI "move";
doStop _unit;
waituntil {!(unitReady _unit)};
_unit enableAI "move";
};
_i = _i + 1;

_assigned = _assigned + 1;
};
};
};
} foreach _units;
{
_x setvariable ["CBA_taskDefend_positions",nil];
} foreach _buildings;
if (count _this > 4 && {!(_this select 4)}) then {_i = _count};
if (_i < _count * 0.5) then {
} forEach _units;

// If half of the group's units aren't assigned then patrol
if (_patrol && {_assigned < (count _units) * 0.5}) then {
[_group, _position, _radius, 5, "sad", "safe", "red", "limited"] call CBA_fnc_taskpatrol;
};
22 changes: 15 additions & 7 deletions addons/ai/fnc_taskPatrol.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Optional:
Example:
(begin example)
[this, getmarkerpos "objective1"] call CBA_fnc_taskPatrol
[this, this, 300, 7, "MOVE", "AWARE", "YELLOW", "FULL", "STAG COLUMN", "this spawn CBA_fnc_searchNearby", [3,6,9]] call CBA_fnc_taskPatrol;
[this, this, 300, 7, "MOVE", "AWARE", "YELLOW", "FULL", "STAG COLUMN", "this call CBA_fnc_searchNearby", [3,6,9]] call CBA_fnc_taskPatrol;
(end)
Returns:
Expand All @@ -43,15 +43,23 @@ if !(local _group) exitWith {}; // Don't create waypoints on each machine
_position = [_position,_group] select (_position isEqualTo []);
_position = _position call CBA_fnc_getPos;

_this =+ _this;
// Clear existing waypoints first
[_group] call CBA_fnc_clearWaypoints;

private _this =+ _this;
if (count _this > 3) then {
_this deleteAt 3;
};
for "_x" from 1 to _count do {

// Store first WP to close loop later
private _wp = _this call CBA_fnc_addWaypoint;

for "_x" from 1 to (_count - 1) do {
_this call CBA_fnc_addWaypoint;
};
_this2 =+ _this;
_this2 set [3, "CYCLE"];
_this2 call CBA_fnc_addWaypoint;

deleteWaypoint ((waypoints _group) select 0);
// Close the patrol loop
_this set [1, getWPPos _wp];
_this set [2, 0];
_this set [3, "CYCLE"];
_this call CBA_fnc_addWaypoint;
Loading

0 comments on commit 3d8ed8b

Please sign in to comment.