Merge branch 'A3EAI-Test'

This commit is contained in:
Zepheris 2020-02-18 11:19:41 -07:00
commit ecce8c725d
259 changed files with 11944 additions and 0 deletions

View File

@ -0,0 +1 @@
A3EAI

View File

@ -0,0 +1 @@
A3EAI

View File

@ -0,0 +1,19 @@
// Return the closest position from array to the positionA.
// In: [positionA,[array of positions]]
// Out: positionB
private ["_pA","_ps","_p1","_p2"];
_pA = _this select 0;
_ps = _this select 1;
_p1 = _ps select 0;
if (count _ps > 1) then {
for "_i" from 1 to (count _ps - 1) do {
_p2 = _ps select _i;
if ((_p2 distance _pA) < (_p1 distance _pA)) then {
_p1 = _p2;
};
};
};
_p1

View File

@ -0,0 +1,59 @@
// In: marker
// Out: array of positions
private ["_area","_corners"];
_area = _this;
_corners = [];
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _area) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _area;
_sizeX = _size select 0;
_sizeY = _size select 1;
private ["_cosX","_sinX","_cosY","_sinY","_addX","_addY","_subX","_subY"];
_cosX = _dirCos * _sizeX;
_sinX = _dirSin * _sizeX;
_cosY = _dirCos * _sizeY;
_sinY = _dirSin * _sizeY;
_addX = _cosX + _sinY;
_addY = _sinX + _cosY;
_subX = _cosX - _sinY;
_subY = _sinX - _cosY;
private ["_posX","_posY"];
// Bottom Left
_posX = _centerX - _subX;
_posY = _centerY - _addY;
_corners set [0,[_posX,_posY]];
// Top Left
_posX = _centerX - _addX;
_posY = _centerY - _subY;
_corners set [1,[_posX,_posY]];
// Top Right
_posX = _centerX + _subX;
_posY = _centerY + _addY;
_corners set [2,[_posX,_posY]];
// Bottom Right
_posX = _centerX + _addX;
_posY = _centerY + _subY;
_corners set [3,[_posX,_posY]];
_corners

View File

@ -0,0 +1,30 @@
// In: marker
// Out: string (marker shape)
private ["_size","_x","_y","_ret"];
_size = markersize _this;
_x = _size select 0;
_y = _size select 1;
_ret = "";
switch (tolower(markershape _this)) do {
case "rectangle": {
if (_x == _y) then {
_ret = "SQUARE";
} else {
_ret = "RECTANGLE";
};
};
case "ellipse": {
if (_x == _y) then {
_ret = "CIRCLE";
} else {
_ret = "ELLIPSE";
};
};
case "icon": {
_ret = "ICON";
};
};
_ret

View File

@ -0,0 +1,13 @@
// In: [position,distance,direction]
// Out: position
private ["_pos","_dst","_dir","_orgX","_orgY","_posX","_posY"];
_pos = _this select 0;
_dst = _this select 1;
_dir = _this select 2;
_orgX = _pos select 0;
_orgY = _pos select 1;
_posX = _orgX + (_dst * sin _dir);
_posY = _orgY + (_dst * cos _dir);
[_posX,_posY,0]

View File

@ -0,0 +1,26 @@
// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size"];
_size = getMarkerSize _this;
_size = _size select 0;
// Randomly pick a direction,
private ["_dir","_posX","_posY","_rand","_pos"];
_dir = random 360;
_rand = sqrt random 1;
_posX = (_size * (cos _dir)) * _rand;
_posY = (_size * (sin _dir)) * _rand;
_pos = [_posX,_posY];
_posX = _centerX + (_pos select 0);
_posY = _centerY + (_pos select 1);
[_posX,_posY,0]

View File

@ -0,0 +1,43 @@
// In: ellipseMarker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Direction and make sure it's between 0 and 360.
private ["_dirMrk"];
_dirMrk = (markerDir _this) * -1;
_dirMrk = _dirMrk % 360;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _this;
_sizeX = _size select 0;
_sizeY = _size select 1;
// If B axis is longer than A, switch them and fix direction.
if (_sizeX < _sizeY) then {
_sizeX = _size select 1;
_sizeY = _size select 0;
_dirMrk = _dirMrk + 90;
};
// Randomly pick a direction,
private ["_dir","_posX","_posY","_rand","_pos"];
_dir = random 360;
_rand = sqrt random 1;
_posX = (_sizeX * (cos _dir)) * _rand;
_posY = (_sizeY * (sin _dir)) * _rand;
_pos = [_posX,_posY];
if (_dirMrk != 0) then {
_pos = [_pos,_dirMrk] call A3EAI_SHK_pos_fnc_rotatePosition;
};
_posX = _centerX + (_pos select 0);
_posY = _centerY + (_pos select 1);
[_posX,_posY,0]

View File

@ -0,0 +1,37 @@
// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _this;
_sizeX = _size select 0;
_sizeY = _size select 1;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _this) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
private ["_rndX","_rndY","_posX","_posY"];
// Select random X and Y
_rndX = (random (_sizeX * 2)) - _sizeX;
_rndY = (random (_sizeY * 2)) - _sizeY;
// If area is angled, shift X and Y
if (_dir != 0) then {
_posX = _centerX + (_dirCos * _rndX - _dirSin * _rndY);
_posY = _centerY + (_dirSin * _rndX + _dirCos * _rndY);
} else {
_posX = _centerX + _rndX;
_posY = _centerY + _rndY;
};
[_posX,_posY,0]

View File

@ -0,0 +1,36 @@
// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size"];
_size = getMarkerSize _this;
_size = _size select 0;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _this) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
private ["_rndX","_rndY","_posX","_posY"];
// Select random X and Y
_rndX = (random (_size * 2)) - _size;
_rndY = (random (_size * 2)) - _size;
// If area is angled, shift X and Y
if (_dir != 0) then {
_posX = _centerX + (_dirCos * _rndX - _dirSin * _rndY);
_posY = _centerY + (_dirSin * _rndX + _dirCos * _rndY);
} else {
_posX = _centerX + _rndX;
_posY = _centerY + _rndY;
};
[_posX,_posY,0]

View File

@ -0,0 +1,85 @@
// In: [position,blackListMarker]
// Out: boolean
private ["_pos","_area","_return"];
_pos = _this select 0;
_area = _this select 1;
_return = false;
// Find corner positions of the rectangle
private ["_dir"];
_dir = markerDir _area;
_dir = _dir % 360;
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
private ["_shape"];
_shape = _area call A3EAI_SHK_pos_fnc_getMarkerShape;
if (_shape == "ICON") then {
// Icon has only one position, so if it equals to the given position, then it's blacklisted.
if ([_pos,_center] call A3EAI_SHK_pos_fnc_isSamePosition) then {
_return = true;
};
// Markers that have an area.
} else {
if (_shape in ["RECTANGLE","SQUARE"]) then {
private ["_corners"];
_corners = _area call A3EAI_SHK_pos_fnc_getMarkerCorners;
// If rectangle is not axis-aligned.
if (_dir % 90 != 0) then {
// Add the point position to the array to have it shifted by the FOR below
_corners set [4,_pos];
// Rotate each corner position so that the rectangle is aligned with x and y axises
// Use origo as center while rotating, but for comparison shift positions back
private ["_posCor","_posNew","_orgX","_orgY","_shiftedX","_shiftedY","_newX","_newY"];
for "_i" from 0 to (count _corners - 1) do {
_posCor = _corners select _i;
// Original coordinates
_orgX = _posCor select 0;
_orgY = _posCor select 1;
// Subtract the marker center coordinates from corner coordinates.
// Rotation is done using origo (0,0) as anchor/centerpoint.
_shiftedX = _orgX - _centerX;
_shiftedY = _orgY - _centerY;
// Axis-aligned corner position
_posNew = [[_shiftedX,_shiftedY],_dir] call A3EAI_SHK_pos_fnc_rotatePosition;
// Shift the aligned corner position back near to the original marker location.
_newX = _posNew select 0;
_newY = _posNew select 1;
_newX = _newX + _centerX;
_newY = _newY + _centerY;
_posCor = [_newX,_newY];
_corners set [_i,_posCor];
};
// Point position
_pos = _corners select 4;
};
// Check if the position is within the marker area.
_return = [_pos,_corners] call A3EAI_SHK_pos_fnc_isInRectangle;
} else {
if (_shape == "CIRCLE") then {
_return = [_pos,_area] call A3EAI_SHK_pos_fnc_isInCircle;
} else {
_return = [_pos,_area] call A3EAI_SHK_pos_fnc_isInEllipse;
};
};
};
_return

View File

@ -0,0 +1,36 @@
// In: [position,marker]
// Out: boolean
private ["_pos","_area","_posX","_posY"];
_pos = _this select 0;
_area = _this select 1;
_posX = _pos select 0;
_posY = _pos select 1;
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size"];
_size = getMarkerSize _area;
_size = _size select 0;
// Difference in coordinates
private ["_difX","_difY"];
_difX = _posX - _centerX;
_difY = _posY - _centerY;
private ["_return"];
_return = false;
// If distance from center of marker to the given position is
// smaller than the radius of the circle, then position is inside.
if (sqrt((_difX * _difX) + (_difY * _difY)) < _size) then {
_return = true;
};
_return

View File

@ -0,0 +1,54 @@
// In: [position,ellipseMarker]
// Out: boolean
private ["_pos","_area","_return"];
_pos = _this select 0;
_area = _this select 1;
_return = false;
// Ellipse size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _area;
_sizeX = _size select 0;
_sizeY = _size select 1;
// Direction and make sure it's between 0 and 360.
private ["_dir"];
_dir = markerDir _area;
_dir = _dir % 360;
// Ellipse center position
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
// If marker is not axis-aligned, rotate the dot position.
if (_dir % 90 != 0) then {
private ["_orgX","_orgY","_shiftedX","_shiftedY"];
_orgX = _pos select 0;
_orgY = _pos select 1;
_shiftedX = _orgX - _centerX;
_shiftedY = _orgY - _centerY;
_pos = [[_shiftedX,_shiftedY],_dir] call A3EAI_SHK_pos_fnc_rotatePosition;
_pos set [0,(_pos select 0) + _centerX];
_pos set [1,(_pos select 1) + _centerY];
};
// Dot position
private ["_posX","_posY"];
_posX = _pos select 0;
_posY = _pos select 1;
// Distance between dot and ellipse center
private ["_dstX","_dstY"];
_dstX = abs(_posX - _centerX);
_dstY = abs(_posY - _centerY);
private ["_sum"];
_sum = ((_dstX * _dstX)/(_sizeX * _sizeX)) + ((_dstY * _dstY)/(_sizeY * _sizeY));
if (_sum <= 1) then {
_return = true;
};
_return

View File

@ -0,0 +1,26 @@
// In: [pointPosition,corners]
// Out: boolean
private ["_pos","_corners","_return"];
_pos = _this select 0;
_corners = _this select 1;
_return = false;
private ["_dotX","_dotY","_bottomLeft","_left","_bottom","_topRight","_right","_top"];
_dotX = _pos select 0;
_dotY = _pos select 1;
_bottomLeft = _corners select 0;
_left = _bottomLeft select 0;
_bottom = _bottomLeft select 1;
_topRight = _corners select 2;
_right = _topRight select 0;
_top = _topRight select 1;
// x is between left and right
// y is between bottom and top
if (_dotX >= _left && _dotX < _right && _dotY >= _bottom && _dotY < _top) then {
_return = true;
};
_return

View File

@ -0,0 +1,16 @@
// In: [array1,array2]
// Out: boolean
private ["_p1","_p2","_return"];
_p1 = _this select 0;
_p2 = _this select 1;
_return = true;
// Only compare X and Y coordinates, ignore Z.
for "_i" from 0 to 1 do {
if ((_p1 select _i) != (_p2 select _i)) exitwith {
_return = false;
};
};
_return

View File

@ -0,0 +1,13 @@
// In: [position,direction]
// Out: position
private ["_pos","_dir","_orgX","_orgY","_newX","_newY"];
_pos = _this select 0;
_dir = _this select 1;
_orgX = _pos select 0;
_orgY = _pos select 1;
_newX = (_orgX * (cos _dir)) - (_orgY * (sin _dir));
_newY = (_orgX * (sin _dir)) + (_orgY * (cos _dir));
[_newX,_newY]

View File

@ -0,0 +1,170 @@
/* Select a random position based on anchor position, direction and distance.
In: [position,distance,direction,water,road,emptySpace]
Out: position
*/
private ["_org","_dst","_dir","_pos","_water","_road","_empty"];
_org = _this select 0;
_dst = _this select 1;
_dir = if (count _this > 2) then {_this select 2} else {random 360};
_water = if (count _this > 3) then {_this select 3} else {0};
_road = if (count _this > 4) then {_this select 4} else {[0,200]};
_empty = if (count _this > 5) then {_this select 5} else {[]};
// Object instead of position array given
if (typename _org == "OBJECT") then {_org = getpos _org};
// Distance given as an array of min and max. Pick a random between them.
if (typename _dst == "ARRAY") then {
private ["_min","_max"];
_min = _dst select 0;
_max = _dst select 1;
_dst = (_min + random(_max - _min));
};
// Direction given as an array of min and max. Pick a random dir between them.
if (typename _dir == "ARRAY") then {
private ["_min","_max","_ang"];
_min = _dir select 0;
_max = _dir select 1;
_ang = _max - _min;
// Min bigger than max, can happen with directions around north
if (_ang < 0) then { _ang = _ang + 360 };
_dir = (_min + random _ang);
};
_pos = [_org,_dst,_dir] call A3EAI_SHK_pos_fnc_getPos;
// Water position
if (typeName _water == "SCALAR") then {
switch _water do {
case 0: { // Water not allowed
if (surfaceIsWater _pos) then {
private ["_p","_d","_l"];
_d = 0; _l = true;
// Search for a land position starting from the randomly picked position and
// then going outwards from it in full circles in 20m steps.
while {_d = _d + 20; _l && _d < 5000} do {
for "_i" from 0 to 340 step 20 do {
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
if (!surfaceIsWater _p) exitwith {_l = false};
};
};
_pos = _p;
};
};
case 1: { // Water allowed
};
case 2: { // Only water allowed
if !(surfaceIsWater _pos) then {
private ["_p","_d","_l"];
_d = 0; _l = true;
// Search for a water position starting from the randomly picked position and
// then going outwards from it in full circles in 20m steps.
while {_d = _d + 20; _l && _d < 5000} do {
for "_i" from 0 to 340 step 20 do {
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
if (surfaceIsWater _p) exitwith {_l = false};
};
};
_pos = _p;
};
};
};
} else { // For backward compatibility
// Water position is not allowed
if !_water then {
if (surfaceIsWater _pos) then {
private ["_p","_d","_l"];
_d = 0; _l = true;
// Search for a land position starting from the randomly picked position and
// then going outwards from it in full circles in 20m steps.
while {_d = _d + 20; _l && _d < 5000} do {
for "_i" from 0 to 340 step 20 do {
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
if (!surfaceIsWater _p) exitwith {_l = false};
};
};
_pos = _p;
};
};
};
// Road position.
if (count _road > 0) then {
if ((_road select 0) > 0) then {
private ["_mode","_range","_roads","_cnt","_p","_p2"];
_mode = _road select 0;
_range = _road select 1;
_roads = _pos nearroads _range;
_cnt = count _roads;
_p = [];
// Road position(s) found.
if (_cnt > 0) then {
_p = getpos (_roads select 0);
// Found more than one road position, return closest.
if (_cnt > 1) then {
for "_i" from 1 to (_cnt - 1) do {
_p2 = getpos (_roads select _i);
if ((_p2 distance _pos) < (_p distance _pos)) then {
_p = _p2;
};
};
};
};
switch _mode do {
// Road position preferred but not forced.
case 1: {
if (count _p > 0) then {
_pos = _p;
};
};
// Only accept road position, return empty array if none found.
case 2: {
if (count _p > 0) then {
_pos = _p;
} else {
_pos resize 0;
};
};
};
};
};
// Find empty position
private ["_dst","_veh","_p"];
_dst = 200;
_veh = "";
switch (typename _empty) do {
case "OBJECT": { _veh = typeof _empty }; // Only vehicle given, use default distance
case "SCALAR": {_dst = _empty;};
case "ARRAY": {
if (count _empty > 0) then {
_dst = _empty select 0;
_veh = _empty select 1;
if (typename _veh == typename objNull) then { _veh = typeof _veh };
};
};
};
_p = [];
if (count _pos > 0) then {_p = _pos findEmptyPosition [0,_dst,_veh];};
// If an empty position is found, use it. Otherwise, return the original position.
if (count _p > 0) then {
_pos = _p;
};
// Return position
_pos

View File

@ -0,0 +1,101 @@
/* Select a random position from an area defined by a marker.
In: [marker,water,blacklist,emptySpace]
Out: position
*/
private ["_area","_water","_blist","_pos","_empty"];
_area = _this select 0;
_water = if (count _this > 1) then {_this select 1} else {0};
_blist = if (count _this > 2) then {_this select 2} else {[]};
_empty = if (count _this > 3) then {_this select 3} else {[]};
_pos = [];
if (typename _blist == "STRING") then {_blist = [_blist]};
private ["_shape"];
_shape = _area call A3EAI_SHK_pos_fnc_getMarkerShape;
// Limited loop so the script won't get stuck
private ["_i","_exit"];
_exit = false;
for [{_i = 0}, {_i < 1000 && !_exit}, {_i = _i + 1}] do {
// Rectangle or Ellipse marker given?
if (_shape in ["SQUARE","RECTANGLE"]) then {
_pos = _area call A3EAI_SHK_pos_fnc_getPosFromRectangle;
} else {
_pos = _area call A3EAI_SHK_pos_fnc_getPosFromEllipse;
};
// Find empty position
private ["_dst","_veh","_p"];
_dst = 200;
_veh = "";
switch (typename _empty) do {
case (typename objNull): { _veh = typeof _empty }; // Only vehicle given, use default distance
case ("STRING"): { _veh = _empty };
case (typename []): {
if (count _empty > 0) then {
_dst = _empty select 0;
_veh = _empty select 1;
if (typename _veh == typename objNull) then { _veh = typeof _veh };
};
};
};
_p = _pos findEmptyPosition [0,_dst,_veh];
// If an empty position is found, use it. Otherwise, return the original position.
if (count _p > 0) then {
_pos = _p;
};
// Water position
if (typeName _water == "SCALAR") then {
switch _water do {
case 0: { // Water position is not allowed
// Position is on land, try to exit script.
if !(surfaceIsWater _pos) then {
_exit = true;
};
};
case 1: { // Doesn't matter if position is on water or land.
_exit = true;
};
case 2: { // Only water position is allowed
// Position is on water, try to exit script.
if (surfaceIsWater _pos) then {
_exit = true;
};
};
};
} else { // For backward compatibility
// Water position is not allowed
if !_water then {
// Position is on land, try to exit script.
if !(surfaceIsWater _pos) then {
_exit = true;
};
// Doesn't matter if position is on water or land.
} else {
_exit = true;
};
};
// Position is not allowed in blacklisted areas
if (count _blist > 0 && _exit) then {
// Check each blacklist marker
{
// If blacklisted, jump out of blacklist check and continue main loop.
if ([_pos,_x] call A3EAI_SHK_pos_fnc_isBlacklisted) exitwith {
_exit = false;
};
} foreach _blist;
};
};
// Return position
_pos

View File

@ -0,0 +1,105 @@
/*
SHK_pos
Version 0.24
Author: Shuko (shuko@quakenet, miika@miikajarvinen.fi)
Contributors: Cool=Azroul13, Hatifnat
Forum: http://forums.bistudio.com/showthread.php?162695-SHK_pos
Marker Based Selection
Required Parameters:
0 String Area marker's name.
Optional Parameters:
1 Number Water position. Default is only land positions allowed.
0 Find closest land. Search outwards 360 degrees (20 degree steps) and 20m steps.
1 Allow water positions.
2 Find only water positions.
2 Array or String One or multiple blacklist area markers which are excluded from the main marker area.
3 Array, Number, Object or Vehicle Type Force finding large enough empty position.
0 Max range from the selection position to look for empty space. Default is 200.
1 Vehicle or vehicle type to fit into an empty space.
Examples:
[...,[300,heli]] Array with distance and vehicle object.
[...,350] Only distance given
[...,(typeof heli)] Only vehicle type given
[...,heli] Only vehicle object given
Position Based Selection
Required Parameters:
0 Object or Position Anchor point from where the relative position is calculated from.
1 Array or Number Distance from anchor.
Optional Parameters:
2 Array of Number Direction from anchor. Default is random between 0 and 360.
3 Number Water position. Default is only land positions allowed.
0 Find closest land. Search outwards 360 degrees (20 degree steps) and 20m steps.
1 Allow water positions.
2 Find only water positions.
4 Array Road positions.
0 Number Road position forcing. Default is 0.
0 Do not search for road positions.
1 Find closest road position. Return the generated random position if none found.
2 Find closest road position. Return empty array if none found.
1 Number Road search range. Default is 200m.
5 Array, Number, Object or Vehicle Type Force finding large enough empty position.
0 Max range from the selection position to look for empty space. Default is 200.
1 Vehicle or vehicle type to fit into an empty space.
Examples:
[...,[300,heli]] Array with distance and vehicle object.
[...,350] Only distance given
[...,(typeof heli)] Only vehicle type given
[...,heli] Only vehicle object given
Usage:
Preprocess the file in init.sqf:
call compile preprocessfile "SHK_pos\A3EAI_SHK_pos_init.sqf";
Actually getting the position:
pos = [parameters] call A3EAI_SHK_pos;
*/
// Functions
A3EAI_SHK_pos_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_getpos.sqf",A3EAI_directory];
A3EAI_SHK_pos_getPosMarker = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_getposmarker.sqf",A3EAI_directory];
// Sub functions
A3EAI_SHK_pos_fnc_findClosestPosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_findclosestposition.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getMarkerCorners = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getmarkercorners.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getMarkerShape = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getmarkershape.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getpos.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getPosFromCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromcircle.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getPosFromEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromellipse.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getPosFromRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromrectangle.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_getPosFromSquare = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromsquare.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_isBlacklisted = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isblacklisted.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_isInCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isincircle.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_isInEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isinellipse.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_isInRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isinrectangle.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_isSamePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_issameposition.sqf",A3EAI_directory];
A3EAI_SHK_pos_fnc_rotatePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_rotateposition.sqf",A3EAI_directory];
// Wrapper function
// Decide which function to call based on parameters.
A3EAI_SHK_pos = {
private ["_pos"];
_pos = [];
// Only marker is given as parameter
if (typename _this isEqualTo "STRING") then {
_pos = [_this] call A3EAI_SHK_pos_getPosMarker;
// Parameter array
} else {
if (typename (_this select 0) isEqualTo "STRING") then {
_pos = _this call A3EAI_SHK_pos_getPosMarker;
} else {
_pos = _this call A3EAI_SHK_pos_getPos;
};
};
// Return position
_pos
};

View File

@ -0,0 +1,233 @@
#include "\A3EAI\globaldefines.hpp"
/*
=======================================================================================================================
Script: BIN_taskPatrol.sqf v1.3
Author(s): Binesi
Partly based on original code by BIS
Description:
Creates a continually randomized patrol path which circles and intersects a given position.
Parameter(s):
_this select 0: the group to which to assign the waypoints (Group)
_this select 1: the position on which to base the patrol (Array)
_this select 2: the maximum distance between waypoints (Number)
_this select 3: (optional) debug markers on or off (Number)
_this select 4: (optional) blacklist of areas (Array)
Returns:
Boolean - success flag
Example(s):
null = [group this,(getPos this),250] execVM "BIN_taskPatrol.sqf"
null = [group this,(getPos this),250,1] execVM "BIN_taskPatrol.sqf" // Same with debug markers
-----------------------------------------------------------------------------------------------------------------------
Notes: Wolffy.au
If anyone is interested, I've made some additions to Binesi's BIN_taskPatrol script.
Random initial patrol direction - I noticed every patrol started off in the same direction, so I've randomised it.
Fixed the 2D position / findSafePos errors
Added building positions as possible patrol locations using Random Building Position Script v1.0 by Tophe of Östgöta Ops
Added check that BIS Functions has been initialized
ArmaIIholic
-- added JTD direction normalization function
-- changed numbers for waypoints to match previous waypoints
-- randomized initial direction - Wolffy.au added only the offset
-- fixed error with building position format
-- randomized initial direction -- Wolffy.au added only the offset which had to be reduced to 180
- however this script is making full circle from wherever it starts
Edited version for A3EAI (https://github.com/dayzai/A3EAI)
=======================================================================================================================
*/
_unitGroup = _this select 0;
_pos = _this select 1;
_max_dist = _this select 2;
_unitType = _unitGroup getVariable ["unitType",""];
_allowWater = (_unitType in ["aircustom","air_reinforce"]);
_searchLoot = _unitType in ["static","vehiclecrew","dynamic","random"];
_isVehicle = (_unitType isEqualTo "landcustom");
_combatMode = (combatMode _unitGroup);
_behavior = (behaviour (leader _unitGroup));
if (_max_dist < 75) then {_unitGroup setSpeedMode "LIMITED"};
_randomizeChance = linearConversion [125,350,_max_dist,0.25,0.45,true];
//diag_log format ["DEBUG: PatrolDist %1 has RandomizeChance %2",_max_dist,_randomizeChance];
_wpStatements = call {
if (_searchLoot && {_max_dist > 100}) exitWith {format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint;} else {_nul = [group this] spawn A3EAI_areaSearching;};",_randomizeChance]};
if (_unitType isEqualTo "aircustom") exitWith {format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint;} else {_nul = [(assignedVehicle this),(group this)] spawn A3EAI_customHeliDetect;};",_randomizeChance]};
format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint};",_randomizeChance]
};
_wpTimeouts = if (_max_dist >= 100) then {[0, 3, 5]} else {[3, 6, 9]};
_center_x = (_pos) select 0;
_center_y = (_pos) select 1;
_center_z = (_pos) select 2;
if(isNil "_center_z")then{_center_z = 0;};
_allowInNoAggroArea = ([_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea);
_wp_count = 4 + (floor random 3) + (floor (_max_dist / 100 ));
_angle = (360 / (_wp_count -1));
_newangle = 0;
_wp_array = [];
_slack = _max_dist / 5.5;
_completionRadius = if (_isVehicle) then {(25 + _slack)} else {(10 + _slack)};
if ( _slack < 20 ) then { _slack = 20 };
_angle_offset = random 180;
while {count _wp_array < _wp_count} do {
private ["_x1","_y1","_wp_pos", "_prepos","_bldgpos","_bldgs","_a","_b"];
_newangle = (count _wp_array * _angle) + _angle_offset;
if ((_newangle > 360) || {_newangle < 0}) then
{
_newangle = abs (abs (_newangle) - 360);
};
if ((random 1) < 0.5) then
{
_newangle = -_newangle;
if ((_newangle > 360) || {_newangle < 0}) then
{
_newangle = abs (abs (_newangle) - 360);
};
};
_x1 = _center_x - (sin _newangle * _max_dist);
_y1 = _center_y - (cos _newangle * _max_dist);
_prepos = [_x1, _y1, _center_z];
if ( isNil "_center_z" ) then {
_prepos = [_x1, _y1];
};
_wp_pos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
_retry = false;
if (((surfaceIsWater _wp_pos) && {!_allowWater}) or {([_wp_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea) or {_allowInNoAggroArea}}) then {
_retry = true;
_retryCount = 0;
_retryPos = [];
_newMaxDist = _max_dist;
while {_retry && {_retryCount < 2}} do {
_newMaxDist = _newMaxDist * 0.5;
_x1 = _center_x - (sin _newangle * _newMaxDist);
_y1 = _center_y - (cos _newangle * _newMaxDist);
_prepos = [_x1, _y1, _center_z];
if ( isNil "_center_z" ) then {
_prepos = [_x1, _y1];
};
_retryPos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
_retryCount = _retryCount + 1;
if ((!(surfaceIsWater _wp_pos) or {_allowWater}) && (!([_wp_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea) or {_allowInNoAggroArea})) then {
_retry = false;
_wp_pos = _retryPos;
};
};
};
if !(_retry) then {
_a = 0 + (_wp_pos select 0);
_b = 0 + (_wp_pos select 1);
if (_searchLoot) then {
//////////////////////////////////////////////////////////////////
// The following code is an extract from Random Building Position Script v1.0 by Tophe of Östgöta Ops
//////////////////////////////////////////////////////////////////
_bldgpos = [];
_bldgs = nearestObjects [[_a,_b,0], ["HouseBase"], 50];
{
private["_i","_y"];
_i = 0;
_y = _x buildingPos _i;
//while {format["%1", _y] != "[0,0,0]"} do {
while {!(_y isEqualTo [0,0,0]) } do {
//_bldgpos = _bldgpos + [_y];
_bldgpos pushBack _y;
_i = _i + 1;
_y = _x buildingPos _i;
};
} forEach _bldgs;
if(count _bldgpos != 0) then {_wp_pos = _bldgpos call A3EAI_selectRandom;};
} else {
if (_isVehicle) then {
_nearRoads = _wp_pos nearRoads ((_max_dist/2) min 100);
_roadsCount = count _nearRoads;
_returnPos = [];
if (_roadsCount > 0) then {
_returnPos = getPosATL (_nearRoads select 0);
if (_roadsCount > 1) then {
for "_i" from 1 to (_roadsCount -1) do {
_comparePos = getPosATL (_nearRoads select _i);
if ((_comparePos distance _wp_pos) < (_returnPos distance _wp_pos)) then {
_returnPos = _comparePos;
};
};
};
_wp_pos = _returnPos;
};
};
};
//_wp_array = _wp_array + [_wp_pos];
_wp_array pushBack _wp_pos;
};
uiSleep 0.25;
};
for "_i" from 1 to (_wp_count - 1) do
{
private ["_wp","_cur_pos"];
_cur_pos = (_wp_array select _i);
_wp = _unitGroup addWaypoint [_cur_pos, 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius _completionRadius;
_wp setWaypointTimeout [_wpTimeouts select 0, _wpTimeouts select 1, _wpTimeouts select 2];
_wp setWaypointStatements ["true",_wpStatements];
_wp setWaypointCombatMode _combatMode;
_wp setWaypointBehaviour _behavior;
uiSleep 0.25;
};
_endWP = [_pos, 0, 50, 6, 0, 50 * (pi / 180), 0, [],[_pos]] call BIS_fnc_findSafePos;
// End back near start point and then pick a new random point
_wp1 = _unitGroup addWaypoint [_endWP, 0];
_wp1 setWaypointType "MOVE";
_wp1 setWaypointCompletionRadius (_max_dist max 50);
_wp1 setWaypointCombatMode _combatMode;
_wp1 setWaypointBehaviour _behavior;
[_unitGroup,(count waypoints _unitGroup)] setWaypointStatements ["true", "if !(local this) exitWith {}; group this setCurrentWaypoint [(group this), (round (random 2) + 1)];"];
// Cycle in case we reach the end
_wp2 = _unitGroup addWaypoint [_endWP, 0];
_wp2 setWaypointType "CYCLE";
_wp2 setWaypointCompletionRadius (_max_dist max 50);
_wp2 setWaypointCombatMode _combatMode;
_wp2 setWaypointBehaviour _behavior;
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
if ((getWPPos [_unitGroup,_i]) isEqualTo [0,0,0]) then {
diag_log format ["A3EAI Error: Waypoint %1 is invalid position.",[_unitGroup,_i]];
deleteWaypoint [_unitGroup,_i];
};
};
if (A3EAI_enableHC && {_unitType in A3EAI_HCAllowedTypes}) then {_unitGroup setVariable ["HC_Ready",true];};
true

View File

@ -0,0 +1,62 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_canCall","_vehicle","_detectStartPos","_searchLength"];
_unitGroup = _this select 0;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_canCall = true;
_searchLength = _unitGroup getVariable "SearchLength";
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3EAI_UAVCallReinforceCooldown])) > A3EAI_UAVCallReinforceCooldown) then {
_detectStartPos = getPosATL _vehicle;
_vehicle flyInHeight (FLYINHEIGHT_UAV_SEARCHING_BASE + (random FLYINHEIGHT_UAV_SEARCHING_VARIANCE));
_unitGroup getVariable ["IsDetecting",true];
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
_vehPos = getPosATL _vehicle;
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
_detected = (getPosATL _vehicle) nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UAV];
if ((count _detected) > 5) then {_detected resize 5};
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
{
_playerPos = getPosATL _x;
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_UAVDetectChance call A3EAI_chance}) then {
if (_canCall) then {
if (isDedicated) then {
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3EAI_spawn_reinforcement;
} else {
A3EAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
publicVariableServer "A3EAI_spawnReinforcements_PVS";
};
_unitGroup setVariable ["UVLastCall",diag_tickTime];
_canCall = false;
};
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
_unitGroup reveal [_x,2.5];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[41+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3EAI_radioSend;
};
};
};
};
uiSleep 0.1;
} forEach _detected;
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
uiSleep 15;
_unitGroup getVariable ["IsDetecting",false];
};
_vehicle flyInHeight (FLYINHEIGHT_UAV_PATROLLING_BASE + (random FLYINHEIGHT_UAV_PATROLLING_VARIANCE));
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};

View File

@ -0,0 +1,30 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_tooClose","_detectionWaypoint","_exitWaypoint","_vehicle","_dirPosToVehicle","_locationSelected"];
_unitGroup = _this select 0;
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_tooClose = true;
_locationSelected = [0,0,0];
while {_tooClose} do {
_locationSelected = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance _locationSelected) > NEXT_WP_DIST_UAV) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_dirPosToVehicle = [_locationSelected,_vehicle] call BIS_fnc_dirTo;
_detectionWaypoint = [_locationSelected,WP_POS_INGRESS_BASE_UAV+(random WP_POS_INGRESS_VARIANCE_UAV),_dirPosToVehicle,1] call A3EAI_SHK_pos;
[_unitGroup,0] setWaypointPosition [_detectionWaypoint,0];
_dirPosToVehicle = [_vehicle,_locationSelected] call BIS_fnc_dirTo;
_exitWaypoint = [_detectionWaypoint,WP_POS_EGRESS_BASE_UAV+(random WP_POS_EGRESS_VARIANCE_UAV),_dirPosToVehicle,1] call A3EAI_SHK_pos;
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance _exitWaypoint)];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};

View File

@ -0,0 +1,58 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_vehicle","_canCall"];
_unitGroup = _this select 0;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_canCall = true;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection start.",_unitGroup,(typeOf (_vehicle))];};
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3EAI_UGVCallReinforceCooldown])) > A3EAI_UGVCallReinforceCooldown) then {
_detectStartPos = getPosATL _vehicle;
_unitGroup getVariable ["IsDetecting",true];
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
private ["_detected","_detectOrigin","_startPos","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
_vehPos = getPosATL _vehicle;
_startPos = getPosATL _vehicle;
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
_detectOrigin = [_startPos,0,getDir _vehicle,1] call A3EAI_SHK_pos;
_detected = _detectOrigin nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UGV];
if ((count _detected) > 5) then {_detected resize 5};
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
{
_playerPos = getPosATL _x;
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_UGVDetectChance call A3EAI_chance}) then {
if (_canCall) then {
if (isDedicated) then {
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3EAI_spawn_reinforcement;
} else {
A3EAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
publicVariableServer "A3EAI_spawnReinforcements_PVS";
};
_unitGroup setVariable ["UVLastCall",diag_tickTime];
_canCall = false;
};
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
_unitGroup reveal [_x,2.5];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[51+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3EAI_radioSend;
};
};
};
};
uiSleep 0.1;
} forEach _detected;
if (((_vehicle distance2D _detectStartPos) > DETECT_LENGTH_UGV_2D) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
uiSleep 15;
};
_unitGroup getVariable ["IsDetecting",false];
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};

View File

@ -0,0 +1,23 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_tooClose","_locationSelected"];
_unitGroup = _this select 0;
_tooClose = true;
_locationSelected = [0,0,0];
while {_tooClose} do {
_locationSelected = (A3EAI_locationsLand call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > 300) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_locationSelected = [_locationSelected,random(300),random(360),0,[1,300]] call A3EAI_SHK_pos;
[_unitGroup,0] setWPPos _locationSelected;
[_unitGroup,1] setWPPos _locationSelected;
[_unitGroup,2] setWaypointPosition [_locationSelected,0];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};

View File

@ -0,0 +1,31 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_searchPoints", "_trigger", "_radius", "_posBetween", "_searchType", "_objects", "_waypoint"];
_unitGroup = _this select 0;
if ((count (waypoints _unitGroup)) > 9) exitWith {};
_searchPoints = call {
_trigger = _unitGroup getVariable "trigger";
if (isNil "_trigger") exitWith {[]};
_radius = (_trigger getVariable ["patrolDist",100])/2;
_posBetween = [_trigger,(leader _unitGroup),_radius] call A3EAI_getPosBetween;
_searchType = floor (random 2);
if (_searchType isEqualTo 0) exitWith {
_objects = _posBetween nearObjects [LOOT_HOLDER_CLASS,_radius];
_objects
};
if (_searchType isEqualTo 1) exitWith {
_objects = _posBetween nearEntities [[PLAYER_UNITS,"LandVehicle"],_radius];
_objects
};
[]
};
{
if ((count (waypoints _unitGroup)) > 9) exitWith {};
_waypoint = [_unitGroup,getPosATL _x] call A3EAI_addTemporaryWaypoint;
} forEach _searchPoints;
true

View File

@ -0,0 +1,34 @@
#include "\A3EAI\globaldefines.hpp"
private ["_detectOrigin", "_vehicle", "_detected", "_unitGroup", "_heliAimPos", "_playerAimPos"];
_vehicle = _this select 0;
_unitGroup = _this select 1;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
_unitGroup setVariable ["IsDetecting",true];
uiSleep (round (random 20));
if (!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}) then{
_detectOrigin = [getPosATL _vehicle,0,getDir _vehicle,1] call A3EAI_SHK_pos;
_detectOrigin set [2,0];
_detected = _detectOrigin nearEntities [[PLAYER_UNITS],DETECT_RANGE_AIR_CUSTOM];
if ((count _detected) > 5) then {_detected resize 5};
{
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 2}) then {
_heliAimPos = aimPos _vehicle;
_playerAimPos = aimPos _x;
if (((lineIntersectsSurfaces [_heliAimPos,_playerEyePos,_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_airDetectChance call A3EAI_chance}) then {
//if (!(terrainIntersectASL [_heliAimPos,_playerAimPos]) && {!(lineIntersects [_heliAimPos,_playerAimPos,_vehicle,_x])} && {A3EAI_airDetectChance call A3EAI_chance}) then { //if no intersection of terrain and objects between helicopter and player, then reveal player
_unitGroup reveal [_x,2.5];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
};
};
};
uiSleep 0.1;
} forEach _detected;
};
_unitGroup setVariable ["IsDetecting",false];

View File

@ -0,0 +1,20 @@
#include "\A3EAI\globaldefines.hpp"
private ["_vehicle", "_hitSource", "_damage", "_unitGroup", "_aggroExpiry"];
_vehicle = _this select 0;
_hitSource = _this select 1;
_damage = _this select 2;
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
if (_unitGroup call A3EAI_getNoAggroStatus) exitWith {false};
if ((isPlayer _hitSource) && {_damage > 0.1} && {(combatMode _unitGroup isEqualTo "BLUE")}) then {
_aggroExpiry = diag_tickTime + DEFENSIVE_AGGRESSION_TIME;
_vehicle setVariable ["AggroTime",_aggroExpiry];
[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Defensive aggression enabled for %1 %2",_unitGroup,(typeOf _vehicle)];};
};
true

View File

@ -0,0 +1,23 @@
#include "\A3EAI\globaldefines.hpp"
private ["_action", "_unitGroup"];
_action = _this select 1;
_unitGroup = _this select 0;
if (_action isEqualTo "IgnoreEnemies") exitWith {
_unitGroup setBehaviour "CARELESS";
_unitGroup setCombatMode "BLUE";
{_x doWatch objNull} forEach (units _unitGroup);
true
};
if (_action isEqualTo "Behavior_Reset") exitWith {
_unitGroup setBehaviour "AWARE";
_unitGroup setCombatMode "YELLOW";
true
};
false

View File

@ -0,0 +1,55 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_detectBase","_vehicle","_canParaDrop","_detectStartPos","_searchLength"];
_unitGroup = _this select 0;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_searchLength = _unitGroup getVariable "SearchLength";
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
_detectStartPos = getPosATL _vehicle;
_canParaDrop = ((diag_tickTime - (_unitGroup getVariable ["HeliLastParaDrop",-A3EAI_paradropCooldown])) > A3EAI_paradropCooldown);
_vehicle flyInHeight (FLYINHEIGHT_AIR_SEARCHING_BASE + (random FLYINHEIGHT_AIR_SEARCHING_VARIANCE));
_unitGroup getVariable ["IsDetecting",true];
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
_vehPos = getPosATL _vehicle;
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
_detected = _vehPos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR];
if ((count _detected) > 5) then {_detected resize 5};
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
{
_playerPos = getPosATL _x;
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
if (_canParaDrop) then {
_canParaDrop = false;
_unitGroup setVariable ["HeliLastParaDrop",diag_tickTime];
_nul = [_unitGroup,_vehicle,_x] spawn A3EAI_heliParaDrop;
};
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_airDetectChance call A3EAI_chance}) then {
_unitGroup reveal [_x,2.5];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
};
};
};
};
uiSleep 0.1;
} forEach _detected;
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
uiSleep 15;
_unitGroup getVariable ["IsDetecting",false];
};
_vehicle flyInHeight (FLYINHEIGHT_AIR_PATROLLING_BASE + (random FLYINHEIGHT_AIR_PATROLLING_VARIANCE));
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};

View File

@ -0,0 +1,30 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_tooClose","_detectionWaypoint","_exitWaypoint","_vehicle","_dir","_locationSelected"];
_unitGroup = _this select 0;
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_tooClose = true;
_locationSelected = [0,0,0];
while {_tooClose} do {
_locationSelected = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > NEXT_WP_DIST_AIR) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_dir = [_locationSelected,_vehicle] call BIS_fnc_dirTo;
_detectionWaypoint = [_locationSelected,WP_POS_INGRESS_BASE_AIR + (random WP_POS_INGRESS_VARIANCE_AIR),_dir,1] call A3EAI_SHK_pos;
[_unitGroup,0] setWaypointPosition [_detectionWaypoint,0];
_dir = [_vehicle,_locationSelected] call BIS_fnc_dirTo;
_exitWaypoint = [_detectionWaypoint,WP_POS_EGRESS_BASE_AIR + (random WP_POS_EGRESS_VARIANCE_AIR),_dir,1] call A3EAI_SHK_pos;
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance2D _exitWaypoint)];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};

View File

@ -0,0 +1,141 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_targetPlayer","_startPos","_chaseDistance","_enableHCReady","_nearBlacklistedAreas","_targetPlayerPos"];
_targetPlayer = _this select 0;
_unitGroup = _this select 1;
//Disable killer-finding for dynamic AI in hunting mode
if (_unitGroup getVariable ["seekActive",false]) exitWith {};
//If group is already pursuing player and target player has killed another group member, then extend pursuit time.
if (((_unitGroup getVariable ["pursuitTime",0]) > 0) && {((_unitGroup getVariable ["targetKiller",""]) isEqualTo (name _targetPlayer))}) exitWith {
_unitGroup setVariable ["pursuitTime",((_unitGroup getVariable ["pursuitTime",0]) + 20)];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Pursuit time +20 sec for Group %1 (Target: %2) to %3 seconds.",_unitGroup,name _targetPlayer,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime]};
};
_enableHCReady = false;
if (_unitGroup getVariable ["HC_Ready",false]) then { //If HC mode enabled and AI group is controlled by server, prevent it from being transferred to HC until hunting mode is over.
_unitGroup setVariable ["HC_Ready",false];
_enableHCReady = true;
};
_startPos = _unitGroup getVariable ["trigger",(getPosASL (leader _unitGroup))];
_chaseDistance = _unitGroup getVariable ["patrolDist",250];
_targetPlayerPos = getPosATL _targetPlayer;
_nearBlacklistedAreas = nearestLocations [_targetPlayerPos,[BLACKLIST_OBJECT_GENERAL],1500];
_unitGroup setFormDir ([(leader _unitGroup),_targetPlayerPos] call BIS_fnc_dirTo);
if ((_startPos distance _targetPlayerPos) < _chaseDistance) then {
private ["_leader","_ableToChase","_marker"];
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 has entered pursuit state for 180 seconds. Target: %2.",_unitGroup,_targetPlayer];};
//Set pursuit timer
_unitGroup setVariable ["pursuitTime",diag_tickTime+180];
_unitGroup setVariable ["targetKiller",name _targetPlayer];
if (A3EAI_enableDebugMarkers) then {
_markername = format ["%1 Target",_unitGroup];
if (_markername in allMapMarkers) then {deleteMarker _markername; uiSleep 0.5;};
_marker = createMarker [_markername,getPosASL _targetPlayer];
_marker setMarkerText _markername;
_marker setMarkerType "mil_warning";
_marker setMarkerColor "ColorRed";
_marker setMarkerBrush "Solid";
};
//Begin pursuit state.
_ableToChase = true;
while {
_ableToChase &&
{isPlayer _targetPlayer} &&
{alive _targetPlayer} &&
{((_startPos distance _targetPlayer) < _chaseDistance)} &&
{(vehicle _targetPlayer) isKindOf "Land"}
} do {
_targetPlayerPos = getPosATL _targetPlayer;
if (({_targetPlayerPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
(units _unitGroup) doMove _targetPlayerPos;
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: AI group %1 in pursuit state. Pursuit time remaining: %2 seconds.",_unitGroup,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime];};
if ((A3EAI_enableRadioMessages) && {0.7 call A3EAI_chance}) then {
_leader = (leader _unitGroup);
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER}) then {
_nearbyUnits = _targetPlayerPos nearEntities [[PLAYER_UNITS,"LandVehicle"],TRANSMIT_RANGE_RADIO_HUNTKILLER];
if !(_nearbyUnits isEqualTo []) then { //Have at least 1 player to send a message to
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then { //Have at least 1 AI unit to send a message from
_speechIndex = (floor (random 3));
_radioSpeech = call {
if (_speechIndex isEqualTo 0) exitWith {
[1,[(name _leader),(name _targetPlayer)]]
};
if (_speechIndex isEqualTo 1) exitWith {
[2,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]
};
if (_speechIndex isEqualTo 2) exitWith {
[3,[(name _leader),round (_leader distance _targetPlayer)]]
};
[0,[]]
};
{
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
[_x,_radioSpeech] call A3EAI_radioSend;
};
} count _nearbyUnits;
} else {
{
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
[_x,[0,[]]] call A3EAI_radioSend;
};
} count _nearbyUnits;
};
};
};
};
if (A3EAI_enableDebugMarkers) then {
_marker setMarkerPos (getPosASL _targetPlayer);
};
_ableToChase = ((!isNull _unitGroup) && {diag_tickTime < (_unitGroup getVariable ["pursuitTime",0])} && {(_unitGroup getVariable ["GroupSize",0]) > 0});
if (_ableToChase) then {uiSleep 20};
};
if !(isNull _unitGroup) then {
//End of pursuit state. Re-enable patrol state.
_unitGroup setVariable ["pursuitTime",0];
_unitGroup setVariable ["targetKiller",""];
//_unitGroup lockWP false;
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
_waypoints = (waypoints _unitGroup);
_unitGroup setCurrentWaypoint (_waypoints call A3EAI_selectRandom);
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Pursuit state ended for group %1. Returning to patrol state. (fn_findKiller)",_unitGroup];};
if (A3EAI_enableRadioMessages) then {
_leader = (leader _unitGroup);
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER} && {((_unitGroup getVariable ["GroupSize",0]) > 1)} && {isPlayer _targetPlayer}) then {
_radioText = if (alive _targetPlayer) then {4} else {5};
_radioSpeech = [_radioText,[name (leader _unitGroup)]];
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTKILLER];
{
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
[_x,_radioSpeech] call A3EAI_radioSend;
};
} count _nearbyUnits;
};
};
};
if (_enableHCReady) then {
_unitGroup setVariable ["HC_Ready",true];
};
};
if (A3EAI_enableDebugMarkers) then {
deleteMarker _marker;
};
};

View File

@ -0,0 +1,80 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_targetPlayer", "_waypoint", "_leader", "_nearbyUnits", "_index", "_radioSpeech", "_searchPos","_triggerPos","_nearBlacklistedAreas","_targetPos"];
_unitGroup = _this;
_triggerPos = getPosATL (_unitGroup getVariable ["trigger",objNull]);
_targetPlayer = _unitGroup getVariable ["targetplayer",objNull];
try {
if !(isPlayer _targetPlayer) then {
throw "Target is not a player.";
};
_nearBlacklistedAreas = nearestLocations [_targetPlayer,[BLACKLIST_OBJECT_GENERAL],1500];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Hunter group %1 has target player %2 and anchor pos %3.",_unitGroup,_targetPlayer,_triggerPos];};
if (
(isPlayer _targetPlayer) &&
{alive _targetPlayer} &&
{(vehicle _targetPlayer) isKindOf "Land"} &&
{(_targetPlayer distance _triggerPos) < SEEK_RANGE_HUNTER}
) then {
_waypoint = [_unitGroup,0];
_targetPos = getPosATL _targetPlayer;
if (({_targetPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
if (((getWPPos _waypoint) distance _targetPlayer) > 20) then {
_waypoint setWPPos _targetPos;
//diag_log format ["Debug: Hunter group %1 is seeking player %2 (position: %3).",_unitGroup,_targetPlayer,(getPosATL _targetPlayer)];
} else {
_searchPos = [(getWPPos _waypoint),20+(random 20),(random 360),0] call A3EAI_SHK_pos;
_waypoint setWPPos _searchPos;
};
};
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
_unitGroup setCurrentWaypoint _waypoint;
if (A3EAI_enableRadioMessages) then {
_leader = (leader _unitGroup);
if ((_leader distance _targetPlayer) < RADIO_RECEPTION_RANGE) then {
_nearbyUnits = _targetPos nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTER];
if !(_nearbyUnits isEqualTo []) then {
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then {
_index = (floor (random 4));
_radioSpeech = call {
if (_index isEqualTo 0) exitWith {[11,[(name _leader),(name _targetPlayer)]]};
if (_index isEqualTo 1) exitWith {[12,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]};
if (_index isEqualTo 2) exitWith {[13,[(name _leader),round (_leader distance _targetPlayer)]]};
if (_index > 2) exitWith {[0,[]]};
[0,[]]
};
{
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
[_x,_radioSpeech] call A3EAI_radioSend;
};
} count _nearbyUnits;
} else {
{
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
[_x,[0,[]]] call A3EAI_radioSend;
};
} count _nearbyUnits;
};
};
};
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 has located player %2.",_unitGroup,_targetPlayer];};
} else {
throw "Hunt ended.";
};
} catch {
[_unitGroup,0] setWaypointStatements ["true","if !(local this) exitWith {}; if ((random 1) < 0.50) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];};"];
0 = [_unitGroup,_triggerPos,PATROL_DIST_DYNAMIC] spawn A3EAI_BIN_taskPatrol;
_unitGroup setSpeedMode "FULL";
if (A3EAI_enableHC && {isDedicated}) then {_unitGroup setVariable ["MiscData",nil];};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is patrolling area. (%2)",_unitGroup,_exception];};
};

View File

@ -0,0 +1,85 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_waypoint", "_vehicle", "_endTime", "_vehiclePos", "_nearUnits", "_vehPos", "_despawnPos", "_reinforcePos","_vehicleArmed","_paraDrop","_reinforceTime"];
_unitGroup = _this;
if (!hasInterface && !isDedicated) exitWith {diag_log format ["Error: %1 executed on headless client.",__FILE__];};
if !((typeName _unitGroup) isEqualTo "GROUP") exitWith {diag_log format ["A3EAI Error: Invalid group %1 provided to %2.",_unitGroup,__FILE__];};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_vehicleArmed = ((({_x call A3EAI_checkIsWeapon} count (weapons _vehicle)) > 0) || {({_x call A3EAI_checkIsWeapon} count (_vehicle weaponsTurret [-1])) > 0} || {(_vehicle call A3EAI_countVehicleGunners) > 0});
_reinforcePos = _unitGroup getVariable ["ReinforcePos",[0,0,0]];
if (_vehicleArmed) then {
_waypoint = [_unitGroup,0];
_waypoint setWaypointStatements ["true",""];
_waypoint setWaypointType "GUARD";
_waypoint setWaypointBehaviour "AWARE";
_waypoint setWaypointCombatMode "RED";
if (local _unitGroup) then {
_unitGroup setCurrentWaypoint _waypoint;
} else {
A3EAI_setCurrentWaypoint_PVC = _waypoint;
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_setCurrentWaypoint_PVC";
};
_reinforceTime = missionNamespace getVariable [format ["A3EAI_airReinforcementDuration%1",_unitGroup getVariable ["unitLevel",0]],0];
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 is now reinforcing for %2 seconds.",_unitGroup,_reinforceTime];};
_unitGroup setSpeedMode "LIMITED";
_endTime = diag_tickTime + _reinforceTime;
while {(diag_tickTime < _endTime) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {(_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce"}} do {
if (local _unitGroup) then {
_vehiclePos = getPosATL _vehicle;
_vehiclePos set [2,0];
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR_REINFORCE];
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
{
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3} && {(lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []}) then {
_unitGroup reveal [_x,3];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
};
};
} forEach _nearUnits;
};
uiSleep 15;
};
_unitGroup setSpeedMode "NORMAL";
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 reinforcement timer complete.",_unitGroup];};
} else {
_paraDrop = [_unitGroup,_vehicle,objNull] spawn A3EAI_heliParaDrop;
waitUntil {uiSleep 0.1; scriptDone _paraDrop};
};
if (((_unitGroup getVariable ["GroupSize",-1]) < 1) or {!((_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce")}) exitWith {
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (type: %2) is no longer reinforcing, reinforce timer exited.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])];};
};
_vehPos = (getPosATL _vehicle);
_despawnPos = [_vehPos,AIR_REINFORCE_DESPAWN_DIST,random(360),1] call A3EAI_SHK_pos;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 Vehicle %2 (pos %3) assigned despawn pos %4.",_unitGroup,(typeOf _vehicle),_vehPos,_despawnPos];};
_waypoint = _unitGroup addWaypoint [_despawnPos,0];
_waypoint setWaypointType "MOVE";
_waypoint setWaypointBehaviour "CARELESS";
if (_vehicleArmed) then {_waypoint setWaypointCombatMode "BLUE";};
if (local _unitGroup) then {
_unitGroup setCurrentWaypoint _waypoint;
} else {
A3EAI_setCurrentWaypoint_PVC = _waypoint;
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_setCurrentWaypoint_PVC";
};
waitUntil {uiSleep 15; (((getPosATL _vehicle) distance2D _vehPos) > 1200) or {!(alive _vehicle)}};
_unitGroup call A3EAI_cleanupReinforcementGroup;
A3EAI_reinforcedPositions = A3EAI_reinforcedPositions - _reinforcePos;
true

View File

@ -0,0 +1,47 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_triggerPos", "_targetPlayer", "_nearbyUnits", "_waypoint", "_patrolDist","_targetPos"];
_unitGroup = _this select 0;
_patrolDist = _this select 1;
_targetPlayer = _this select 2;
_triggerPos = _this select 3;
_targetPos = getPosATL _targetPlayer;
if ((isPlayer _targetPlayer) && {(vehicle _targetPlayer) isKindOf "Land"}) then {
if (A3EAI_enableRadioMessages) then {
//diag_log "DEBUG: Sending radio static";
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
_nearbyUnits = _targetPlayer nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTER];
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
{
if (isPlayer _x) then {
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[0,[]]] call A3EAI_radioSend;
};
}
} count _nearbyUnits;
};
};
_unitGroup setSpeedMode "FULL";
_waypoint = [_unitGroup,0]; //Group will move to waypoint index 0 (first waypoint).
_waypoint setWaypointType "MOVE";
_waypoint setWaypointCompletionRadius 50;
_waypoint setWaypointTimeout [3, 3, 3];
_waypoint setWPPos _targetPos;
_waypoint setWaypointStatements ["true","if !(local this) exitWith {}; (group this) spawn A3EAI_hunterLocate;"];
_unitGroup setCurrentWaypoint _waypoint;
_unitGroup setVariable ["targetplayer",_targetPlayer];
if (A3EAI_enableHC && {"dynamic" in A3EAI_HCAllowedTypes}) then {
_unitGroup setVariable ["HC_Ready",true];
_unitGroup setVariable ["MiscData",_targetPlayer];
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is now hunting player %2.",_unitGroup,_targetPlayer];};
} else {
0 = [_unitGroup,_triggerPos,_patrolDist] spawn A3EAI_BIN_taskPatrol;
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is patrolling area.",_unitGroup];};
};

View File

@ -0,0 +1,43 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_vehicle","_loadWP","_loadWPCond","_unit","_regroupPos","_waypointCycle"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
if ((count (waypoints _unitGroup)) > 1) exitWith {
if (isNull (driver _vehicle)) then {
[_unitGroup,1] setWaypointPosition [(getPosATL _vehicle),0];
_unitGroup setCurrentWaypoint [_unitGroup,1];
};
};
_unit = objNull;
{
if (isNull (objectParent _x)) exitWith {_unit = _x};
} forEach (units _unitGroup);
if (isNull _unit) exitWith {_unitGroup call A3EAI_setVehicleRegrouped}; //If no units outside of vehicle, consider crew regrouped and exit script
_regroupPos = if (isNull (driver _vehicle)) then {
(getPosATL _vehicle)
} else {
([_vehicle,_unit,(_unit distance _vehicle)/2] call A3EAI_getPosBetween)
};
_loadWP = _unitGroup addWaypoint [_regroupPos,0];
_loadWP setWaypointType "LOAD";
_loadWPCond = "_vehicle = (group this) getVariable ['assignedVehicle',objNull]; ({_x isEqualTo (vehicle _x)} count (assignedCargo _vehicle)) isEqualTo 0";
_loadWP setWaypointStatements [_loadWPCond,"if !(local this) exitWith {}; (group this) spawn A3EAI_vehCrewRegroupComplete;"];
_waypointCycle = _unitGroup addWaypoint [_regroupPos, 0];
_waypointCycle setWaypointType "CYCLE";
_waypointCycle setWaypointStatements ["true","if !(local this) exitWith {}; _unitGroup = (group this); deleteWaypoint [_unitGroup,2]; deleteWaypoint [_unitGroup,1];"];
_waypointCycle setWaypointCompletionRadius 150;
_loadWP setWaypointCompletionRadius 10;
_unitGroup setCurrentWaypoint _loadWP;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Regroup order issued for AI group %1 to vehicle %2. Check WP count: %3.",_unitGroup,typeOf _vehicle,(count (waypoints _unitGroup))];};
true

View File

@ -0,0 +1,16 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_vehicle","_vehiclePos"];
_unitGroup = _this;
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
if (isNull _vehicle) exitWith {diag_log format ["A3EAI Error: Group %1 has null vehicle.",_unitGroup];};
_vehiclePos = getPosATL _vehicle;
[_unitGroup,0] setWaypointPosition [_vehiclePos,0];
[_unitGroup,2] setWaypointPosition [_vehiclePos,0];
_unitGroup call A3EAI_setVehicleRegrouped;
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Regroup completed for vehicle group %1.",_unitGroup];};
true

View File

@ -0,0 +1,23 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_tooClose","_locationSelected"];
_unitGroup = _this select 0;
_tooClose = true;
_locationSelected = [0,0,0];
while {_tooClose} do {
_locationSelected = (A3EAI_locationsLand call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > 300) then {
_tooClose = false;
};
};
_locationSelected = [_locationSelected,random(300),random(360),0,[1,300]] call A3EAI_SHK_pos;
[_unitGroup,0] setWPPos _locationSelected;
[_unitGroup,0] setWaypointCompletionRadius 150;
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
_unitGroup setCurrentWaypoint [_unitGroup,0];
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};

View File

@ -0,0 +1,236 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_unitType", "_unitTypeRef", "_vehicle", "_stuckCheckTime", "_groupLeadMarker", "_groupWPMarker", "_fncArray", "_fnc_execEveryLoop", "_fnc_checkUnits",
"_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck", "_currentTime", "_managerStartTime", "_updateServerLoot", "_pullRate", "_markname", "_mark", "_markername", "_unitPos",
"_unitMarker", "_lootPool", "_result", "_debugStartTime"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
if (_unitGroup getVariable ["isManaged",false]) exitWith {};
_unitGroup setVariable ["isManaged",true];
_unitType = (_unitGroup getVariable ["unitType",""]);
_unitTypeRef = _unitType;
_vehicle = if (_unitType in ["air","land","aircustom","landcustom","air_reinforce","uav","ugv"]) then {_unitGroup getVariable ["assignedVehicle",(assignedVehicle (leader _unitGroup))]} else {objNull};
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
if (isNil {_unitGroup getVariable "GroupSize"}) then {_unitGroup setVariable ["GroupSize",(count (units _unitGroup))]};
_stuckCheckTime = _unitType call A3EAI_getAntistuckTime;
//set up debug variables
_groupLeadMarker = "";
_groupWPMarker = "";
//Set up local functions
_fncArray = [_unitGroup,_unitType] call A3EAI_getLocalFunctions;
_fnc_execEveryLoop = _fncArray select 0;
_fnc_checkUnits = _fncArray select 1;
_fnc_generateLoot = _fncArray select 2;
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
_fnc_antistuck = _fncArray select 4;
//Set up timer variables
_currentTime = diag_tickTime;
_managerStartTime = _currentTime;
_unitGroup setVariable ["lastRearmTime",_currentTime];
_unitGroup setVariable ["antistuckTime",_currentTime];
_unitGroup setVariable ["lootGenTime",_currentTime];
//Setup loot variables
_updateServerLoot = (A3EAI_enableHC && {!isDedicated});
_pullRate = 30;
if (isDedicated) then {
[_unitGroup,_unitType,_unitLevel] call A3EAI_setLoadoutVariables;
if (A3EAI_enableDebugMarkers) then {
_groupLeadMarker = format ["%1_Lead",_unitGroup];
if (_groupLeadMarker in allMapMarkers) then {deleteMarker _groupLeadMarker; uiSleep 0.5}; //Delete the previous marker if it wasn't deleted for some reason.
_groupLeadMarker = createMarker [_groupLeadMarker,getPosATL (leader _unitGroup)];
_groupLeadMarker setMarkerType "mil_warning";
_groupLeadMarker setMarkerBrush "Solid";
if (isNull _vehicle) then {
_groupLeadMarker setMarkerText format ["%1 (AI L%2)",_unitGroup,_unitLevel];
} else {
_groupLeadMarker setMarkerText format ["%1 (AI L%2 %3)",_unitGroup,_unitLevel,(typeOf (vehicle (leader _unitGroup)))];
};
_groupWPMarker = (format ["%1_WP",_unitGroup]);
if (_groupWPMarker in allMapMarkers) then {deleteMarker _groupWPMarker; uiSleep 0.5;}; //Delete the previous marker if it wasn't deleted for some reason.
_groupWPMarker = createMarker [_groupWPMarker,(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
_groupWPMarker setMarkerText format ["%1 Waypoint",_unitGroup];
_groupWPMarker setMarkerType "Waypoint";
_groupWPMarker setMarkerColor "ColorBlue";
_groupWPMarker setMarkerBrush "Solid";
[_unitGroup] spawn {
_unitGroup = _this select 0;
{
_markname = str(_x);
if (_markname in allMapMarkers) then {deleteMarker _markname; uiSleep 0.5};
_mark = createMarker [_markname,getPosATL _x];
_mark setMarkerShape "ELLIPSE";
_mark setMarkerType "Dot";
_mark setMarkerColor "ColorRed";
_mark setMarkerBrush "SolidBorder";
_nul = _x spawn {
_markername = str (_this);
_unitGroup = group _this;
while {alive _this} do {
if (local _this) then {
_unitPos = getPosATL _this;
if ((leader _unitGroup) isEqualTo _this) then {
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
_color = call {
_combatMode = (combatMode _unitGroup);
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
"ColorBlack"
};
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
};
_markername setMarkerPos _unitPos;
};
uiSleep 10;
};
deleteMarker _markername;
};
} forEach (units _unitGroup);
};
};
} else {
waitUntil {uiSleep 0.25; (local _unitGroup)};
[_unitGroup,_unitType,_unitLevel] call A3EAI_setLoadoutVariables_HC;
if (A3EAI_enableDebugMarkers) then {
{
_nul = _x spawn {
waitUntil {sleep 5; ((local _this) or {!(alive _this)})};
_unitMarker = str (_this);
_unitGroup = group _this;
while {alive _this} do {
if (local _this) then {
_unitPos = getPosATL _this;
if ((leader _unitGroup) isEqualTo _this) then {
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
_color = call {
_combatMode = (combatMode _unitGroup);
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
"ColorBlack"
};
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
};
_unitMarker setMarkerPos _unitPos;
};
uiSleep 10;
};
};
} forEach (units _unitGroup);
};
if (A3EAI_debugLevel > 1) then {
_lootPool = _unitGroup getVariable ["LootPool",[]];
//diag_log format ["Debug: Found loot pool for group %1 from server: %2",_unitGroup,_lootPool];
};
};
//Main loop
while {(!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
_unitType = (_unitGroup getVariable ["unitType",""]);
if !(_unitType isEqualTo _unitTypeRef) then {
_fncArray = [_unitGroup,_unitType] call A3EAI_getLocalFunctions;
_fnc_execEveryLoop = _fncArray select 0;
_fnc_checkUnits = _fncArray select 1;
_fnc_generateLoot = _fncArray select 2;
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
_fnc_antistuck = _fncArray select 4;
_stuckCheckTime = _unitType call A3EAI_getAntistuckTime;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reassigned group %1 type from %2 to %3.",_unitGroup,_unitTypeRef,_unitType];};
_unitTypeRef = _unitType;
};
[_unitGroup,_vehicle] call _fnc_execEveryLoop;
[_unitGroup] call _fnc_checkUnits;
//Generate loot
if ((diag_tickTime - (_unitGroup getVariable ["lootGenTime",diag_tickTime])) > _pullRate) then {
[_unitGroup,_unitLevel] call _fnc_generateLoot;
};
//Vehicle ammo/fuel check
if ((alive _vehicle) && {(diag_tickTime - (_unitGroup getVariable ["lastRearmTime",0])) > 180}) then { //If _vehicle is objNull (if no vehicle was assigned to the group) then nothing in this bracket should be executed
[_unitGroup,_vehicle] call _fnc_vehicleAmmoFuelCheck;
};
//Antistuck
if ((diag_tickTime - (_unitGroup getVariable ["antistuckTime",diag_tickTime])) > _stuckCheckTime) then {
[_unitGroup,_vehicle,_stuckCheckTime] call _fnc_antistuck;
};
if (A3EAI_HCIsConnected && {_unitGroup getVariable ["HC_Ready",false]} && {(diag_tickTime - _managerStartTime) > 30}) then {
private ["_result"];
_result = _unitGroup call A3EAI_transferGroupToHC;
if (_result) then {
waitUntil {sleep 1.5; (!(local _unitGroup) or {isNull _unitGroup})};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Transferred ownership of %1 group %2 to HC %3.",_unitType,_unitGroup,A3EAI_HCObjectOwnerID];};
waitUntil {sleep 15; ((local _unitGroup) or {isNull _unitGroup})};
if ((_unitGroup getVariable ["GroupSize",-1]) > 0) then {
_currentTime = diag_tickTime;
_unitGroup call A3EAI_initNoAggroStatus;
_unitGroup setVariable ["lastRearmTime",_currentTime];
_unitGroup setVariable ["antistuckTime",_currentTime];
_unitGroup setVariable ["lootGenTime",_currentTime];
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 ownership was returned to server.",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup];};
} else {
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Waiting to transfer %1 group %2 ownership to headless client (ID: %3).",_unitType,_unitGroup,A3EAI_HCObjectOwnerID];};
};
};
//diag_log format ["DEBUG: Group Manager cycle time for group %1: %2 seconds.",_unitGroup,(diag_tickTime - _debugStartTime)];
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {uiSleep 15};
};
if (A3EAI_enableDebugMarkers) then {
deleteMarker _groupLeadMarker;
deleteMarker _groupWPMarker;
};
if !(isNull _unitGroup) then {
_unitGroup setVariable ["isManaged",false]; //allow group manager to run again on group respawn.
if !(isDedicated) exitWith {
A3EAI_transferGroup_PVS = _unitGroup;
publicVariableServer "A3EAI_transferGroup_PVS"; //Return ownership to server.
A3EAI_HCGroupsCount = A3EAI_HCGroupsCount - 1;
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Returned ownership of AI %1 group %2 to server.",_unitType,_unitGroup];};
};
while {(_unitGroup getVariable ["GroupSize",-1]) isEqualTo 0} do { //Wait until group is either respawned or marked for deletion. A dummy unit should be created to preserve group.
uiSleep 5;
};
if ((_unitGroup getVariable ["GroupSize",-1]) isEqualTo -1) then { //GroupSize value of -1 marks group for deletion
if (!isNull _unitGroup) then {
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Deleting %2 group %1.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])]};
_unitGroup call A3EAI_deleteGroup;
};
};
} else {
diag_log "A3EAI Error: An A3EAI-managed group was deleted unexpectedly!";
};
if ((local _vehicle) && {isEngineOn _vehicle}) then {
_vehicle engineOn false;
};

View File

@ -0,0 +1,37 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect", "_leader"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
if (isNull _vehicle) exitWith {};
_checkPos = (getPosATL _vehicle);
_leader = (leader _unitGroup);
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < ANTISTUCK_MIN_TRAVEL_DIST_AIR} && {canMove _vehicle}) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_AIR_MIN_WP_DIST) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,ANTISTUCK_AIR_WP_DIST_BASE+(random ANTISTUCK_AIR_WP_DIST_VARIANCE),(random 360),1] call A3EAI_SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,1] setWPPos _wpSelect;
if ((count (waypoints _unitGroup)) > 2) then {[_unitGroup,2] setWPPos _wpSelect;};
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
_unitGroup setVariable ["antistuckPos",_wpSelect];
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI air vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,27 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_currentWP", "_allWP", "_nextWP","_leader"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
if (isNull _vehicle) exitWith {};
_checkPos = (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
_leader = (leader _unitGroup);
if ((((_leader distance2D (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea}) && {_checkPos isEqualTo (_unitGroup getVariable ["antistuckPos",[0,0,0]])} && {canMove _vehicle}) then {
_currentWP = (currentWaypoint _unitGroup);
_allWP = (waypoints _unitGroup);
_nextWP = _currentWP + 1;
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 1}; //Cycle back to first added waypoint if group is currently on last waypoint.
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI air (custom) group %1. Forcing next waypoint.",_unitGroup];};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,27 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_allWP", "_currentWP", "_nextWP","_leader"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
_allWP = (waypoints _unitGroup);
_leader = (leader _unitGroup);
if ((count _allWP) > 1) then {
_checkPos = (getPosATL (leader _unitGroup));
if ((((_leader distance (_leader findNearestEnemy _leader)) > NEAREST_ENEMY_INFANTRY) or {[_checkPos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea}) && ((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_INFANTRY) then {
_currentWP = (currentWaypoint _unitGroup);
_nextWP = _currentWP + 1;
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 0}; //Cycle back to first waypoint if group is currently on last waypoint.
[_unitGroup] call A3EAI_fixStuckGroup;
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI %1 group %2. Forcing next waypoint.",(_unitGroup getVariable ["unitType","unknown"]),_unitGroup];};
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
};
true

View File

@ -0,0 +1,35 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_allWP", "_currentWP", "_nextWP","_leader"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
if (isNull _vehicle) exitWith {};
_checkPos = (getPosATL _vehicle);
_leader = (leader _unitGroup);
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_LAND) or {[_checkPos,NO_AGGRO_RANGE_LAND] call A3EAI_checkInNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_LAND}) then {
if (canMove _vehicle) then {
[_unitGroup] call A3EAI_fixStuckGroup;
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
[_unitGroup,0] setWaypointPosition [_checkPos,0];
_unitGroup setCurrentWaypoint [_unitGroup,0];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI land vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
};
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
} else {
if (!(_vehicle getVariable ["vehicle_disabled",false])) then {
[_vehicle] call A3EAI_vehDestroyed;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: AI vehicle %1 (Group: %2) is immobilized. Respawning vehicle patrol group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
if (A3EAI_enableDebugMarkers) then {_checkPos call A3EAI_debugMarkerLocation;};
};
};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,37 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect","_leader"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
if (isNull _vehicle) exitWith {};
_checkPos = (getPosATL _vehicle);
_leader = (leader _unitGroup);
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < ANTISTUCK_MIN_TRAVEL_DIST_AIR} && {canMove _vehicle}) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_AIR_MIN_WP_DIST) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,ANTISTUCK_AIR_WP_DIST_BASE+(random ANTISTUCK_AIR_WP_DIST_VARIANCE),(random 360),1] call A3EAI_SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,1] setWPPos _wpSelect;
if ((count (waypoints _unitGroup)) > 2) then {[_unitGroup,2] setWPPos _wpSelect;};
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
_unitGroup setVariable ["antistuckPos",_wpSelect];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for UAV %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,34 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_stuckCheckTime = _this select 2;
if (isNull _vehicle) exitWith {};
_checkPos = (getPosATL _vehicle);
_leader = (leader _unitGroup);
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_LAND) or {[_checkPos,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_LAND}) then {
if (canMove _vehicle) then {
[_unitGroup] call A3EAI_fixStuckGroup;
[_unitGroup,0] setWaypointPosition [_checkPos,0];
[_unitGroup,1] setWaypointPosition [_checkPos,0];
_unitGroup setCurrentWaypoint [_unitGroup,1];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for UGV %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
} else {
if (!(_vehicle getVariable ["vehicle_disabled",false])) then {
[_vehicle] call A3EAI_UGV_destroyed;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: UGV %1 (Group: %2) is immobilized. Respawning UGV group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
if (A3EAI_enableDebugMarkers) then {_checkPos call A3EAI_debugMarkerLocation;};
};
};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,13 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unit", "_loadout", "_currentMagazines", "_magazine"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_result = _vehicle call A3EAI_reloadVehicleTurrets; //Rearms vehicle weapons/turrets individually
if ((A3EAI_debugLevel > 0) && {_result}) then {diag_log format ["A3EAI Debug: Reloaded ammo for group %1 %2.",_unitGroup,(typeOf _vehicle)];};
if ((fuel _vehicle) < 0.50) then {_vehicle setFuel 1; if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Refueled group %1 %2.",_unitGroup,(typeOf _vehicle)];};};
_unitGroup setVariable ["lastRearmTime",diag_tickTime];
true

View File

@ -0,0 +1,45 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unit", "_loadout", "_currentMagazines", "_magazine"];
_unitGroup = _this select 0;
{
if ((isNull (objectParent _x)) && {_x getVariable ["canCheckUnit",true]} && {local _x}) then {
_x setVariable ["canCheckUnit",false];
_nul = _x spawn {
if (!alive _this) exitWith {};
_unit = _this;
_loadout = _unit getVariable "loadout";
if (!isNil "_loadout") then {
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Unpacked unit manager for unit %1. Loadout found: %2.",_unit,_loadout];};
while {(alive _unit) && {isNull (objectParent _unit)} && {local _unit}} do {
_currentMagazines = (magazines _unit);
_magazine = ((_loadout select 1) select 0);
if (((_unit ammo ((_loadout select 0) select 0)) isEqualTo 0) || {!((_magazine in _currentMagazines))}) then {
_unit removeMagazines _magazine;
[_unit,_magazine] call A3EAI_addItem;
if (_unit getVariable ["extraMag",false]) then {
[_unit,_magazine] call A3EAI_addItem;
};
};
for "_i" from 1 to ((count (_loadout select 0)) - 1) do {
_magazine = ((_loadout select 1) select _i);
if (((_unit ammo ((_loadout select 0) select _i)) isEqualTo 0) && {!((_magazine in _currentMagazines))}) then {
_unit removeMagazines _magazine;
[_unit,_magazine] call A3EAI_addItem;
};
};
if (alive _unit) then {uiSleep 15};
};
};
if (alive _unit) then {
_unit setVariable ["canCheckUnit",true];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Repacking unit manager for unit %1.",_unit];};
};
};
};
uiSleep 0.1;
} forEach (units _unitGroup);
true

View File

@ -0,0 +1,20 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle","_inNoAggroArea","_result","_leader", "_assignedTarget"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_inArea = [_vehicle,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea;
if !(_inArea) then {
_leader = (leader _unitGroup);
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_AIR) then { //900: replace with engagement range
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
};
}; //To test!
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
true

View File

@ -0,0 +1,34 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_inArea", "_result", "_trigger", "_maxDistance","_leader", "_assignedTarget"];
_unitGroup = _this select 0;
//_vehicle = _this select 1;
_leader = (leader _unitGroup);
_inArea = [_leader,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_MAN) then { //900: replace with engagement range
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
};
};
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
/*
if !(_inArea) then {
_trigger = _unitGroup getVariable "trigger";
if !(isNil "_trigger") then {
_maxDistance = _unitGroup getVariable ["patrolDist",250];
if ((_leader distance2D _trigger) > (_maxDistance + PATROL_DISTANCE_BUFFER)) then {
_randomWaypoint = _unitGroup call A3EAI_setRandomWaypoint;
(units _unitGroup) doMove (waypointPosition _randomWaypoint);
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 moved beyond allowed patrol radius, ordering group towards spawn center.",_unitGroup];};
};
};
};
*/
true

View File

@ -0,0 +1,36 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_lastAggro","_result","_leader", "_assignedTarget"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
if (A3EAI_detectOnlyUAVs) then {
_lastAggro = _vehicle getVariable "AggroTime";
if (isNil "AggroTime") then {
_lastAggro = 0;
_vehicle setVariable ["AggroTime",0];
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
};
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea}) then {
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reset Group %1 %2 UAV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
};
};
} else {
_leader = (leader _unitGroup);
_inArea = [_vehicle,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UAV) then { //900: replace with engagement range
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
};
};
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
};
true

View File

@ -0,0 +1,36 @@
#include "\A3EAI\globaldefines.hpp"
private ["_hitArray", "_hitName", "_hitPoint", "_lastRepaired","_result","_leader", "_assignedTarget"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
if (A3EAI_detectOnlyUGVs) then {
_lastAggro = _vehicle getVariable "AggroTime";
if (isNil "AggroTime") then {
_lastAggro = 0;
_vehicle setVariable ["AggroTime",0];
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
};
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea}) then {
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reset Group %1 %2 UGV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
};
};
} else {
_leader = (leader _unitGroup);
_inArea = [_vehicle,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UGV) then { //900: replace with engagement range
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
};
};
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
};
true

View File

@ -0,0 +1,35 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_lastRegroupCheck","_inNoAggroArea","_inArea","_result","_leader", "_assignedTarget"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_leader = (leader _unitGroup);
_inArea = [_leader,NO_AGGRO_RANGE_LAND] call A3EAI_checkInNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_LAND) then { //900: replace with engagement range
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
};
}; //To test!
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
_lastRegroupCheck = _vehicle getVariable "LastRegroupCheck";
if (isNil "_lastRegroupCheck") then {
_lastRegroupCheck = diag_tickTime;
_vehicle setVariable ["LastRegroupCheck",0];
};
if ((diag_tickTime - _lastRegroupCheck) > 30) then {
if ((alive _vehicle) && {_unitGroup getVariable ["regrouped",true]} && {({if ((_x distance2D _vehicle) > REGROUP_VEHICLEGROUP_DIST) exitWith {1}} count (assignedCargo _vehicle)) > 0}) then {
_unitGroup setVariable ["regrouped",false];
[_unitGroup,_vehicle] call A3EAI_vehCrewRegroup;
};
_vehicle setVariable ["LastRegroupCheck",diag_tickTime];
};
true

View File

@ -0,0 +1,29 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_lootPool", "_updateServerLoot", "_pullChance", "_lootUnit", "_lootIndex", "_loot", "_unitLevel"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_lootPool = _unitGroup getVariable ["LootPool",[]];
_updateServerLoot = (A3EAI_enableHC && {!isDedicated});
_pullChance = missionNamespace getVariable [format ["A3EAI_lootPullChance%1",_unitLevel],0.40];
if !(_lootPool isEqualTo []) then {
if (_pullChance call A3EAI_chance) then {
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
_lootIndex = floor (random (count _lootPool));
_loot = _lootPool select _lootIndex;
if (alive _lootUnit) then {
if ([_lootUnit,_loot] call A3EAI_addItem) then {
_lootPool deleteAt _lootIndex;
if (_updateServerLoot) then {
[_unitGroup,_lootIndex] call A3EAI_updateServerLoot;
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Pulled %1 from %2 loot pool (%3 items remain).",_loot,_unitGroup,(count _lootPool)];};
};
};
};
};
_unitGroup setVariable ["lootGenTime",diag_tickTime];
true

View File

@ -0,0 +1,178 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unit", "_unitLevel", "_unitLevelInvalid", "_loadout", "_weaponSelected", "_unitLevelString", "_uniforms", "_backpacks", "_vests", "_headgears", "_magazine", "_uniformItem", "_backpackItem", "_vestItem", "_headgearItem",
"_useGL", "_weaponMuzzles", "_GLWeapon", "_GLMagazines", "_isRifle", "_opticsList", "_opticsType", "_pointersList", "_pointerType", "_muzzlesList", "_muzzleType", "_underbarrelList", "_underbarrelType", "_gadgetsArray", "_gadget"];
_unit = _this select 0;
_unitLevel = _this select 1;
if !(isNil {_unit getVariable "loadout"}) exitWith {diag_log format ["A3EAI Error: Unit already has loadout! (%1)",__FILE__];};
if !(_unitLevel in A3EAI_unitLevelsAll) then {
_unitLevelInvalid = _unitLevel;
_unitLevel = A3EAI_unitLevels call A3EAI_selectRandom;
diag_log format ["A3EAI Error: Invalid unitLevel provided: %1. Generating new unitLevel value: %2. (%3)",_unitLevelInvalid,_unitLevel,__FILE__];
};
_unit call A3EAI_purgeUnitGear; //Clear unwanted gear from unit first.
_loadout = [[],[]];
_weaponSelected = _unitLevel call A3EAI_getWeapon;
_unitLevelString = str (_unitLevel);
_uniformChance = missionNamespace getVariable ["A3EAI_addUniformChance"+_unitLevelString,1.00];
_uniformItem = DEFAULT_UNIFORM_ITEM;
if (_uniformChance call A3EAI_chance) then {
_uniforms = missionNamespace getVariable ["A3EAI_uniformTypes"+_unitLevelString,[]];
if !(_uniforms isEqualTo []) then {
_uniformItem = _uniforms call A3EAI_selectRandom;
_unit forceAddUniform _uniformItem;
//diag_log format ["DEBUG: %1",_uniformItem];
};
} else {
_unit forceAddUniform DEFAULT_UNIFORM_ITEM;
//diag_log format ["DEBUG: %1",DEFAULT_UNIFORM_ITEM];
};
_backpackChance = missionNamespace getVariable ["A3EAI_addBackpackChance"+_unitLevelString,1.00];
if (_backpackChance call A3EAI_chance) then {
_backpacks = missionNamespace getVariable ["A3EAI_backpackTypes"+_unitLevelString,[]];
if !(_backpacks isEqualTo []) then {
_backpackItem = _backpacks call A3EAI_selectRandom;
_unit addBackpack _backpackItem;
clearAllItemsFromBackpack _unit;
//diag_log format ["DEBUG: %1",_backpackItem];
};
};
_vestChance = missionNamespace getVariable ["A3EAI_addVestChance"+_unitLevelString,1.00];
if (_vestChance call A3EAI_chance) then {
_vests = missionNamespace getVariable ["A3EAI_vestTypes"+_unitLevelString,[]];
if !(_vests isEqualTo []) then {
_vestItem = _vests call A3EAI_selectRandom;
_unit addVest _vestItem;
//diag_log format ["DEBUG: %1",_vestItem];
};
} else {
_uniformClass = configName (configFile >> "CfgWeapons" >> _uniformItem >> "ItemInfo" >> "uniformClass");
_isWoman = [configFile >> "CfgVehicles" >> _uniformClass,"woman",0] call BIS_fnc_returnConfigEntry;
_vestItem = if (_isWoman isEqualTo 0) then {
DEFAULT_VEST_ITEM_MALE
} else {
DEFAULT_VEST_ITEM_FEMALE
};
_unit addVest _vestItem;
//diag_log format ["DEBUG: %1",_vestItem];
};
_headgearChance = missionNamespace getVariable ["A3EAI_addHeadgearChance"+_unitLevelString,1.00];
if (_headgearChance call A3EAI_chance) then {
_headgears = missionNamespace getVariable ["A3EAI_headgearTypes"+_unitLevelString,[]];
if !(_headgears isEqualTo []) then {
_headgearItem = _headgears call A3EAI_selectRandom;
_unit addHeadgear _headgearItem;
//diag_log format ["DEBUG: %1",_headgearItem];
};
};
_magazine = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "magazines") select 0;
_unit addMagazine _magazine;
_unit addWeapon _weaponSelected;
_unit selectWeapon _weaponSelected;
(_loadout select 0) pushBack _weaponSelected;
(_loadout select 1) pushBack _magazine;
if ((getNumber (configFile >> "CfgMagazines" >> _magazine >> "count")) < 6) then {
_unit setVariable ["extraMag",true];
_unit addMagazine _magazine;
};
//Grenades
_useGL = if !(A3EAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3EAI_levelRequiredGL} else {false};
if (_useGL) then {
_weaponMuzzles = getArray(configFile >> "cfgWeapons" >> _weaponSelected >> "muzzles");
if ((count _weaponMuzzles) > 1) then {
_GLWeapon = _weaponMuzzles select 1;
_GLMagazines = (getArray (configFile >> "CfgWeapons" >> _weaponSelected >> _GLWeapon >> "magazines"));
if (GRENADE_AMMO_3RND in _GLMagazines) then {
_unit addMagazine GRENADE_AMMO_3RND;
(_loadout select 0) pushBack _GLWeapon;
(_loadout select 1) pushBack GRENADE_AMMO_3RND;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_unit,_loadout];};
} else {
if (GRENADE_AMMO_1RND in _GLMagazines) then {
_unit addMagazine GRENADE_AMMO_1RND;
(_loadout select 0) pushBack _GLWeapon;
(_loadout select 1) pushBack GRENADE_AMMO_1RND;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_unit,_loadout];};
}
};
};
};
//Select weapon optics
_isRifle = ((getNumber (configFile >> "CfgWeapons" >> _weaponSelected >> "type")) isEqualTo 1);
if ((missionNamespace getVariable [("A3EAI_opticsChance"+_unitLevelString),3]) call A3EAI_chance) then {
_opticsList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems");
if !(_opticsList isEqualTo []) then {
_opticsType = A3EAI_weaponOpticsList call A3EAI_selectRandom;
if (_opticsType in _opticsList) then {
if (_isRifle) then {_unit addPrimaryWeaponItem _opticsType} else {_unit addHandGunItem _opticsType};
};
};
};
//Select weapon pointer
if ((missionNamespace getVariable [("A3EAI_pointerChance"+_unitLevelString),3]) call A3EAI_chance) then {
_pointersList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "PointerSlot" >> "compatibleItems");
if !(_pointersList isEqualTo []) then {
_pointerType = _pointersList call A3EAI_selectRandom;
if (_isRifle) then {_unit addPrimaryWeaponItem _pointerType} else {_unit addHandGunItem _pointerType};
//diag_log format ["DEBUG :: Added pointer item %1 to unit %2.",_pointerType,_unit];
};
};
//Select weapon muzzle
if ((missionNamespace getVariable [("A3EAI_muzzleChance"+_unitLevelString),3]) call A3EAI_chance) then {
_muzzlesList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems");
if !(_muzzlesList isEqualTo []) then {
_muzzleType = _muzzlesList call A3EAI_selectRandom;
if (_isRifle) then {_unit addPrimaryWeaponItem _muzzleType} else {_unit addHandGunItem _muzzleType};
//diag_log format ["DEBUG :: Added muzzle item %1 to unit %2.",_muzzleType,_unit];
};
};
//Select weapon muzzle
if ((missionNamespace getVariable [("A3EAI_underbarrelChance"+_unitLevelString),3]) call A3EAI_chance) then {
_underbarrelList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "UnderBarrelSlot" >> "compatibleItems");
if !(_underbarrelList isEqualTo []) then {
_underbarrelType = _underbarrelList call A3EAI_selectRandom;
if (_isRifle) then {_unit addPrimaryWeaponItem _underbarrelType} else {_unit addHandGunItem _underbarrelType};
//diag_log format ["DEBUG :: Added underbarrel item %1 to unit %2.",_underbarrelType,_unit];
};
};
_gadgetsArray = missionNamespace getVariable ["A3EAI_gadgetsList"+_unitLevelString,[]];
for "_i" from 0 to ((count _gadgetsArray) - 1) do {
if (((_gadgetsArray select _i) select 1) call A3EAI_chance) then {
_gadget = ((_gadgetsArray select _i) select 0);
_unit addWeapon _gadget;
};
};
//If unit was not given NVGs, give the unit temporary NVGs which will be removed at death.
if (A3EAI_enableTempNVGs && {sunOrMoon < 1}) then {
_unit call A3EAI_addTempNVG;
};
//Give unit temporary first aid kits to allow self-healing (unit level 1+)
if (A3EAI_enableHealing) then {
for "_i" from 1 to (_unitLevel min 3) do {
[_unit,FIRST_AID_ITEM_AI] call A3EAI_addItem;
};
};
_unit setVariable ["loadout",_loadout];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created loadout for unit %1 (unitLevel: %2): %3.",_unit,_unitLevel,_loadout];};
true

View File

@ -0,0 +1,66 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unit", "_unitLevel", "_weaponLoot", "_toolLoot", "_pistol", "_magazine", "_kryptoAmountMax", "_kryptoAmount", "_kryptoPos", "_kryptoDevice", "_toolsArray", "_item" , "_loadout", "_primaryWeapon"];
_unit = _this select 0;
_unitLevel = _this select 1;
if (_unit getVariable ["LootGenerated",false]) exitWith {};
_unit setVariable ["LootGenerated",true];
if !(local _unit) then {
waitUntil {uiSleep 1; local _unit};
};
if (A3EAI_debugLevel > 1) then {diag_log format["A3EAI Debug: Generating loot for AI unit with unitLevel %2.",_unit,_unitLevel];};
_weaponLoot = [];
_toolLoot = [];
_loadout = _unit getVariable ["loadout",[[],[]]];
_primaryWeapon = [_loadout select 0,0,""] call A3EAI_param;
//Generate a pistol if one wasn't assigned with loadout script.
if ((getNumber (configFile >> "CfgWeapons" >> _primaryWeapon >> "type")) != 2) then {
_pistol = A3EAI_pistolList call A3EAI_selectRandom;
_magazine = getArray (configFile >> "CfgWeapons" >> _pistol >> "magazines") select 0;
_unit addMagazine _magazine;
_unit addWeapon _pistol;
if (A3EAI_debugLevel > 1) then {
_weaponLoot pushBack _pistol;
_weaponLoot pushBack _magazine
};
};
//Generate Krypto
_kryptoAmountMax = missionNamespace getVariable ["A3EAI_kryptoAmount"+str(_unitLevel),0];
_kryptoAmount = floor (random (_kryptoAmountMax + 1));
if(_kryptoAmount > 0) then {
_kryptoPos = getPosATL _unit;
_kryptoDevice = createVehicle ["Land_MPS_EPOCH",_kryptoPos,[],1.5,"CAN_COLLIDE"];
_kryptoDevice setVariable ["Crypto",_kryptoAmount,true];
_kryptoDevice setVariable ["A3EAI_kryptoGenTime",diag_tickTime];
A3EAI_kryptoObjects pushBack _kryptoDevice;
_kryptoPosEmpty = _kryptoPos findEmptyPosition [0,0.5,"Land_MPS_EPOCH"];
if !(_kryptoPosEmpty isEqualTo []) then {
_kryptoDevice setPosATL _kryptoPosEmpty;
};
_kryptoDevice setVelocity [0,0,0.25];
if (A3EAI_kryptoPickupAssist > 0) then {
_kryptoPickup = [_kryptoDevice,_kryptoPos] call A3EAI_generateKryptoPickup;
};
};
//Add tool items
_toolsArray = missionNamespace getVariable ["A3EAI_toolsList"+str(_unitLevel),[]];
{
_item = _x select 0;
if (((_x select 1) call A3EAI_chance) && {[_item,"weapon"] call A3EAI_checkClassname}) then {
_unit addWeapon _item;
if (A3EAI_debugLevel > 1) then {
_toolLoot pushBack _item;
};
}
} forEach _toolsArray;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Generated loot for AI death: %1,%2,%3. Krypto: %4.",_weaponLoot,_toolLoot,_kryptoAmount];};

View File

@ -0,0 +1,73 @@
#include "\A3EAI\globaldefines.hpp"
private ["_lootPool", "_groupSize", "_unitType", "_lootUnit", "_unitGroup", "_lootItem"];
_unitGroup = _this;
_lootPool = _unitGroup getVariable ["LootPool",[]];
_groupSize = _unitGroup getVariable ["GroupSize",0];
_unitType = _unitGroup getVariable ["unitType",""];
if (_unitType != "dynamic") then {
for "_j" from 1 to _groupSize do {
//Add first aid kit to loot list
if (A3EAI_firstAidKitChance call A3EAI_chance) then {
_lootPool pushBack FIRST_AID_ITEM_PLAYER;
};
//Add food to loot list
for "_i" from 1 to A3EAI_foodLootCount do {
_lootPool pushBack (A3EAI_foodLoot call A3EAI_selectRandom);
};
//Add items to loot list
for "_i" from 1 to A3EAI_miscLootCount1 do {
_lootPool pushBack (A3EAI_MiscLoot1 call A3EAI_selectRandom);
};
//Add items to loot list
for "_i" from 1 to A3EAI_miscLootCount2 do {
_lootPool pushBack (A3EAI_MiscLoot2 call A3EAI_selectRandom);
};
sleep 0.5;
};
} else {
//Generate loot all at once for dynamic AI
for "_i" from 1 to _groupSize do {
//Add first aid kit to loot list
if (A3EAI_firstAidKitChance call A3EAI_chance) then {
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
[_lootUnit,FIRST_AID_ITEM_PLAYER] call A3EAI_addItem;
};
//Add food to loot list
for "_i" from 1 to A3EAI_foodLootCount do {
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
_lootItem = (A3EAI_foodLoot call A3EAI_selectRandom);
[_lootUnit,_lootItem] call A3EAI_addItem;
};
//Add items to loot list
for "_i" from 1 to A3EAI_miscLootCount1 do {
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
_lootItem = (A3EAI_MiscLoot1 call A3EAI_selectRandom);
[_lootUnit,_lootItem] call A3EAI_addItem;
};
//Add items to loot list
for "_i" from 1 to A3EAI_miscLootCount2 do {
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
_lootItem = (A3EAI_MiscLoot2 call A3EAI_selectRandom);
[_lootUnit,_lootItem] call A3EAI_addItem;
};
sleep 0.5;
};
};
//Update local group loot pool
_unitGroup setVariable ["LootPool",_lootPool];
true

View File

@ -0,0 +1,12 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitType"];
_unitType = _this;
call {
if (_unitType in ["static","staticcustom","vehiclecrew","aircustom","landcustom"]) exitWith {ANTISTUCK_CHECK_TIME_INFANTRY};
if (_unitType in ["air","uav"]) exitWith {ANTISTUCK_CHECK_TIME_AIR};
if (_unitType in ["land","ugv"]) exitWith {ANTISTUCK_CHECK_TIME_LAND};
300
};

View File

@ -0,0 +1,116 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitType", "_fnc_execEveryLoop", "_fnc_checkUnits", "_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck", "_noAggroRange"];
_unitGroup = _this select 0;
_unitType = _this select 1;
call {
if (_unitType isEqualTo "static") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_MAN;
};
if (_unitType isEqualTo "random") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_MAN;
};
if (_unitType isEqualTo "dynamic") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_MAN;
};
if (_unitType isEqualTo "air") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_air;
_fnc_checkUnits = {};
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_air;
_noAggroRange = NO_AGGRO_RANGE_AIR;
};
if (_unitType isEqualTo "land") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_vehicle;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_land;
_noAggroRange = NO_AGGRO_RANGE_LAND;
};
if (_unitType isEqualTo "uav") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_uav;
_fnc_checkUnits = {};
_fnc_generateLoot = {};
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_uav;
_noAggroRange = NO_AGGRO_RANGE_UAV;
};
if (_unitType isEqualTo "ugv") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_ugv;
_fnc_checkUnits = {};
_fnc_generateLoot = {};
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_ugv;
_noAggroRange = NO_AGGRO_RANGE_UGV;
};
if (_unitType isEqualTo "air_reinforce") exitWith {
_fnc_execEveryLoop = {};
_fnc_checkUnits = {};
_fnc_generateLoot = {};
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = {};
_noAggroRange = NO_AGGRO_RANGE_AIR;
};
if (_unitType isEqualTo "vehiclecrew") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_MAN;
};
if (_unitType isEqualTo "staticcustom") exitWith {
_fnc_execEveryLoop = {};
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_MAN;
};
if (_unitType isEqualTo "aircustom") exitWith {
_fnc_execEveryLoop = {};
_fnc_checkUnits = {};
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_aircustom;
_noAggroRange = NO_AGGRO_RANGE_AIR;
};
if (_unitType isEqualTo "landcustom") exitWith {
_fnc_execEveryLoop = A3EAI_execEveryLoop_vehicle;
_fnc_checkUnits = A3EAI_checkGroupUnits;
_fnc_generateLoot = A3EAI_generateGroupLoot;
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
_fnc_antistuck = A3EAI_antistuck_generic;
_noAggroRange = NO_AGGRO_RANGE_LAND;
};
_fnc_execEveryLoop = {};
_fnc_checkUnits = {};
_fnc_generateLoot = {};
_fnc_vehicleAmmoFuelCheck = {};
_fnc_antistuck = {};
_noAggroRange = NO_AGGRO_RANGE_DEFAULT;
diag_log format ["A3EAI Warning: Group functions for unit type %1 not found.",_unitType];
};
[_fnc_execEveryLoop,_fnc_checkUnits,_fnc_generateLoot,_fnc_vehicleAmmoFuelCheck,_fnc_antistuck,_noAggroRange]

View File

@ -0,0 +1,47 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo","_launchersAdded"];
_unitGroup = _this select 0;
_unitType = _this select 1;
_unitLevel = _this select 2;
if !(_unitType in ["uav","ugv"]) then {
_useLaunchers = if !(A3EAI_levelRequiredLauncher isEqualTo -1) then {((count A3EAI_launcherTypes) > 0) && {(_unitLevel >= A3EAI_levelRequiredLauncher)}} else {false};
_maxLaunchers = if (_useLaunchers) then {A3EAI_launchersPerGroup min _unitLevel} else {0};
_launchersAdded = 0;
_unitGroup setVariable ["LootPool",[]];
_unitGroup spawn A3EAI_generateLootPool;
//Set up individual group units
{
_loadout = _x getVariable "loadout";
if (isNil "_loadout") then {
_weapon = primaryWeapon _x;
_magazine = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines") select 0;
_loadout = [[_weapon],[_magazine]];
_x setVariable ["loadout",_loadout];
};
if (_launchersAdded < _maxLaunchers) then {
_launchWeapon = A3EAI_launcherTypes call A3EAI_selectRandom;
_launchAmmo = getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
if (_x canAdd _launchAmmo) then {
_x addMagazine _launchAmmo;
_x addWeapon _launchWeapon;
(_loadout select 1) pushBack _launchAmmo;
(_loadout select 0) pushBack _launchWeapon;
_launchersAdded = _launchersAdded + 1;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Successfully added weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
} else {
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Unable to add weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
};
};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
} forEach (units _unitGroup);
};
true

View File

@ -0,0 +1,27 @@
#include "\A3EAI\globaldefines.hpp"
private ["_currentTime", "_monitorReport", "_getUptime", "_currentSec", "_outHour", "_outMin", "_outSec", "_uptime"];
_currentTime = diag_tickTime;
_monitorReport = _currentTime;
_getUptime = {
private ["_currentSec","_outSec","_outMin","_outHour"];
_currentSec = diag_tickTime;
_outHour = floor (_currentSec/3600);
_outMin = floor ((_currentSec - (_outHour*3600))/60);
_outSec = floor (_currentSec - (_outHour*3600) - (_outMin*60));
[_outHour,_outMin,_outSec]
};
while {true} do {
_currentTime = diag_tickTime;
if ((A3EAI_monitorReportRate > 0) && {((_currentTime - _monitorReport) > A3EAI_monitorReportRate)}) then {
_uptime = [] call _getUptime;
diag_log format ["A3EAI Monitor: Uptime: %1:%2:%3. FPS: %4. HC Groups: %5.",_uptime select 0, _uptime select 1, _uptime select 2,round(diag_fps),A3EAI_HCGroupsCount];
_monitorReport = _currentTime;
};
uiSleep 30;
};

View File

@ -0,0 +1,10 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_targetPlayer"];
_unitGroup = _this select 0;
_targetPlayer = _this select 1;
_unitGroup setVariable ["targetPlayer",_targetPlayer];
true

View File

@ -0,0 +1,65 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_anchor", "_unitType", "_groupSize", "_functionCall", "_check", "_lootPool","_miscData1","_miscData2","_anchorType"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_anchor = _this select 2;
_unitType = _this select 3;
_groupSize = _this select 4;
_lootPool = _this select 5;
_miscData1 = if ((count _this) > 6) then {_this select 6};
_miscData2 = if ((count _this) > 7) then {_this select 7};
call {
_anchorType = (typeName _anchor);
if (_anchorType isEqualTo "ARRAY") exitWith {
_anchor = createTrigger [TRIGGER_OBJECT,_anchor,false];
_unitGroup setVariable ["trigger",_anchor];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created group trigger for %1 group %2.",_unitType,_unitGroup];};
};
if (_anchorType isEqualTo "OBJECT") exitWith {
_unitGroup setVariable ["assignedVehicle",_anchor];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 has assigned vehicle %3 (%4).",_unitType,_unitGroup,_anchor,(typeOf _anchor)];};
};
_anchor = objNull;
};
_unitGroup setVariable ["unitLevel",_unitLevel];
_unitGroup setVariable ["unitType",_unitType];
_unitGroup setVariable ["GroupSize",_groupSize];
_unitGroup call A3EAI_initNoAggroStatus;
if !(_lootPool isEqualTo []) then {_unitGroup setVariable ["LootPool",_lootPool];};
if !(isNil "_miscData1") then {
call {
if (_unitType isEqualTo "dynamic") exitWith {
_unitGroup setVariable ["targetplayer",_miscData1];
_anchor setVariable ["targetplayer",_miscData1];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 has target player %3.",_unitType,_unitGroup,_miscData1];};
};
};
};
if (!isNil "_miscData2") then {
};
_functionCall = missionNamespace getVariable ["A3EAI_handle"+_unitType,{false}];
_check = _unitGroup call _functionCall;
if (A3EAI_debugLevel > 0) then {
if (_check) then {
diag_log format ["A3EAI Debug: HC received new group from server: %1. Processing new group with function %2.",_unitGroup,("A3EAI_handle"+_unitType)];
} else {
diag_log format ["A3EAI Debug: Function %1 not found.","A3EAI_handle"+_unitType]
};
};
0 = [_unitGroup,_unitLevel] spawn A3EAI_addGroupManager;
A3EAI_HCGroupsCount = A3EAI_HCGroupsCount + 1;
true

View File

@ -0,0 +1,28 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_unitType", "_groupSize", "_vehicle"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Waiting for reinforcement group %1 ready state.",_unitGroup];};
waitUntil {uiSleep 10; diag_log format ["Debug: Group %1 behavior is %2, combat mode %3.",_unitGroup,(behaviour (leader _unitGroup)),(combatMode _unitGroup)]; !((behaviour (leader _unitGroup)) isEqualTo "CARELESS")};
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 has now entered ready state.",_unitGroup];};
while {((behaviour (leader _unitGroup)) in ["AWARE","COMBAT"]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
if (local _unitGroup) then {
_vehiclePos = getPosATL _vehicle;
_vehiclePos set [2,0];
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],250];
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
{
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3}) then {
_unitGroup reveal [_x,3];
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
};
};
} forEach _nearUnits;
};
uiSleep 15;
};

View File

@ -0,0 +1,13 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetIn","GetOut","Fired","Local","Hit"];
_unitGroup setVariable ["GroupSize",-1];
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Releasing ownership of reinforcement group %1 to server.",_unitGroup];};
true

View File

@ -0,0 +1,12 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_trigger","_triggerPos"];
_unitGroup = _this select 0;
_triggerPos = _this select 1;
_trigger = createTrigger [TRIGGER_OBJECT,_triggerPos,false];
_unitGroup setVariable ["trigger",_trigger];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created group trigger object for %1 at %2.",_unitGroup,_triggerPos];};
_trigger

View File

@ -0,0 +1,24 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addVehAirEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
true

View File

@ -0,0 +1,26 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addVehAirEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
[_unitGroup,_vehicle] spawn A3EAI_airReinforcementDetection;
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
true

View File

@ -0,0 +1,24 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addVehAirEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
true

View File

@ -0,0 +1,20 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_unitGroup call A3EAI_requestGroupVars;
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
true

View File

@ -0,0 +1,25 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_vehicle = assignedVehicle (leader _unitGroup);
_unitGroup setVariable ["assignedVehicle",_vehicle];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addLandVehEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
true

View File

@ -0,0 +1,25 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_vehicle = assignedVehicle (leader _unitGroup);
_unitGroup setVariable ["assignedVehicle",_vehicle];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addLandVehEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
true

View File

@ -0,0 +1,20 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_unitGroup call A3EAI_requestGroupVars;
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
true

View File

@ -0,0 +1,20 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUnitEH;
} forEach (units _unitGroup);
_unitGroup call A3EAI_requestGroupVars;
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
true

View File

@ -0,0 +1 @@
#include "A3EAI_handlestatic.sqf"

View File

@ -0,0 +1,24 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUVUnitEH;
} forEach (units _unitGroup);
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addUAVEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
true

View File

@ -0,0 +1,25 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
_unitGroup = _this;
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
//_trigger = _unitGroup getVariable ["trigger",objNull];
//_unitType = _unitGroup getVariable ["unitType","unknown"];
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
{
_x call A3EAI_addUVUnitEH;
} forEach (units _unitGroup);
_vehicle = assignedVehicle (leader _unitGroup);
_unitGroup setVariable ["assignedVehicle",_vehicle];
(assignedDriver _vehicle) setVariable ["isDriver",true];
_vehicle call A3EAI_addUGVEH;
_vehicle call A3EAI_secureVehicle;
_vehicle setVariable ["unitGroup",_unitGroup];
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
true

View File

@ -0,0 +1 @@
#include "A3EAI_handlestatic.sqf"

View File

@ -0,0 +1,3 @@
A3EAI_getGroupTriggerVars_PVS = _this;
publicVariableServer "A3EAI_getGroupTriggerVars_PVS";
true

View File

@ -0,0 +1,18 @@
private ["_unitGroup","_mode"];
_unitGroup = _this select 0;
_mode = _this select 1;
call {
if (_mode isEqualTo 0) exitWith {
_unitGroup setBehaviour "CARELESS";
{_x doWatch objNull} forEach (units _unitGroup);
_unitGroup setVariable ["EnemiesIgnored",true];
true
};
if (_mode isEqualTo 1) exitWith {
_unitGroup setBehaviour "AWARE";
_unitGroup setVariable ["EnemiesIgnored",false];
true
};
false
};

View File

@ -0,0 +1,5 @@
private ["_unitGroup","_waypointIndex"];
_unitGroup = _this select 0;
_waypointIndex = _this select 1;
_unitGroup setCurrentWaypoint [_unitGroup,_waypointIndex];
true

View File

@ -0,0 +1,35 @@
#include "\A3EAI\globaldefines.hpp"
private ["_arrayData", "_unitGroup", "_trigger"];
_arrayData = _this;
_unitGroup = _arrayData select 0;
/*
if !(local _unitGroup) then {
diag_log format ["Debug: Server sent group trigger variables for remote group %1.",_unitGroup];
};
*/
_trigger = _unitGroup getVariable "trigger";
if (isNil "_trigger") exitWith {diag_log format ["A3EAI Error: Group %1 has undefined trigger.",_unitGroup];};
//Remove array headers (Group reference)
_arrayData deleteAt 0;
{
_trigger setVariable [_x,_arrayData select _forEachIndex];
//diag_log format ["Debug: Group %1 variable %2 has value %3.",_unitGroup,_x,_arrayData select _forEachIndex];
} forEach [
"GroupArray",
"patrolDist",
"unitLevel",
"unitLevelEffective",
"maxUnits",
"spawnChance",
"spawnType",
"respawn",
"permadelete"
];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set group trigger variables for group %1. Success check: %2.",_unitGroup,_trigger isKindOf TRIGGER_OBJECT];};

View File

@ -0,0 +1,61 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo", "_useGL"];
_unitGroup = _this select 0;
_unitType = _this select 1;
_unitLevel = _this select 2;
if !(_unitType in ["uav","ugv"]) then {
_useGL = if !(A3EAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3EAI_levelRequiredGL} else {false};
{
_x setVariable ["loadout",[[],[]]];
_loadout = _x getVariable "loadout";
_primaryWeapon = primaryWeapon _x;
_secondaryWeapon = secondaryWeapon _x;
_handgunWeapon = handgunWeapon _x;
if !(_primaryWeapon isEqualTo "") then {
(_loadout select 0) pushBack _primaryWeapon;
_primaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "magazines") select 0;
(_loadout select 1) pushBack _primaryWeaponMagazine;
} else {
if !(_handgunWeapon isEqualTo "") then {
(_loadout select 0) pushBack _handgunWeapon;
_handgunWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _handgunWeapon >> "magazines") select 0;
(_loadout select 1) pushBack _handgunWeaponMagazine;
};
};
if !(_secondaryWeapon isEqualTo "") then {
(_loadout select 0) pushBack _secondaryWeapon;
_secondaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _secondaryWeapon >> "magazines") select 0;
(_loadout select 1) pushBack _secondaryWeaponMagazine;
};
if ((getNumber (configFile >> "CfgMagazines" >> ((_loadout select 1) select 0) >> "count")) < 6) then {_x setVariable ["extraMag",true]};
if (_useGL) then {
_weaponMuzzles = getArray(configFile >> "cfgWeapons" >> ((_loadout select 0) select 0) >> "muzzles");
if ((count _weaponMuzzles) > 1) then {
_GLWeapon = _weaponMuzzles select 1;
_GLMagazines = (getArray (configFile >> "CfgWeapons" >> ((_loadout select 0) select 0) >> _GLWeapon >> "magazines"));
if (GRENADE_AMMO_3RND in _GLMagazines) then {
(_loadout select 0) pushBack _GLWeapon;
(_loadout select 1) pushBack GRENADE_AMMO_3RND;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
} else {
if (GRENADE_AMMO_1RND in _GLMagazines) then {
(_loadout select 0) pushBack _GLWeapon;
(_loadout select 1) pushBack GRENADE_AMMO_1RND;
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
}
};
};
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
} forEach (units _unitGroup);
};
true

View File

@ -0,0 +1,9 @@
private ["_unitGroup","_lootPool"];
_unitGroup = _this select 0;
_lootPool = _this select 1;
_unitGroup setVariable ["LootPool",_lootPool];
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Updated group %1 loot pool to %2.",_unitGroup,_lootPool];};
true

View File

@ -0,0 +1,10 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_groupSize"];
_unitGroup = _this select 0;
_groupSize = _this select 1;
_unitGroup setVariable ["GroupSize",_groupSize];
true

View File

@ -0,0 +1,3 @@
A3EAI_updateGroupLoot_PVS = _this;
publicVariableServer "A3EAI_updateGroupLoot_PVS";
true

View File

@ -0,0 +1,8 @@
private ["_unitGroup","_status"];
_unitGroup = _this select 0;
_status = _this select 1;
_unitGroup setVariable ["NoAggroStatus",_status];
true

View File

@ -0,0 +1,49 @@
#include "\A3EAI\globaldefines.hpp"
private ["_HCObject","_versionHC","_compatibleVersions","_positionHC","_useRemoteConfigs"];
_HCObject = _this select 0;
_versionHC = _this select 1;
_useRemoteConfigs = _this select 2;
A3EAI_HC_serverResponse = false;
if (((owner A3EAI_HCObject) isEqualTo 0) && {(typeOf _HCObject) isEqualTo "HeadlessClient_F"}) then {
_compatibleVersions = [configFile >> "CfgPatches" >> "A3EAI","compatibleHCVersions",[]] call BIS_fnc_returnConfigEntry;
if (_versionHC in _compatibleVersions) then {
A3EAI_HCObject = _HCObject;
A3EAI_HCObject allowDamage false;
A3EAI_HCObject enableSimulationGlobal false;
A3EAI_HCObject addEventHandler ["Local",{
if (_this select 1) then {
private["_unit","_unitGroup"];
A3EAI_HCIsConnected = false;
A3EAI_HCObjectOwnerID = 0;
A3EAI_HCObject = objNull;
_unit = _this select 0;
_unitGroup = (group _unit);
_unit removeAllEventHandlers "Local";
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Deleting disconnected headless client unit %1.",typeOf _unit];};
deleteVehicle _unit;
deleteGroup _unitGroup;
};
}];
A3EAI_HCObjectOwnerID = (owner A3EAI_HCObject);
A3EAI_HCIsConnected = true;
A3EAI_HC_serverResponse = if (_useRemoteConfigs) then {
A3EAI_pushedHCVariables
} else {
true
};
_positionHC = getPosATL A3EAI_HCObject;
if (({if (_positionHC in _x) exitWith {1}} count (nearestLocations [_positionHC,[BLACKLIST_OBJECT_GENERAL],BLACKLIST_AREA_HC_SIZE])) isEqualTo 0) then {
[_positionHC,TEMP_BLACKLIST_AREA_HC_SIZE] call A3EAI_createBlackListArea;
diag_log format ["[A3EAI] Created 750m radius blacklist area at HC position %1",_positionHC];
};
diag_log format ["[A3EAI] Headless client %1 (owner: %2) logged in successfully.",A3EAI_HCObject,A3EAI_HCObjectOwnerID];
} else {
diag_log format ["[A3EAI] Headless client %1 (owner: %2) has wrong A3EAI version %3 (Compatible versions: %4).",_HCObject,owner _HCObject,_versionHC,_compatibleVersions];
};
} else {
diag_log format ["[A3EAI] Rejecting connection from HC %1. A headless client is already connected: %2. Client object type: %3.",(_this select 1),!((owner A3EAI_HCObject) isEqualTo 0),typeOf _HCObject];
};
(owner _HCObject) publicVariableClient "A3EAI_HC_serverResponse";

View File

@ -0,0 +1,27 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_trigger", "_triggerVars", "_value"];
_unitGroup = _this;
_trigger = _unitGroup getVariable ["trigger",A3EAI_defaultTrigger];
_triggerVars = [_unitGroup];
{
_value = _trigger getVariable [_x select 0,_x select 1];
_triggerVars pushBack _value;
} forEach [
["GroupArray",[]],
["patrolDist",100],
["unitLevel",1],
["unitLevelEffective",1],
["maxUnits",[0,0]],
["spawnChance",0],
["spawnType",""],
["respawn",true],
["permadelete",false]
];
A3EAI_sendGroupTriggerVars_PVC = _triggerVars;
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_sendGroupTriggerVars_PVC";
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Retrieved group %1 trigger variables: %2",_unitGroup,_triggerVars];};

View File

@ -0,0 +1,5 @@
private ["_unitGroup","_dummy"];
_unitGroup = _this select 0;
_dummy = _this select 1;
_unitGroup setVariable ["dummyUnit",_dummy];
true

View File

@ -0,0 +1,22 @@
#include "\A3EAI\globaldefines.hpp"
private ["_victim", "_killer", "_unitGroup", "_unitLevel","_groupSize","_newGroupSize"];
_victim = _this select 0;
_killer = _this select 1;
_unitGroup = _this select 2;
_victim setVariable ["A3EAI_deathTime",diag_tickTime];
_unitLevel = (_unitGroup getVariable ["unitLevel",0]);
_groupSize = (_unitGroup getVariable ["GroupSize",0]);
if (_groupSize > 0) then {
_newGroupSize = (_groupSize - 1);
_unitGroup setVariable ["GroupSize",_newGroupSize];
};
if ((_unitGroup getVariable ["ReinforceAvailable",false]) && {isPlayer _killer} && {(missionNamespace getVariable [format ["A3EAI_airReinforcementSpawnChance%1",_unitLevel],0]) call A3EAI_chance}) then {
_unitGroup setVariable ["ReinforceAvailable",false];
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 (Level %2) is calling reinforcements.",_unitGroup,_unitLevel];};
_nul = [(getPosATL _victim),_killer,_unitLevel] spawn A3EAI_spawn_reinforcement;
};

View File

@ -0,0 +1,18 @@
private ["_unitGroup","_mode"];
_unitGroup = _this select 0;
_mode = _this select 1;
call {
if (_mode isEqualTo 0) exitWith {
_unitGroup setBehaviour "CARELESS";
{_x doWatch objNull} forEach (units _unitGroup);
_unitGroup setVariable ["EnemiesIgnored",true];
true
};
if (_mode isEqualTo 1) exitWith {
_unitGroup setBehaviour "AWARE";
_unitGroup setVariable ["EnemiesIgnored",false];
true
};
false
};

View File

@ -0,0 +1,36 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_lootPool","_miscData","_miscData2","_groupData""_result","_vehicle"];
_unitGroup = _this;
if ((diag_tickTime - A3EAI_lastGroupTransfer) < 5) exitWith {false};
A3EAI_lastGroupTransfer = diag_tickTime;
/*
if (A3EAI_debugLevel > 1) then {
diag_log format ["%1 variables: %2",_unitGroup,(allVariables _unitGroup)];
};
*/
_unitLevel = _unitGroup getVariable ["unitLevel",0];
_trigger = _unitGroup getVariable ["trigger",nil];
_unitType = _unitGroup getVariable ["unitType","unknown"];
_groupSize = _unitGroup getVariable ["GroupSize",nil];
_lootPool = _unitGroup getVariable ["LootPool",[]];
_miscData = _unitGroup getVariable ["MiscData",nil];
_miscData2 = _unitGroup getVariable ["MiscData2",nil];
_vehicle = _unitGroup getVariable ["assignedVehicle",nil];
_groupData = [_unitGroup,_unitLevel,nil,_unitType,_groupSize,_lootPool];
if (!isNil "_trigger") then {_groupData set [2,(getPosATL _trigger)];};
if (!isNil "_vehicle") then {_groupData set [2,_vehicle];};
if (!isNil "_miscData") then {_groupData set [6,_miscData];};
if (!isNil "_miscData2") then {_groupData set [7,_miscData2];};
A3EAI_transferGroup_PVC = _groupData;
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_transferGroup_PVC";
_result = _unitGroup setGroupOwner A3EAI_HCObjectOwnerID;
_result

View File

@ -0,0 +1,7 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup"];
_unitGroup = _this;
_unitGroup setGroupOwner 2;
true

View File

@ -0,0 +1,11 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_targetPlayer"];
_unitGroup = _this select 0;
_targetPlayer = _this select 1;
A3EAI_sendHunterGroupHC = [_unitGroup,_targetPlayer];
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_sendHunterGroupHC";
true

View File

@ -0,0 +1,10 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_lootPool","_lootIndex"];
_unitGroup = _this select 0;
_lootIndex = _this select 1;
_lootPool = _unitGroup getVariable ["LootPool",[]];
_lootPool deleteAt _lootIndex;
true

View File

@ -0,0 +1,10 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unitGroup","_groupSize"];
_unitGroup = _this select 0;
_groupSize = _this select 1;
_unitGroup setVariable ["GroupSize",_groupSize];
true

View File

@ -0,0 +1,21 @@
#include "\A3EAI\globaldefines.hpp"
private ["_vehicle","_unitGroup","_unitLevel"];
_vehicle = (_this select 0);
if (isNull _vehicle) exitWith {};
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
_vehicle setVariable ["vehicle_disabled",true];
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetOut","Fired","Local","Hit"];
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
_vehicle call A3EAI_respawnAIVehicle;
if !(isNil {_unitGroup getVariable "dummyUnit"}) exitWith {};
_unitGroup setVariable ["GroupSize",-1];
if !(isDedicated) then {
A3EAI_updateGroupSize_PVS = [_unitGroup,-1];
publicVariableServer "A3EAI_updateGroupSize_PVS";
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 %2 destroyed at %3",_unitGroup,(typeOf _vehicle),mapGridPosition _vehicle];};

View File

@ -0,0 +1,21 @@
#include "\A3EAI\globaldefines.hpp"
private ["_vehicle","_unitGroup","_unitsAlive"];
_vehicle = (_this select 0);
if (isNull _vehicle) exitWith {};
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
_vehicle setVariable ["vehicle_disabled",true];
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetOut","Fired","Local","Hit"];
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
_vehicle call A3EAI_respawnAIVehicle;
if !(isNil {_unitGroup getVariable "dummyUnit"}) exitWith {};
_unitGroup setVariable ["GroupSize",-1];
if !(isDedicated) then {
A3EAI_updateGroupSize_PVS = [_unitGroup,-1];
publicVariableServer "A3EAI_updateGroupSize_PVS";
};
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 %2 destroyed at %3",_unitGroup,(typeOf _vehicle),mapGridPosition _vehicle];};

View File

@ -0,0 +1,13 @@
#include "\A3EAI\globaldefines.hpp"
private ["_unit","_unitPos","_parachute"];
_unit = _this;
_unitPos = getPosATL _unit;
_parachute = createVehicle [PARACHUTE_OBJECT, _unitPos, [], (-10 + (random 10)), "FLY"];
unassignVehicle _unit;
_unit setPosATL _unitPos;
_unit moveInDriver _parachute;
_parachute

View File

@ -0,0 +1,77 @@
#include "\A3EAI\globaldefines.hpp"
private["_object","_hit","_damage","_source","_ammo","_partdamage","_durability","_unitGroup","_currentDamage","_hitPoint"];
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
_source = _this select 3; //The source unit that caused the damage.
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
_hitPoint = (_object getHitIndex _hitPartIndex);
if (_damage > _hitPoint) then {
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
if ((group _object) call A3EAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
_durability = _object getVariable "durability";
if (isNil "_durability") then {
_object setVariable ["durability",[0,0,0,0]];
_durability = _object getVariable "durability";
};
if ((side _source) != AI_GROUP_SIDE) then {
_destroyed = false;
_disabled = false;
call {
if (_hit isEqualTo "hull_hit") exitWith {
//Structural damage
_currentDamage = (_durability select 0);
_partdamage = _currentDamage + (_damage - _currentDamage);
_durability set [0,_partdamage];
if ((_partdamage > 0.9) && {alive _object}) then {
_damage = _hitPoint;
_destroyed = true;
_disabled = true;
};
};
if (_hit in ["engine_hit","engine_1_hit","engine_2_hit","engine_3_hit","engine_4_hit"]) exitWith {
_currentDamage = (_durability select 1);
_partdamage =_currentDamage + (_damage - _currentDamage);
_durability set [1,_partdamage];
if ((_partdamage > 0.9) && {alive _object}) then {
_damage = _hitPoint;
_destroyed = true;
_disabled = true;
};
};
if (_hit in ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"]) exitWith {
_currentDamage = (_durability select 2);
_partdamage = _currentDamage + (_damage - _currentDamage);
_durability set [2,_partdamage];
if ((_partdamage > 0.9)&& {alive _object}) then {
{
_object setHit [_x,1];
} forEach ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"];
_destroyed = false;
_disabled = true;
};
};
if (_hit isEqualTo "fuel_hit") exitWith {_damage = _hitPoint;};
};
if (_disabled) then {
0 = [_object] call A3EAI_heliEvacuated;
//{_object removeAllEventHandlers _x} forEach ["HandleDamage","GetOut","Killed","Hit"];
if (_destroyed) then {
_nul = _object spawn {
uiSleep 3;
_this setVehicleAmmo 0;
_this setFuel 0;
_this setDamage 1;
};
};
};
};
};
_damage

View File

@ -0,0 +1,22 @@
#include "\A3EAI\globaldefines.hpp"
private["_object","_hit","_damage","_source","_ammo","_hitPoint"];
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
_source = _this select 3; //The source unit that caused the damage.
//_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
_hitPoint = (_object getHitIndex _hitPartIndex);
if (_damage > _hitPoint) then {
call {
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
if ((group _object) call A3EAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
if !(isPlayer _source) exitWith {_damage = _hitPoint;};
if ((_hit find "wheel") > -1) exitWith {_damage = _hitPoint;};
};
};
_damage

Some files were not shown because too many files have changed in this diff Show More