A3XAI Final Release (April 17, 2016 version)

Releasing previously unreleased version. Completely unsupported with no guarantee of functionality. Use at own risk.
This commit is contained in:
Snark Industries 2017-07-19 21:20:00 -04:00
parent 7abaffe24e
commit c4a7084754
277 changed files with 13461 additions and 1 deletions

1
A3XAI/$PREFIX$ Normal file
View File

@ -0,0 +1 @@
A3XAI

1
A3XAI/PboPrefix.txt Normal file
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 A3XAI_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 A3XAI_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 A3XAI_SHK_pos_fnc_isSamePosition) then {
_return = true;
};
// Markers that have an area.
} else {
if (_shape in ["RECTANGLE","SQUARE"]) then {
private ["_corners"];
_corners = _area call A3XAI_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 A3XAI_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 A3XAI_SHK_pos_fnc_isInRectangle;
} else {
if (_shape == "CIRCLE") then {
_return = [_pos,_area] call A3XAI_SHK_pos_fnc_isInCircle;
} else {
_return = [_pos,_area] call A3XAI_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 A3XAI_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 A3XAI_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 A3XAI_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 A3XAI_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 A3XAI_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 A3XAI_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 A3XAI_SHK_pos_fnc_getPosFromRectangle;
} else {
_pos = _area call A3XAI_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 A3XAI_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\A3XAI_SHK_pos_init.sqf";
Actually getting the position:
pos = [parameters] call A3XAI_SHK_pos;
*/
// Functions
A3XAI_SHK_pos_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_getpos.sqf",A3XAI_directory];
A3XAI_SHK_pos_getPosMarker = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_getposmarker.sqf",A3XAI_directory];
// Sub functions
A3XAI_SHK_pos_fnc_findClosestPosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_findclosestposition.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getMarkerCorners = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getmarkercorners.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getMarkerShape = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getmarkershape.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getpos.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getPosFromCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getposfromcircle.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getPosFromEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getposfromellipse.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getPosFromRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getposfromrectangle.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_getPosFromSquare = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_getposfromsquare.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_isBlacklisted = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_isblacklisted.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_isInCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_isincircle.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_isInEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_isinellipse.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_isInRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_isinrectangle.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_isSamePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_issameposition.sqf",A3XAI_directory];
A3XAI_SHK_pos_fnc_rotatePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3XAI_SHK_pos_fnc_rotateposition.sqf",A3XAI_directory];
// Wrapper function
// Decide which function to call based on parameters.
A3XAI_SHK_pos = {
private ["_pos"];
_pos = [];
// Only marker is given as parameter
if (typename _this isEqualTo "STRING") then {
_pos = [_this] call A3XAI_SHK_pos_getPosMarker;
// Parameter array
} else {
if (typename (_this select 0) isEqualTo "STRING") then {
_pos = _this call A3XAI_SHK_pos_getPosMarker;
} else {
_pos = _this call A3XAI_SHK_pos_getPos;
};
};
// Return position
_pos
};

View File

@ -0,0 +1,262 @@
#include "\A3XAI\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 A3XAI (https://github.com/dayzai/A3XAI)
=======================================================================================================================
*/
_unitGroup = _this select 0;
_pos = _this select 1;
_max_dist = [_this,2,100] call A3XAI_param;
_speedMode = [_this,3,"LIMITED"] call A3XAI_param;
_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));
_trigger = _unitGroup getVariable ["trigger",objNull];
if !(isNull _trigger) then {
_locationArray = _trigger getVariable ["locationArray",[]];
if (_locationArray isEqualTo []) then {
_trigger = objNull;
};
};
// 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 A3XAI_chance) then {_nul = [group this] call A3XAI_setRandomWaypoint;} else {_nul = [group this] spawn A3XAI_areaSearching;};",_randomizeChance]};
if (_unitType isEqualTo "aircustom") exitWith {format ["if !(local this) exitWith {}; if (%1 call A3XAI_chance) then {_nul = [group this] call A3XAI_setRandomWaypoint;} else {_nul = [(assignedVehicle this),(group this)] spawn A3XAI_customHeliDetect;};",_randomizeChance]};
format ["if !(local this) exitWith {}; if (%1 call A3XAI_chance) then {_nul = [group this] call A3XAI_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;};
_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 {(50 + _slack)} else {(25 + _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}) then {
_retry = true;
_retryCount = 0;
_retryPos = [];
_newMaxDist = _max_dist;
while {_retry && {_retryCount < 3}} 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}) then {
_retry = false;
_wp_pos = _retryPos;
};
};
};
if !(_retry) then {
_a = 0 + (_wp_pos select 0);
_b = 0 + (_wp_pos select 1);
call {
if (_searchLoot) exitWith {
//////////////////////////////////////////////////////////////////
// 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 !(_bldgpos isEqualTo []) then {
_wp_pos = _bldgpos call A3XAI_selectRandom;
};
};
if (_isVehicle) exitWith {
_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 pushBack _wp_pos;
} else {
if !(isNull _trigger) then {
_wp_pos = getPosATL ((_trigger getVariable ["locationArray",[_pos]]) call A3XAI_selectRandom);
if ((_wp_pos distance2D [0,0]) > 0) then {
_wp_array pushBack _wp_pos;
} else {
_wp_array pushBack _pos;
};
} else {
_wp_array pushBack _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;
_wp setWaypointSpeed _speedMode;
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;
_wp1 setWaypointSpeed _speedMode;
[_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;
_wp2 setWaypointSpeed _speedMode;
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
if (((getWPPos [_unitGroup,_i]) distance2D [0,0]) isEqualTo 0) then {
diag_log format ["A3XAI Error: Waypoint %1 is invalid position.",[_unitGroup,_i]];
// deleteWaypoint [_unitGroup,_i];
[_unitGroup,_i] setWaypointPosition _pos;
};
};
if (A3XAI_enableHC && {_unitType in A3XAI_HCAllowedTypes}) then {_unitGroup setVariable ["HC_Ready",true];};
true

View File

@ -0,0 +1,67 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup","_canCall","_vehicle","_detectStartPos"];
_unitGroup = _this select 0;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Default"] call A3XAI_forceBehavior};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_canCall = true;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection started.",_unitGroup,(typeOf (_vehicle))];};
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3XAI_UAVCallReinforceCooldown])) > A3XAI_UAVCallReinforceCooldown) then {
_detectStartPos = getPosATL _vehicle;
_vehicle flyInHeight (FLYINHEIGHT_UAV_SEARCHING_BASE + (random FLYINHEIGHT_UAV_SEARCHING_VARIANCE));
_unitGroup setVariable ["IsDetecting",true];
while {!(_vehicle getVariable ["VehicleDisabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
_vehPos = getPosATL _vehicle;
_canReveal = ((combatMode _unitGroup) in ["YELLOW","RED"]);
_detected = (getPosATL _vehicle) nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UAV];
{
if !(isPlayer _x) then {
_detected deleteAt _forEachIndex;
};
if (_forEachIndex > 4) exitWith {};
} forEach _detected;
_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 []) && {A3XAI_UAVDetectChance call A3XAI_chance}) then {
if (_canCall) then {
if (isDedicated) then {
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3XAI_spawn_reinforcement;
} else {
A3XAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
publicVariableServer "A3XAI_spawnReinforcements_PVS";
};
_unitGroup setVariable ["UVLastCall",diag_tickTime];
_canCall = false;
};
if !(isNull (objectParent _x)) then { //Reveal vehicles
_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 A3XAI_radioSend;
};
};
};
};
uiSleep 0.1;
} forEach _detected;
if (((_vehicle distance2D _detectStartPos) > DETECT_LENGTH_UAV_2D) or {_vehicle getVariable ["VehicleDisabled",false]}) exitWith {};
uiSleep 15;
};
_vehicle flyInHeight (FLYINHEIGHT_UAV_PATROLLING_BASE + (random FLYINHEIGHT_UAV_PATROLLING_VARIANCE));
};
_unitGroup setVariable ["IsDetecting",false];
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};

View File

@ -0,0 +1,28 @@
#include "\A3XAI\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 = (A3XAI_locationsAir call A3XAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _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 A3XAI_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 A3XAI_SHK_pos;
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
true

View File

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

View File

@ -0,0 +1,66 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup","_vehicle","_canCall"];
_unitGroup = _this select 0;
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Default"] call A3XAI_forceBehavior};
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_canCall = true;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection start.",_unitGroup,(typeOf (_vehicle))];};
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3XAI_UGVCallReinforceCooldown])) > A3XAI_UGVCallReinforceCooldown) then {
_detectStartPos = getPosATL _vehicle;
_unitGroup setVariable ["IsDetecting",true];
while {!(_vehicle getVariable ["VehicleDisabled",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) in ["YELLOW","RED"]);
_detectOrigin = [_startPos,0,getDir _vehicle,1] call A3XAI_SHK_pos;
_detected = _detectOrigin nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UGV];
{
if !(isPlayer _x) then {
_detected deleteAt _forEachIndex;
};
if (_forEachIndex > 4) exitWith {};
} forEach _detected;
_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 []) && {A3XAI_UGVDetectChance call A3XAI_chance}) then {
if (_canCall) then {
if (isDedicated) then {
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3XAI_spawn_reinforcement;
} else {
A3XAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
publicVariableServer "A3XAI_spawnReinforcements_PVS";
};
_unitGroup setVariable ["UVLastCall",diag_tickTime];
_canCall = false;
};
if (isNull (objectParent _x)) then { //Reveal infantry
_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 A3XAI_radioSend;
};
};
};
};
uiSleep 0.1;
} forEach _detected;
if (((_vehicle distance2D _detectStartPos) > DETECT_LENGTH_UGV_2D) or {_vehicle getVariable ["VehicleDisabled",false]}) exitWith {};
uiSleep 15;
};
};
_unitGroup setVariable ["IsDetecting",false];
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};

View File

@ -0,0 +1,23 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup","_tooClose","_locationSelected"];
_unitGroup = _this select 0;
_tooClose = true;
_locationSelected = [0,0,0];
while {_tooClose} do {
_locationSelected = (A3XAI_locationsLand call A3XAI_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 A3XAI_SHK_pos;
[_unitGroup,0] setWPPos _locationSelected;
[_unitGroup,1] setWPPos _locationSelected;
[_unitGroup,2] setWaypointPosition [_locationSelected,0];
true

View File

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

View File

@ -0,0 +1,172 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_unitType", "_vehicle", "_stuckCheckTime", "_groupLeadMarker", "_groupWPMarker", "_currentTime", "_managerStartTime", "_updateServerLoot",
"_pullRate", "_unitPos", "_unitMarker", "_result", "_groupVariables", "_assignedVehicle"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
scopeName "GroupManagerScope";
if (_unitGroup getVariable ["isManaged",false]) exitWith {};
_unitGroup setVariable ["isManaged",true];
_unitType = (_unitGroup getVariable ["unitType",""]);
_vehicle = objNull;
if (_unitType in ["air","land","aircustom","landcustom","air_reinforce","uav","ugv"]) then {
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
} else {
call {
_assignedVehicle = (assignedVehicle (leader _unitGroup));
if (isNull _vehicle) exitWith {};
if (_vehicle isKindOf "ParachuteBase") exitWith {};
if (_vehicle isKindOf "StaticWeapon") exitWith {};
_unitGroup setVariable ["assignedVehicle",_assignedVehicle];
_vehicle = _assignedVehicle;
};
};
if (isNil {_unitGroup getVariable "antistuckPos"}) then {_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];};
if (isNil {_unitGroup getVariable "GroupSize"}) then {_unitGroup setVariable ["GroupSize",(count (units _unitGroup))]};
_stuckCheckTime = _unitType call A3XAI_getAntistuckTime;
//set up debug variables
_groupLeadMarker = format ["%1_Lead",_unitGroup];
_groupWPMarker = format ["%1_WP",_unitGroup];
//Get group variables
_groupVariables = _unitGroup getVariable "GroupVariables";
if (isNil "_groupVariables") then {
_unitGroup setVariable ["GroupVariables",[]];
_groupVariables = _unitGroup getVariable "GroupVariables";
_groupVariables = [_unitGroup,_unitType] call A3XAI_setUnitType;
_unitGroup setVariable ["GroupVariables",_groupVariables];
if (A3XAI_debugLevel > 0) then {
diag_log format ["A3XAI Debug: Group %1 variables not found. Setting them now.",_unitGroup];
};
} else {
if (A3XAI_debugLevel > 0) then {
diag_log format ["A3XAI Debug: Group %1 variables check passed.",_unitGroup];
};
};
//Set up timer variables
_currentTime = diag_tickTime;
_managerStartTime = _currentTime;
if (isNil {_unitGroup getVariable "lastRearmTime"}) then {_unitGroup setVariable ["lastRearmTime",_currentTime];};
if (isNil {_unitGroup getVariable "antistuckTime"}) then {_unitGroup setVariable ["antistuckTime",_currentTime];};
if (isNil {_unitGroup getVariable "lootGenTime"}) then {_unitGroup setVariable ["lootGenTime",_currentTime];};
//Setup loot variables
_updateServerLoot = (A3XAI_enableHC && {!isDedicated});
_pullRate = 30;
if (isDedicated) then {
[_unitGroup,_unitType,_unitLevel] call A3XAI_setLoadoutVariables;
} else {
waitUntil {uiSleep 0.25; (local _unitGroup)};
[_unitGroup,_unitType,_unitLevel] call A3XAI_setLoadoutVariables_HC;
};
if (A3XAI_groupManageMode isEqualTo 1) exitWith {
[_unitGroup, _vehicle, _groupVariables, _unitLevel] call A3XAI_addGroupManangerGlobal;
};
//Main loop
while {(!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
//Every-loop check
[_unitGroup,_vehicle] call (_groupVariables select 0);
//Check units
[_unitGroup] call (_groupVariables select 1);
//Generate loot
if ((diag_tickTime - (_unitGroup getVariable ["lootGenTime",diag_tickTime])) > _pullRate) then {
[_unitGroup,_unitLevel] call (_groupVariables select 2);
};
//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 (_groupVariables select 3);
};
//Antistuck
if ((diag_tickTime - (_unitGroup getVariable ["antistuckTime",diag_tickTime])) > (_groupVariables select 5)) then {
[_unitGroup,_vehicle,(_groupVariables select 5)] call (_groupVariables select 4);
};
if (A3XAI_HCIsConnected && {_unitGroup getVariable ["HC_Ready",false]} && {(diag_tickTime - _managerStartTime) > 30}) then {
private ["_result"];
_result = _unitGroup call A3XAI_transferGroupToHC;
if (_result) then {
waitUntil {sleep 1.5; (!(local _unitGroup) or {isNull _unitGroup})};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Transferred ownership of %1 group %2 to HC %3.",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup,A3XAI_HCObjectOwnerID];};
//breakOut "GroupManagerScope"; //To-do add "Local" EH to group units first!
waitUntil {sleep 15; ((local _unitGroup) or {isNull _unitGroup})};
if ((_unitGroup getVariable ["GroupSize",-1]) > 0) then {
_currentTime = diag_tickTime;
// _unitGroup call A3XAI_initNoAggroStatus;
_unitGroup setVariable ["lastRearmTime",_currentTime];
_unitGroup setVariable ["antistuckTime",_currentTime];
_unitGroup setVariable ["lootGenTime",_currentTime];
};
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: %1 group %2 ownership was returned to server.",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup];};
} else {
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Waiting to transfer %1 group %2 ownership to headless client (ID: %3).",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup,A3XAI_HCObjectOwnerID];};
};
};
if (isDedicated) then {
if !((groupOwner _unitGroup) in [2,A3XAI_HCObjectOwnerID]) then {
_unitGroup setGroupOwner 2;
diag_log format ["[A3XAI] Returned improperly transferred group %1 to server.",_unitGroup];
};
};
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {uiSleep 15};
};
if (A3XAI_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 {
A3XAI_transferGroup_PVS = _unitGroup;
publicVariableServer "A3XAI_transferGroup_PVS"; //Return ownership to server.
A3XAI_HCGroupsCount = A3XAI_HCGroupsCount - 1;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI 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]) < 0) then { //GroupSize value of -1 marks group for deletion
if (!isNull _unitGroup) then {
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Deleting %2 group %1.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])]};
_result = _unitGroup call A3XAI_deleteGroup;
};
};
} else {
diag_log "A3XAI Error: An A3XAI-managed group was deleted unexpectedly!";
};
if (local _vehicle) then {
call {
if (_vehicle getVariable ["DeleteVehicle",false]) exitWith {
_vehicle setPosATL [0,0,100];
deleteVehicle _vehicle;
};
if (isEngineOn _vehicle) exitWith {
_vehicle engineOn false;
};
};
};
true

View File

@ -0,0 +1,99 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_groupVariables", "_unitLevel"];
//Expected input:
// _unitGroup = _this select 0;
// _vehicle = _this select 1;
// _groupVariables = _this select 2;
// _unitLevel = _this select 3;
if (A3XAI_debugLevel > 1) then {
diag_log format ["A3XAI Debug: %1 groups in global group manager.",(count A3XAI_managedGroups)];
};
A3XAI_managedGroups pushBack _this;
if (A3XAI_managedGroups isEqualTo [_this]) then {
diag_log "Starting new global group manager.";
_nul = [] spawn {
while {!(A3XAI_managedGroups isEqualTo [])} do {
// diag_log "DEBUG: Global group manager is checking groups.";
{
_unitGroup = _x select 0;
_vehicle = _x select 1;
_groupVariables = _x select 2;
_unitLevel = _x select 3;
if ((!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}) then {
call {
if (A3XAI_HCIsConnected && {local _unitGroup}) exitWith {
_result = _unitGroup call A3XAI_transferGroupToHC;
if (_result) then {
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Transferred ownership of %1 group %2 to HC %3.",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup,A3XAI_HCObjectOwnerID];};
};
};
[_unitGroup,_vehicle] call (_groupVariables select 0);
[_unitGroup] call (_groupVariables select 1);
if ((diag_tickTime - (_unitGroup getVariable ["lootGenTime",diag_tickTime])) > LOOT_PULL_RATE) then {
[_unitGroup,_unitLevel] call (_groupVariables select 2);
};
if ((alive _vehicle) && {(diag_tickTime - (_unitGroup getVariable ["lastRearmTime",0])) > CHECK_VEHICLE_AMMO_FUEL_TIME}) then { //If _vehicle is objNull (if no vehicle was assigned to the group) then nothing in this bracket should be executed
[_unitGroup,_vehicle] call (_groupVariables select 3);
};
if ((diag_tickTime - (_unitGroup getVariable ["antistuckTime",diag_tickTime])) > (_groupVariables select 5)) then {
[_unitGroup,_vehicle,(_groupVariables select 5)] call (_groupVariables select 4);
};
};
} else {
// diag_log format ["DEBUG: Global group manager is removing group %1.",_unitGroup];
if (A3XAI_enableDebugMarkers) then {
deleteMarker format ["%1_Lead",_unitGroup];
deleteMarker format ["%1_WP",_unitGroup];
};
_nul = [_unitGroup,_vehicle] spawn {
_unitGroup = _this select 0;
_vehicle = _this select 1;
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]) < 0) then { //GroupSize value of -1 marks group for deletion
if (!isNull _unitGroup) then {
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Deleting %2 group %1.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])]};
_result = _unitGroup call A3XAI_deleteGroup;
};
};
if (local _vehicle) then {
call {
if (_vehicle getVariable ["DeleteVehicle",false]) exitWith {
_vehicle setPosATL [0,0,100];
deleteVehicle _vehicle;
};
if (isEngineOn _vehicle) exitWith {
_vehicle engineOn false;
};
};
};
};
A3XAI_managedGroups deleteAt _forEachIndex;
};
uiSleep 0.1;
} forEach A3XAI_managedGroups;
uiSleep 10;
};
if (A3XAI_debugLevel > 1) then {
diag_log format ["A3XAI Debug: %1 groups in global group manager. Exiting.",(count A3XAI_managedGroups)];
};
};
};
true

View File

@ -0,0 +1,11 @@
#include "\A3XAI\globaldefines.hpp"
_unit = (_this select 0);
_item = (_this select 1);
_slot = floor (random 3);
if ((_slot isEqualTo 0) && {_unit canAddItemToUniform _item}) exitWith {_unit addItemToUniform _item; true};
if ((_slot isEqualTo 1) && {_unit canAddItemToVest _item}) exitWith {_unit addItemToVest _item; true};
if ((_slot isEqualTo 2) && {_unit canAddItemToBackpack _item}) exitWith {_unit addItemToBackpack _item; true};
false

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
_this addEventHandler ["Killed","[(_this select 0),true] call A3XAI_vehDestroyed"];
_this addEventHandler ["HandleDamage","_this call A3XAI_handleDamageVeh"];
true

View File

@ -0,0 +1 @@
#include "\A3XAI\globaldefines.hpp" private ["_trigger", "_objectString", "_mapMarkerArray"]; _trigger = _this select 0; _objectString = _this select 1; if !(isNull _trigger) then { if !(_objectString in allMapMarkers) then { _objectString = createMarker [_objectString, _trigger]; _objectString setMarkerType "mil_warning"; _objectString setMarkerBrush "Solid"; _mapMarkerArray = missionNamespace getVariable ["A3XAI_mapMarkerArray",[]]; _trigger setVariable ["MarkerName",_objectString]; _mapMarkerArray pushBack _objectString; }; _objectString setMarkerText "STATIC TRIGGER (ACTIVE)"; _objectString setMarkerColor "ColorRed"; }; // diag_log format ["%1 %2",__FILE__,_this]; true

View File

@ -0,0 +1,41 @@
#include "\A3XAI\globaldefines.hpp"
private ["_targetPlayer", "_vehicle", "_startPos", "_unitLevel", "_unitGroup", "_paraGroup", "_cargoAvailable", "_unit", "_vehiclePos", "_parachute", "_unitsAlive", "_trigger", "_rearm", "_cargoAvailable"];
_vehicle = _this select 0;
_unitGroup = _this select 1;
_cargoAvailable = _this select 2;
_targetPlayer = _this select 3;
_target = if (isPlayer _targetPlayer) then {_targetPlayer} else {_vehicle};
_startPos = getPosATL _target;
_startPos set [2,0];
_unitLevel = _unitGroup getVariable ["unitLevel",1];
_paraGroup = ["vehiclecrew"] call A3XAI_createGroup;
for "_i" from 1 to _cargoAvailable do {
_unit = [_paraGroup,_unitLevel,[0,0,0]] call A3XAI_createUnit;
_vehiclePos = (getPosATL _vehicle);
_parachute = createVehicle [PARACHUTE_OBJECT, [_vehiclePos select 0, _vehiclePos select 1, (_vehiclePos select 2)], [], (-10 + (random 10)), "FLY"];
_unit moveInDriver _parachute;
_unit call A3XAI_addTempNVG;
};
_unitsAlive = {alive _x} count (units _paraGroup);
_trigger = [_startPos,(format ["Heli AI Reinforcement %1",mapGridPosition _vehicle])] call A3XAI_createTriggerArea;
0 = [5,_trigger,[_unitGroup],PATROL_DIST_PARAGROUP,_unitLevel,[_unitsAlive,0]] call A3XAI_initializeTrigger;
_paraGroup setVariable ["GroupSize",_unitsAlive];
_paraGroup setVariable ["trigger",_trigger];
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
A3XAI_staticSpawnObjects pushBackUnique _trigger;
[_paraGroup,_startPos] call A3XAI_setFirstWPPos;
0 = [_paraGroup,_startPos,PATROL_DIST_PARAGROUP] spawn A3XAI_BIN_taskPatrol;
_rearm = [_paraGroup,_unitLevel] spawn A3XAI_addGroupManagerSingle;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Paradrop group %1 with %2 units deployed at %3 by %4 group %5.",_paraGroup,_cargoAvailable,_startPos,typeOf _vehicle,_unitGroup];};
true

View File

@ -0,0 +1,104 @@
#include "\A3XAI\globaldefines.hpp"
private ["_respawnSleep", "_nextRespawnTime", "_mode", "_trigger", "_unitGroup", "_fastMode", "_respawnLimit", "_spawnParams", "_vehicleType"];
if (isDedicated) then {
_respawnSleep = 0;
_nextRespawnTime = 0;
_mode = _this select 0;
call {
if (_mode isEqualTo 0) exitWith {
//Infantry AI respawn
_trigger = _this select 1; //spawn area to respawn
_unitGroup = _this select 2; //infantry group to respawn
// _fastMode = if ((count _this) > 3) then {_this select 3} else {false}; //shorter wait time if retrying a spawn
_fastMode = [_this,3,false] call A3XAI_param;
if (isNull _trigger) then {_trigger = _unitGroup getVariable ["trigger",objNull];};
_respawnSleep = _trigger getVariable ["respawnTime",(A3XAI_respawnTimeMin + (random A3XAI_respawnTimeVariance))]; //Calculate wait time for respawn. Respawn time may be individually defined for custom spawns.
if (_fastMode) then {_respawnSleep = ADD_RESPAWN_FAST_TIME;};
_nextRespawnTime = (diag_tickTime + _respawnSleep); //Determine time of next respawn
A3XAI_respawnQueue pushBack [diag_tickTime + _respawnSleep,_mode,_trigger,_unitGroup];
_respawnLimit = _trigger getVariable ["respawnLimit",-1];
if !(_respawnLimit isEqualTo 0) then {
if (_respawnLimit > 0) then {_trigger setVariable ["respawnLimit",(_respawnLimit -1)];};
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Added group %1 to respawn queue. Queue position %2. Wait Time %3 (respawnHandler)",_unitGroup,(count A3XAI_respawnQueue),_respawnSleep];};
};
if (_mode isEqualTo 1) exitWith {
//Custom vehicle AI respawn
_spawnParams = _this select 1; //parameters used to call A3XAI_createVehicleSpawn
_respawnSleep = if ((count _spawnParams) > 5) then {_spawnParams select 5} else {600}; //calculate respawn time
_nextRespawnTime = (diag_tickTime + _respawnSleep); //Determine time of next respawn
A3XAI_respawnQueue pushBack [diag_tickTime + _respawnSleep,_mode,_spawnParams];
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Added custom AI vehicle %1 patrol to respawn queue. Queue position %2. Wait Time %3 (respawnHandler)",(_spawnParams select 1),(count A3XAI_respawnQueue),_respawnSleep];};
};
if (_mode isEqualTo 2) exitWith {
//Vehicle patrol AI respawn
_vehicleType = _this select 1;
_fastMode = [_this,2,false] call A3XAI_param;
call {
if (_fastMode) exitWith {
_respawnSleep = ADD_RESPAWN_FAST_TIME;
};
if (_vehicleType isKindOf "Air") exitWith {
_respawnSleep = (A3XAI_respawnAirMinTime + random A3XAI_respawnTimeVarAir);
};
if (_vehicleType isKindOf "LandVehicle") exitWith {
_respawnSleep = (A3XAI_respawnLandMinTime + random A3XAI_respawnTimeVarLand);
};
};
_nextRespawnTime = (diag_tickTime + _respawnSleep); //Determine time of next respawn
A3XAI_respawnQueue pushBack [diag_tickTime + _respawnSleep,_mode,_vehicleType];
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Added AI vehicle patrol type %1 to respawn queue. Queue position %2. Wait Time %3 (respawnHandler)",_vehicleType,(count A3XAI_respawnQueue),_respawnSleep];};
};
if (_mode isEqualTo 3) exitWith {
//UAV/UGV respawn
_vehicleType = _this select 1;
// _fastMode = if ((count _this) > 2) then {_this select 2} else {false}; //shorter wait time if retrying a spawn
_fastMode = [_this,2,false] call A3XAI_param;
if (_fastMode) then {_respawnSleep = ADD_RESPAWN_FAST_TIME};
if (_vehicleType isKindOf "Air") then {
_respawnSleep = (A3XAI_respawnUAVMinTime + random A3XAI_respawnTimeVarUAV);
} else {
_respawnSleep = (A3XAI_respawnUGVMinTime + random A3XAI_respawnTimeVarUGV);
};
_nextRespawnTime = (diag_tickTime + _respawnSleep); //Determine time of next respawn
A3XAI_respawnQueue pushBack [diag_tickTime + _respawnSleep,_mode,_vehicleType];
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Added unmanned vehicle patrol type %1 to respawn queue. Queue position %2. Wait Time %3 (respawnHandler)",_vehicleType,(count A3XAI_respawnQueue),_respawnSleep];};
};
if (_mode isEqualTo 4) exitWith {
//Custom UAV/UGV respawn
};
};
if (!isNil "A3XAI_respawnActive") exitWith {}; //If the first respawn has already occured, no need to modify the initial wait time.
if (!isNil "A3XAI_nextRespawnTime") then {
if (_nextRespawnTime < A3XAI_nextRespawnTime) then { //If the newest respawn is scheduled to happen sooner than the next closest respawn, reduce the initial wait time appropriately.
A3XAI_nextRespawnTime = _nextRespawnTime; //Time of next spawn
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Decreased time to next respawn to %1 seconds.",_respawnSleep];};
};
} else {
A3XAI_nextRespawnTime = _nextRespawnTime;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Time to first respawn set to %1 seconds.",_respawnSleep];};
};
if (!isNil "A3XAI_queueActive") exitWith {};
A3XAI_queueActive = true; //The respawn queue is established, so don't create another one until it's finished.
A3XAI_addRespawnQueueHandle = [] spawn A3XAI_processRespawn;
} else {
A3XAI_respawnGroup_PVS = _this;
publicVariableServer "A3XAI_respawnGroup_PVS";
};
true

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
if (_this hasWeapon NVG_ITEM_PLAYER) exitWith {false};
_this addWeapon NVG_ITEM_AI;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Generated temporary NVGs for AI %1.",_this];};
true

View File

@ -0,0 +1,21 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup","_waypoint","_pos","_wpStatements"];
_unitGroup = _this select 0;
_pos = _this select 1;
_wpStatements = [_this,2,"if !(local this) exitWith {}; (group this) call A3XAI_moveToPosAndDeleteWP;"] call A3XAI_param;
if !(_pos isEqualTo [0,0,0]) then {
_waypoint = _unitGroup addWaypoint [_pos,0];
_waypoint setWaypointType "MOVE";
_waypoint setWaypointSpeed "FULL";
_waypoint setWaypointCompletionRadius 30;
_waypoint setWaypointStatements ["true",_wpStatements];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 assigned temporary waypoint at %2 with statements %3.",_unitGroup,_pos,_wpStatements];};
_waypoint
} else {
diag_log format ["A3XAI Error: Group %1 was assigned temporary waypoint at %2.",_unitGroup,_pos];
};

View File

@ -0,0 +1,11 @@
#include "\A3XAI\globaldefines.hpp"
private ["_index"];
_index = -1;
if !(isNull _this) then {
_this setVariable ["ExileIsSimulationMonitored", true];
_index = A3XAI_externalObjectMonitor pushBack _this;
};
_index

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
_this addEventHandler ["Killed","_this call A3XAI_UAV_destroyed"];
_this addEventHandler ["Hit","_this call A3XAI_defensiveAggression"];
true

View File

@ -0,0 +1,9 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
_this addEventHandler ["Killed","_this call A3XAI_UGV_destroyed"];
_this addEventHandler ["HandleDamage","_this call A3XAI_handleDamageUGV"];
_this addEventHandler ["Hit","_this call A3XAI_defensiveAggression"];
true

View File

@ -0,0 +1,7 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
_this addEventHandler ["Killed","_this call A3XAI_handle_death_UV;"];
true

View File

@ -0,0 +1,10 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
_this addEventHandler ["Killed","_this call A3XAI_handleDeathEvent;"];
_this addEventHandler ["HandleDamage","_this call A3XAI_handleDamageUnit;"];
_this setVariable ["bodyName",(name _this)];
true

View File

@ -0,0 +1,10 @@
#include "\A3XAI\globaldefines.hpp"
if (isNull _this) exitWith {};
if (isNil {_this getVariable "durability"}) then {_this setVariable ["durability",[0,0,0,0]];};
_this addEventHandler ["Killed","_this call A3XAI_heliDestroyed"];
_this addEventHandler ["GetOut","_this call A3XAI_heliLanded"];
_this addEventHandler ["HandleDamage","_this call A3XAI_handleDamageHeli"];
true

View File

@ -0,0 +1,104 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_unitsAlive", "_unitLevel", "_trigger", "_rearm" ,"_pos", "_posReflected", "_leader","_airEvacType"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_airEvacType = [_this,2,0] call A3XAI_param;
_leader = leader _unitGroup;
_pos = getPosATL _leader;
_pos set [2,0];
_unitsAlive = {alive _x} count (units _unitGroup);
try {
if (_unitsAlive isEqualTo 0) then {
throw format ["A3XAI Debug: %1 cannot create trigger area for empty group %2.",__FILE__,_unitGroup];
};
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
deleteWaypoint [_unitGroup,_i];
};
if ([_pos,NO_AGGRO_RANGE_LAND] call A3XAI_checkInNoAggroArea) then {
_pos = [_pos,NO_AGGRO_RANGE_LAND] call A3XAI_getSafePosReflected;
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
if !(_pos isEqualTo []) then {
_tempWP = [_unitGroup,_pos,format ["if !(local this) exitWith {}; [(group this),%1] call A3XAI_moveToPosAndPatrol;",PATROL_DIST_VEHICLEGROUP]] call A3XAI_addTemporaryWaypoint;
};
} else {
_unitGroup setCombatMode "YELLOW";
_unitGroup setBehaviour "AWARE";
[_unitGroup,_pos] call A3XAI_setFirstWPPos;
0 = [_unitGroup,_pos,PATROL_DIST_VEHICLEGROUP] spawn A3XAI_BIN_taskPatrol;
};
if (_pos isEqualTo []) then {
_unitGroup setVariable ["GroupSize",-1];
if !(local _unitGroup) then {
A3XAI_updateGroupSizeManual_PVC = [_unitGroup,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
deleteVehicle _vehicle;
throw format ["A3XAI Debug: Vehicle group %1 inside no-aggro area at %2. Deleting group.",_unitGroup,_pos];
};
//new
_unitLevel = _unitGroup getVariable ["unitLevel",1]; //A3EAI to-do - grab unitLevel value here
if (_airEvacType > 0) then {
_cargoAvailable = (_vehicle emptyPositions "cargo") min A3XAI_paraDropAmount; //To do: Replace A3XAI_paraDropAmount with Cargo amount
if (_airEvacType isEqualTo 1) then {
for "_i" from 1 to _cargoAvailable do {
_unit = [_unitGroup,_unitLevel,[0,0,0]] call A3XAI_createUnit;
_unit moveInCargo _vehicle;
_unit action ["getOut",_vehicle];
_unit call A3XAI_addTempNVG;
};
} else {
for "_i" from 1 to _cargoAvailable do {
_unit = [_unitGroup,_unitLevel,[0,0,0]] call A3XAI_createUnit;
_vehiclePos = (getPosATL _vehicle);
_parachute = createVehicle [PARACHUTE_OBJECT, [_vehiclePos select 0, _vehiclePos select 1, (_vehiclePos select 2)], [], (-10 + (random 10)), "FLY"];
_unit moveInDriver _parachute;
_unit call A3XAI_addTempNVG;
};
};
_unitsAlive = {alive _x} count (units _unitGroup);
if !(local _unitGroup) then {
A3XAI_updateGroupSizeAuto_PVC = _unitGroup;
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeAuto_PVC";
};
};
_trigger = [_pos,(format ["AI Vehicle Group %1",mapGridPosition _leader])] call A3XAI_createTriggerArea;
0 = [4,_trigger,[_unitGroup],PATROL_DIST_VEHICLEGROUP,_unitLevel,[_unitsAlive,0]] call A3XAI_initializeTrigger;
_unitGroup setVariable ["GroupSize",_unitsAlive];
_unitGroup setVariable ["trigger",_trigger];
[_unitGroup,"vehiclecrew"] call A3XAI_setUnitType;
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
A3XAI_staticSpawnObjects pushBackUnique _trigger;
{
if (alive _x) then {
if ((_x getHit "legs") > 0) then {_x setHit ["legs",0]};
unassignVehicle _x;
};
} count (units _unitGroup);
if !(local _unitGroup) then {
A3XAI_sendGroupTriggerVars_PVC = [_unitGroup,[_unitGroup],PATROL_DIST_VEHICLEGROUP,1,1,[_unitsAlive,0],0,"vehiclecrew",false,true];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_sendGroupTriggerVars_PVC";
};
} catch {
if (A3XAI_debugLevel > 0) then {
diag_log _exception;
};
};
true

View File

@ -0,0 +1,30 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_unitLevel", "_vehicle", "_maxGunners", "_vehicleTurrets", "_maxGunnersAssigned", "_gunnersAdded", "_turretWeapons", "_turretMagazines", "_gunner"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_vehicle = _this select 2;
_maxGunners = _this select 3;
_vehicleTurrets = allTurrets [_vehicle,false];
_maxGunnersAssigned = (_maxGunners min (count _vehicleTurrets));
_gunnersAdded = 0;
{
if (_gunnersAdded isEqualTo _maxGunnersAssigned) exitWith {};
_turretWeapons = _vehicle weaponsTurret _x;
if !(_turretWeapons isEqualTo []) then {
_turretMagazines = _vehicle magazinesTurret _x;
if !(_turretMagazines isEqualTo []) then {
_gunner = [_unitGroup,_unitLevel,[0,0,0]] call A3XAI_createUnit;
_gunner call A3XAI_addTempNVG;
_gunner assignAsTurret [_vehicle,_x];
_gunner moveInTurret [_vehicle,_x];
_gunnersAdded = _gunnersAdded + 1;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Added gunner unit %1 to %2 %3 with weapon %4 (%5 of %6).",_gunner,_unitGroup,(typeOf _vehicle),(_turretWeapons select 0),_gunnersAdded,_maxGunnersAssigned];};
};
};
} count _vehicleTurrets;
_gunnersAdded

View File

@ -0,0 +1,37 @@
#include "\A3XAI\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_RANGE) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3XAI_checkInActiveNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < ANTISTUCK_MIN_TRAVEL_DIST_AIR} && {canMove _vehicle}) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (A3XAI_locationsAir call A3XAI_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 A3XAI_SHK_pos;
[_unitGroup,0] setWPPos _wpSelect;
[_unitGroup,1] setWPPos _wpSelect;
if ((count (waypoints _unitGroup)) > 2) then {[_unitGroup,2] setWPPos _wpSelect;};
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
_unitGroup setVariable ["antistuckPos",_wpSelect];
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 "\A3XAI\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 distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_RANGE) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3XAI_checkInActiveNoAggroArea}) && {_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 (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 "\A3XAI\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 A3XAI_checkInActiveNoAggroArea}) && ((_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 A3XAI_fixStuckGroup;
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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,46 @@
#include "\A3XAI\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 A3XAI_checkInActiveNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_LAND}) then {
if (canMove _vehicle) then {
[_unitGroup] call A3XAI_fixStuckGroup;
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (A3XAI_locationsLand call A3XAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_LAND_MIN_WP_DIST) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,ANTISTUCK_LAND_WP_DIST_BASE+(random ANTISTUCK_LAND_WP_DIST_VARIANCE),(random 360),0] call A3XAI_SHK_pos;
[_unitGroup,0] setWaypointPosition [_wpSelect,0];
_unitGroup setCurrentWaypoint [_unitGroup,0];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 ["VehicleDisabled",false])) then {
[_vehicle,false] call A3XAI_vehDestroyed;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: AI vehicle %1 (Group: %2) is immobilized. Respawning vehicle patrol group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
if (A3XAI_enableDebugMarkers) then {_checkPos call A3XAI_debugMarkerLocation;};
};
};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

Binary file not shown.

View File

@ -0,0 +1,45 @@
#include "\A3XAI\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 A3XAI_checkInActiveNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < 100}) then {
if (canMove _vehicle) then {
[_unitGroup] call A3XAI_fixStuckGroup;
_tooClose = true;
_wpSelect = [];
while {_tooClose} do {
_wpSelect = (A3XAI_locationsLand call A3XAI_selectRandom) select 1;
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_LAND_MIN_WP_DIST) then {
_tooClose = false;
} else {
uiSleep 0.1;
};
};
_wpSelect = [_wpSelect,ANTISTUCK_LAND_WP_DIST_BASE+(random ANTISTUCK_LAND_WP_DIST_VARIANCE),(random 360),0] call A3XAI_SHK_pos;
[_unitGroup,0] setWaypointPosition [_wpSelect,0];
[_unitGroup,1] setWaypointPosition [_wpSelect,0];
_unitGroup setCurrentWaypoint [_unitGroup,1];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 ["VehicleDisabled",false])) then {
[_vehicle] call A3XAI_UGV_destroyed;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: UGV %1 (Group: %2) is immobilized. Respawning UGV group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
if (A3XAI_enableDebugMarkers) then {_checkPos call A3XAI_debugMarkerLocation;};
};
};
} else {
_unitGroup setVariable ["antistuckPos",_checkPos];
_unitGroup setVariable ["antistuckTime",diag_tickTime];
};
true

View File

@ -0,0 +1,31 @@
#include "\A3XAI\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 A3XAI_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 A3XAI_addTemporaryWaypoint;
} forEach _searchPoints;
true

View File

@ -0,0 +1,15 @@
#include "\A3XAI\globaldefines.hpp"
private["_trigger"];
_trigger = _this;
A3XAI_dynamicTriggerArray = A3XAI_dynamicTriggerArray - [_trigger];
_playerUID = _trigger getVariable "targetplayerUID";
if (!isNil "_playerUID") then {A3XAI_failedDynamicSpawns pushBack _playerUID};
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
deleteVehicle _trigger;
false

View File

@ -0,0 +1,15 @@
#include "\A3XAI\globaldefines.hpp"
private["_trigger","_triggerLocation"];
_trigger = _this;
[_trigger,"A3XAI_randomTriggerArray",false] call A3XAI_updateSpawnCount;
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
_triggerLocation = _trigger getVariable "triggerLocation";
deleteLocation _triggerLocation;
deleteVehicle _trigger;
false

View File

@ -0,0 +1,6 @@
#include "\A3XAI\globaldefines.hpp"
private ["_result"];
_result = ((random 1) < _this);
_result

View File

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

View File

@ -0,0 +1,66 @@
#include "\A3XAI\globaldefines.hpp"
private ["_classname","_checkType","_result","_config","_banString","_check","_configIndex"];
_classname = _this select 0;
_checkType = _this select 1;
_result = false;
_configIndex = -1;
_checkType = (toLower _checkType);
_startTime = diag_tickTime;
call {
if (_checkType isEqualTo "weapon") exitWith {
if (_classname in (A3XAI_checkedClassnames select 0)) then {
_result = true;
} else {
if (!(_classname in (A3XAI_invalidClassnames select 0))) then {
_config = "CfgWeapons";
_banString = "bin\config.bin/CfgWeapons/FakeWeapon";
_configIndex = 0;
};
};
};
if (_checkType isEqualTo "magazine") exitWith {
if (_classname in (A3XAI_checkedClassnames select 1)) then {
_result = true;
} else {
if (!(_classname in (A3XAI_invalidClassnames select 0))) then {
_config = "CfgMagazines";
_banString = "bin\config.bin/CfgMagazines/FakeMagazine";
_configIndex = 1;
};
};
};
if (_checkType isEqualTo "vehicle") exitWith {
if (_classname in (A3XAI_checkedClassnames select 2)) then {
_result = true;
} else {
if (!(_classname in (A3XAI_invalidClassnames select 0))) then {
_config = "CfgVehicles";
_banString = "bin\config.bin/CfgVehicles/Banned";
_configIndex = 2;
};
};
};
diag_log format ["A3XAI Error: Attempted to check %1 as an invalid classname type! Provided type: %2. Valid types: weapon, magazine, vehicle.",_checkType];
};
if (_configIndex > -1) then {
_check = (str(inheritsFrom (configFile >> _config >> _classname)));
_classnameArray = [];
if ((_check != "") && {(_check != _banString)} && {(getNumber (configFile >> _config >> _classname >> "scope")) != 0}) then {
_classnameArray = A3XAI_checkedClassnames;
_result = true;
} else {
_classnameArray = A3XAI_invalidClassnames;
diag_log format ["A3XAI Warning: %1 is an invalid %2 classname!",_classname,_checkType];
};
//(_classnameArray select _configIndex) set [(count (_classnameArray select _configIndex)),_classname]; //Classname now known to be either valid or invalid, no need to check it again
(_classnameArray select _configIndex) pushBack _classname;
//;diag_log format ["DEBUG :: Classname check result: %1. ClassnameArray: %2.",_result,_classnameArray];
};
//diag_log format ["DEBUG :: Classname %1 (check result: %2) completed in %3 seconds.",_classname,_result,diag_tickTime - _startTime];
_result

View File

@ -0,0 +1,45 @@
#include "\A3XAI\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 (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 A3XAI_addItem;
if (_unit getVariable ["extraMag",false]) then {
[_unit,_magazine] call A3XAI_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 A3XAI_addItem;
};
};
if (alive _unit) then {uiSleep 15};
};
};
if (alive _unit) then {
_unit setVariable ["canCheckUnit",true];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Repacking unit manager for unit %1.",_unit];};
};
};
};
uiSleep 0.1;
} forEach (units _unitGroup);
true

View File

@ -0,0 +1,18 @@
#include "\A3XAI\globaldefines.hpp"
private ["_inNoAggroArea", "_objectPos", "_noAggroRange"];
_objectPos = _this select 0;
_noAggroRange = [_this,1,900] call A3XAI_param;
if (_objectPos isEqualTo objNull) exitWith {false};
if (((typeName _objectPos) isEqualTo "OBJECT") && {_objectPos isEqualTo objNull}) exitWith {false};
_inNoAggroArea = false;
{
if ((_x distance2D _objectPos) < _noAggroRange) exitWith {
_inNoAggroArea = true;
};
} count A3XAI_activeNoAggroAreas;
_inNoAggroArea

View File

@ -0,0 +1,18 @@
#include "\A3XAI\globaldefines.hpp"
private ["_inArea", "_object", "_distance"];
_object = _this select 0;
_distance = [_this,1,750] call A3XAI_param;
if (((typeName _object) isEqualTo "OBJECT") && {_object isEqualTo objNull}) exitWith {false};
// if ((typeName _object) isEqualTo "OBJECT") then {_object = getPosATL _object};
_inArea = false;
{
if ((_x distance2D _object) < _distance) exitWith {
_inArea = true;
};
} count A3XAI_activePlayerAreas;
_inArea

View File

@ -0,0 +1,18 @@
#include "\A3XAI\globaldefines.hpp"
private ["_inNoAggroArea", "_objectPos", "_noAggroRange"];
_objectPos = _this select 0;
_noAggroRange = [_this,1,900] call A3XAI_param;
if (_objectPos isEqualTo objNull) exitWith {false};
if ((typeName _objectPos) isEqualTo "OBJECT") then {_objectPos = getPosATL _objectPos};
_inNoAggroArea = false;
{
if (((position _x) distance2D _objectPos) < _noAggroRange) exitWith {
_inNoAggroArea = true;
};
} count A3XAI_noAggroAreas;
_inNoAggroArea

View File

@ -0,0 +1,15 @@
#include "\A3XAI\globaldefines.hpp"
private ["_magazineTypes","_ammo","_ammoMaxRange","_ammoHit"];
if ((typeName _this) != "STRING") exitWith {false};
_magazineTypes = [configFile >> "CfgWeapons" >> _this,"magazines",[]] call BIS_fnc_returnConfigEntry;
if (_magazineTypes isEqualTo []) exitWith {false};
_cursorAim = [configFile >> "CfgWeapons" >> _this,"cursorAim","throw"] call BIS_fnc_returnConfigEntry;
if (_cursorAim isEqualTo "throw") exitWith {false};
_ammo = [configFile >> "CfgMagazines" >> (_magazineTypes select 0),"ammo",""] call BIS_fnc_returnConfigEntry;
if (_ammo isEqualTo "") exitWith {false};
_ammoHit = [configFile >> "CfgAmmo" >> _ammo,"hit",0] call BIS_fnc_returnConfigEntry;
if (_ammoHit isEqualTo 0) exitWith {false};
true

View File

@ -0,0 +1,20 @@
#include "\A3XAI\globaldefines.hpp"
_unitGroup = _this;
if (!((typeName _unitGroup) isEqualTo "GROUP") || {isNull _unitGroup}) exitWith {diag_log format ["A3XAI Error: Invalid group %1 provided to %2.",_unitGroup,__FILE__];};
diag_log format ["Debug: Cleaning up reinforcement group %1.",_unitGroup];
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
_vehicle allowDamage false;
// _vehicle enableSimulationGlobal false;
// _vehicle hideObjectGlobal true;
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed","Hit"];
// {_x enableSimulationGlobal false;} forEach (units _unitGroup);
_unitGroup setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_cleanupReinforcement_PVC = [_unitGroup,_vehicle];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_cleanupReinforcement_PVC";
};
true

View File

@ -0,0 +1,11 @@
#include "\A3XAI\globaldefines.hpp"
private ["_vehicle"];
_vehicle = _this;
clearWeaponCargoGlobal _vehicle;
clearMagazineCargoGlobal _vehicle;
clearItemCargoGlobal _vehicle;
clearBackpackCargoGlobal _vehicle;
true

View File

@ -0,0 +1,11 @@
#include "\A3XAI\globaldefines.hpp"
private ["_vehicle", "_gunnerCount"];
_vehicle = _this;
_gunnerCount = {!((_vehicle weaponsTurret _x) isEqualTo []) && {!((_vehicle magazinesTurret _x) isEqualTo [])}} count (allTurrets [_vehicle,false]);
diag_log format ["Debug: %1 has %2 gunners.",(typeOf _vehicle),_gunnerCount];
_gunnerCount

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
private ["_pos","_size"];
_pos = _this select 0;
_size = _this select 1;
createLocation [BLACKLIST_OBJECT_GENERAL,_pos,_size,_size]

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
private ["_pos","_size"];
_pos = _this select 0;
_size = _this select 1;
createLocation [BLACKLIST_OBJECT_DYNAMIC,_pos,_size,_size]

View File

@ -0,0 +1,8 @@
#include "\A3XAI\globaldefines.hpp"
private ["_pos","_size"];
_pos = _this select 0;
_size = _this select 1;
createLocation [BLACKLIST_OBJECT_DYNAMIC,_pos,_size,_size]

View File

@ -0,0 +1,20 @@
#include "\A3XAI\globaldefines.hpp"
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1.",__FILE__]};
if (A3XAI_customBlacklistQueue isEqualTo []) then {
A3XAI_customBlacklistQueue pushBack _this;
_blacklistQueue = [] spawn {
while {!(A3XAI_customBlacklistQueue isEqualTo [])} do {
_statement = (A3XAI_customBlacklistQueue select 0);
_blacklistName = _statement select 0;
_statement deleteAt 0;
if ((_statement select 1) > 1499) then {_statement set [1,1499];};
_statement call A3XAI_createBlackListArea;
A3XAI_customBlacklistQueue deleteAt 0;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Creating blacklist area at %1 (pos: %2) with radius %3.",_blacklistName,_statement select 0,_statement select 1];};
uiSleep 1;
};
};
} else {
A3XAI_customBlacklistQueue pushBack _this;
};

View File

@ -0,0 +1,15 @@
#include "\A3XAI\globaldefines.hpp"
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1 (%2).",__FILE__,_this]};
if (A3XAI_createCustomSpawnQueue isEqualTo []) then {
A3XAI_createCustomSpawnQueue pushBack _this;
_infantryQueue = [] spawn {
while {!(A3XAI_createCustomSpawnQueue isEqualTo [])} do {
(A3XAI_createCustomSpawnQueue select 0) call A3XAI_createCustomSpawn;
A3XAI_createCustomSpawnQueue deleteAt 0;
uiSleep 1;
};
};
} else {
A3XAI_createCustomSpawnQueue pushBack _this;
};

View File

@ -0,0 +1,57 @@
#include "\A3XAI\globaldefines.hpp"
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1.",__FILE__]};
private ["_trigger", "_grpArray", "_infantryQueue","_triggerStatements"];
_trigger = _this select 3;
_grpArray = _trigger getVariable ["GroupArray",[]];
if (_grpArray isEqualTo []) then {
if (A3XAI_customInfantrySpawnQueue isEqualTo []) then {
A3XAI_customInfantrySpawnQueue pushBack _this;
_infantryQueue = [] spawn {
//uiSleep 0.5;
while {!(A3XAI_customInfantrySpawnQueue isEqualTo [])} do {
if (A3XAI_currentFPS < A3XAI_minFPS) then {
if (A3XAI_debugLevel > 0) then {
diag_log format ["A3XAI Debug: Custom Infantry AI spawning paused. Waiting for server FPS to be above minimum set value (Current: %1. Minimum: %2)",A3XAI_currentFPS,A3XAI_minFPS];
};
waitUntil {uiSleep 15; A3XAI_currentFPS > A3XAI_minFPS};
};
private ["_args","_trigger"];
_args = (A3XAI_customInfantrySpawnQueue select 0);
_trigger = _args select 3;
if (triggerActivated _trigger) then {
_trigger setVariable ["isCleaning",false];
_triggerStatements = (triggerStatements _trigger);
_triggerStatements set [1,""];
_trigger setTriggerStatements _triggerStatements;
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
0 = _args call A3XAI_spawnInfantryCustom;
if (A3XAI_enableDebugMarkers) then {
_nul = [_trigger,str(_trigger)] call A3XAI_addMapMarker;
};
};
A3XAI_customInfantrySpawnQueue deleteAt 0;
uiSleep 1;
};
};
} else {
if !(_this in A3XAI_customInfantrySpawnQueue) then {
A3XAI_customInfantrySpawnQueue pushBack _this;
};
};
} else {
private ["_triggerStatements"];
_triggerStatements = (triggerStatements _trigger);
_triggerStatements set [1,""];
_trigger setTriggerStatements _triggerStatements;
_trigger setTriggerArea [TRIGGER_SIZE_EXPANDED,TRIGGER_SIZE_EXPANDED,0,false];
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
if (A3XAI_enableDebugMarkers) then {
_nul = [_trigger,str(_trigger)] call A3XAI_addMapMarker;
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Maximum number of groups already spawned at custom %1. Exiting spawn script.",(_trigger getVariable ["TriggerText","Unknown Trigger"])];};
};
true

View File

@ -0,0 +1,44 @@
#include "\A3XAI\globaldefines.hpp"
if ((typeName _this) isEqualTo "ARRAY") then {
private ["_arraySize","_spawnName","_spawnPos","_patrolDist","_trigStatements","_trigger","_respawn","_unitLevel","_totalAI","_respawnTime"];
_arraySize = (count _this);
_spawnName = _this select 0;
_spawnPos = _this select 1;
_patrolDist = if (_arraySize> 2) then {_this select 2} else {100};
_totalAI = if (_arraySize > 3) then {_this select 3} else {2};
_unitLevel = if (_arraySize > 4) then {_this select 4} else {2};
_respawn = if (_arraySize > 5) then {_this select 5} else {false};
_respawnTime = if (_arraySize > 6) then {_this select 6} else {0};
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Creating custom spawn area with params %1.",_this];};
if !(_unitLevel in A3XAI_unitLevels) then {_unitLevel = 3;};
if !(surfaceIsWater _spawnPos) then {
_trigStatements = format ["0 = [%1,0,%2,thisTrigger,%3,%4] call A3XAI_createCustomInfantrySpawnQueue;",_totalAI,_patrolDist,_unitLevel,_respawnTime];
_trigger = createTrigger [SENSOR_OBJECT,_spawnPos,false];
_trigger setTriggerArea [TRIGGER_SIZE_NORMAL,TRIGGER_SIZE_NORMAL,0,false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [TRIGGER_TIMEOUT_STATICCUSTOM, true];
_trigger setTriggerStatements ["{if (isPlayer _x) exitWith {1}} count thisList != 0;",_trigStatements,"0 = [thisTrigger] spawn A3XAI_despawn_static;"];
_trigger setVariable ["respawn",_respawn];
_trigger setVariable ["TriggerText",_spawnName];
//_trigger setVariable ["spawnmarker",_spawnName];
_trigger setVariable ["isCustom",true];
if (_respawnTime > 0) then {_trigger setVariable ["respawnTime",_respawnTime];};
0 = [3,_trigger,[],_patrolDist,_unitLevel,[],[_totalAI,0]] call A3XAI_initializeTrigger;
//diag_log format ["DEBUG: triggerstatements variable is %1",_trigger getVariable "triggerStatements"];
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Created custom spawn area %1 at %2 with %3 AI units, unitLevel %4, respawn %5, respawn time %6.",_spawnName,mapGridPosition _trigger,_totalAI,_unitLevel,_respawn,_respawnTime];};
_trigger
} else {
diag_log format ["A3XAI Error: Unable to create custom spawn %1, position at %2 is water.",_spawnName,_spawnPos];
objNull
};
} else {
diag_log format ["Error: Wrong arguments sent to %1 (%2).",__FILE__,_this];
objNull
};

View File

@ -0,0 +1,20 @@
#include "\A3XAI\globaldefines.hpp"
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1.",__FILE__]};
if (A3XAI_customVehicleSpawnQueue isEqualTo []) then {
A3XAI_customVehicleSpawnQueue pushBack _this;
_vehicleQueue = [] spawn {
while {!(A3XAI_customVehicleSpawnQueue isEqualTo [])} do {
_vehicleType = (A3XAI_customVehicleSpawnQueue select 0) select 2;
if (!(_vehicleType isKindOf "StaticWeapon") && {[_vehicleType,"vehicle"] call A3XAI_checkClassname}) then {
(A3XAI_customVehicleSpawnQueue select 0) call A3XAI_spawnVehicleCustom;
} else {
diag_log format ["A3XAI Error: %1 attempted to spawn unsupported vehicle type %2.",__FILE__,_vehicleType];
};
A3XAI_customVehicleSpawnQueue deleteAt 0;
uiSleep 2;
};
};
} else {
A3XAI_customVehicleSpawnQueue pushBack _this;
};

View File

@ -0,0 +1,11 @@
#include "\A3XAI\globaldefines.hpp"
private["_unitGroup","_protect","_unitType"];
_unitType = _this select 0;
_unitGroup = createGroup A3XAI_side;
if ((count _this) > 1) then {_unitGroup call A3XAI_protectGroup};
[_unitGroup,_unitType] call A3XAI_setUnitType;
A3XAI_activeGroups pushBack _unitGroup;
_unitGroup

View File

@ -0,0 +1,74 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger", "_grpArray", "_numGroups", "_infantryQueue","_triggerStatements"];
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1.",__FILE__]};
_trigger = _this select 3;
_grpArray = _trigger getVariable ["GroupArray",[]];
_numGroups = if ((count _this) > 6) then {_this select 6} else {1};
if ((count _grpArray) < _numGroups) then {
if (A3XAI_staticInfantrySpawnQueue isEqualTo []) then {
A3XAI_staticInfantrySpawnQueue pushBack _this;
_infantryQueue = [] spawn {
while {!(A3XAI_staticInfantrySpawnQueue isEqualTo [])} do {
if (A3XAI_currentFPS < A3XAI_minFPS) then {
if (A3XAI_debugLevel > 0) then {
diag_log format ["A3XAI Debug: Static Infantry AI spawning paused. Waiting for server FPS to be above minimum set value (Current: %1. Minimum: %2)",A3XAI_currentFPS,A3XAI_minFPS];
};
waitUntil {uiSleep 15; A3XAI_currentFPS > A3XAI_minFPS};
};
private ["_args","_trigger"];
_args = (A3XAI_staticInfantrySpawnQueue select 0);
_trigger = _args select 3;
if (({(_trigger distance2D _x) < NO_AGGRO_RANGE_MAN} count A3XAI_activeNoAggroAreas) isEqualTo 0) then {
if (triggerActivated _trigger) then {
_trigger setVariable ["isCleaning",false];
_triggerStatements = (triggerStatements _trigger);
if (_trigger getVariable ["A3XAI_static_spawn",false]) then {
_triggerStatements set [1,"if !(thisTrigger in A3XAI_activePlayerAreas) then {A3XAI_activePlayerAreas pushBack thisTrigger;};"];
} else {
_triggerStatements set [1,""];
};
_trigger setTriggerStatements _triggerStatements;
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
0 = _args call A3XAI_spawnUnits_static;
if (A3XAI_enableDebugMarkers) then {
//diag_log format ["Trigger object: %1, position: %2, type: %3",_trigger,getPosASL _trigger,typeOf _trigger];
_nul = [_trigger,str(_trigger)] call A3XAI_addMapMarker;
if (A3XAI_enableDebugMarkers) then {
_marker = str(_trigger);
_marker setMarkerColor "ColorOrange";
_marker setMarkerAlpha 0.9;
};
};
};
};
A3XAI_staticInfantrySpawnQueue deleteAt 0;
uiSleep 3;
};
};
} else {
if !(_this in A3XAI_staticInfantrySpawnQueue) then {
A3XAI_staticInfantrySpawnQueue pushBack _this;
};
};
} else {
private ["_triggerStatements"];
_triggerStatements = (triggerStatements _trigger);
if (_trigger getVariable ["A3XAI_static_spawn",false]) then {
_triggerStatements set [1,"if !(thisTrigger in A3XAI_activePlayerAreas) then {A3XAI_activePlayerAreas pushBack thisTrigger;};"];
} else {
_triggerStatements set [1,""];
};
_trigger setTriggerStatements _triggerStatements;
_trigger setTriggerArea [TRIGGER_SIZE_EXPANDED,TRIGGER_SIZE_EXPANDED,0,false];
[_trigger,"A3XAI_staticTriggerArray",true] call A3XAI_updateSpawnCount;
if (A3XAI_enableDebugMarkers) then {
//diag_log format ["Trigger object: %1, position: %2, type: %3",_trigger,getPosASL _trigger,typeOf _trigger];
_nul = [_trigger,str(_trigger)] call A3XAI_addMapMarker;
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Maximum number of groups already spawned at %1. Exiting spawn script.",(_trigger getVariable ["TriggerText","Unknown Trigger"])];};
};
true

View File

@ -0,0 +1,28 @@
#include "\A3XAI\globaldefines.hpp"
private ["_size", "_trigger"];
_areaPos = _this select 0;
_size = _this select 1;
_trigger = createTrigger [SENSOR_OBJECT,_areaPos,false];
_trigger setTriggerArea [_size,_size,0,false];
_trigger setTriggerActivation ["ANY", "PRESENT", true];
_trigger setTriggerTimeout [TRIGGER_TIMEOUT_NOAGGROAREA,true];
_trigger setTriggerStatements ["{if (isPlayer _x) exitWith {1}} count thisList > 0;", "0 = [thisTrigger] call A3XAI_noAggroAreaActivate;", "0 = [thisTrigger] call A3XAI_noAggroAreaDeactivate;"];
_trigger setVariable ["TriggerText",format ["No-Aggro Area %1",_areaPos]];
A3XAI_noAggroAreas pushBack _trigger;
/*
diag_log format ["Debug: Trigger object %1",_trigger];
diag_log format ["Debug: Trigger area %1",triggerArea _trigger];
diag_log format ["Debug: Trigger activation %1",triggerActivation _trigger];
diag_log format ["Debug: Trigger timeout %1",triggerTimeout _trigger];
diag_log format ["Debug: Trigger text %1",_trigger getVariable ["TriggerText","Unknown Trigger"]];
diag_log format ["Debug: Trigger statements %1",triggerStatements _trigger];
diag_log format ["Debug: A3XAI_noAggroAreas: %1",A3XAI_noAggroAreas];
*/
_trigger

View File

@ -0,0 +1,46 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger", "_infantryQueue","_triggerStatements"];
if !((typeName _this) isEqualTo "ARRAY") exitWith {diag_log format ["Error: Wrong arguments sent to %1.",__FILE__]};
_trigger = _this select 1;
//diag_log format ["DEBUG: Started random spawn queue with args %1",_this];
if ((_trigger getVariable ["GroupArray",[]]) isEqualTo []) then {
if (A3XAI_randomInfantrySpawnQueue isEqualTo []) then {
A3XAI_randomInfantrySpawnQueue pushBack _this;
_infantryQueue = [] spawn {
while {!(A3XAI_randomInfantrySpawnQueue isEqualTo [])} do {
if (A3XAI_currentFPS < A3XAI_minFPS) then {
if (A3XAI_debugLevel > 0) then {
diag_log format ["A3XAI Debug: Random Infantry AI spawning paused. Waiting for server FPS to be above minimum set value (Current: %1. Minimum: %2)",A3XAI_currentFPS,A3XAI_minFPS];
};
waitUntil {uiSleep 15; A3XAI_currentFPS > A3XAI_minFPS};
};
private ["_args","_trigger"];
_args = (A3XAI_randomInfantrySpawnQueue select 0);
_trigger = _args select 1;
if (triggerActivated _trigger) then {
_trigger setVariable ["isCleaning",false];
_triggerStatements = (triggerStatements _trigger);
_triggerStatements set [1,""];
_trigger setTriggerStatements _triggerStatements;
0 = _args call A3XAI_spawnUnits_random;
if (A3XAI_enableDebugMarkers) then {
_marker = str(_trigger);
_marker setMarkerColor "ColorOrange";
_marker setMarkerAlpha 0.9;
};
};
A3XAI_randomInfantrySpawnQueue deleteAt 0;
uiSleep 3;
};
};
} else {
if !(_this in A3XAI_randomInfantrySpawnQueue) then {
A3XAI_randomInfantrySpawnQueue pushBack _this;
};
};
};
true

View File

@ -0,0 +1,19 @@
#include "\A3XAI\globaldefines.hpp"
private ["_size", "_trigger", "_areaName"];
_areaPos = _this select 0;
_areaName = _this select 1;
if (_areaPos isEqualTo [0,0,0]) exitWith {
diag_log format ["A3XAI Error: Invalid parameters sent to %1: %2",__FILE__,_this];
objNull
};
// _trigger = TRIGGER_OBJECT createVehicleLocal _areaPos; //triggerless version
_trigger = createTrigger [TRIGGER_OBJECT,_areaPos,false]; //triggerless version
_trigger enableSimulation false; //Disable to reduce performance impact
_trigger setVariable ["TriggerText",_areaName];
diag_log format ["Debug: Created trigger object %1 at %2",_trigger,_areaName];
_trigger

View File

@ -0,0 +1,24 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unit", "_unitGroup", "_spawnPos", "_unitLevel", "_type"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_spawnPos = _this select 2;
_antistuck = if ((count _this) > 3) then {_this select 3} else {false};
_unit = _unitGroup createUnit [DEFAULT_UNIT_CLASSNAME,_spawnPos,[],0,"FORM"];
[_unit] joinSilent _unitGroup;
0 = _unit call A3XAI_addUnitEH;
0 = [_unit, _unitLevel] call A3XAI_generateLoadout; // Assign unit loadout
0 = [_unit, _unitLevel] call A3XAI_setSkills; // Set AI skill
_unit enableFatigue false;
A3XAI_monitoredObjects pushBack _unit;
if (_antistuck) then {
_unit setPosATL _spawnPos;
_unit setVelocity [0,0,0.5];
};
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: Spawned AI %1 with unitLevel %2 for group %3.",_unit,_unitLevel,_unitGroup];};
_unit

View File

@ -0,0 +1,16 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unit", "_unitGroup", "_spawnPos", "_unitLevel", "_type"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_spawnPos = _this select 2;
_unit = _unitGroup createUnit ["I_UAV_AI",_spawnPos,[],0,"FORM"];
[_unit] joinSilent _unitGroup;
0 = _unit call A3XAI_addUVUnitEH;
0 = [_unit, _unitLevel] call A3XAI_setSkills; // Set AI skill
A3XAI_monitoredObjects pushBack _unit;
if (A3XAI_debugLevel > 1) then {diag_log format["A3XAI Debug: Spawned UAV AI %1 with unitLevel %2 for group %3.",_unit,_unitLevel,_unitGroup];};
_unit

View File

@ -0,0 +1,34 @@
#include "\A3XAI\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 ["VehicleDisabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}) then{
_detectOrigin = [getPosATL _vehicle,0,getDir _vehicle,1] call A3XAI_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 []) && {A3XAI_airDetectChance call A3XAI_chance}) then {
//if (!(terrainIntersectASL [_heliAimPos,_playerAimPos]) && {!(lineIntersects [_heliAimPos,_playerAimPos,_vehicle,_x])} && {A3XAI_airDetectChance call A3XAI_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 A3XAI_radioSend;
};
};
};
uiSleep 0.1;
} forEach _detected;
};
_unitGroup setVariable ["IsDetecting",false];

View File

@ -0,0 +1,16 @@
#include "\A3XAI\globaldefines.hpp"
private ["_mapMarkerArray","_objectString"];
_mapMarkerArray = missionNamespace getVariable ["A3XAI_mapMarkerArray",[]];
_objectString = str (_this);
if !(_objectString in _mapMarkerArray) then { //Determine if marker is new
if !(_objectString in allMapMarkers) then {
private ["_marker"];
_marker = createMarker [_objectString, _this];
_marker setMarkerType "Waypoint";
_marker setMarkerColor "ColorRed";
_marker setMarkerBrush "Solid";
};
_mapMarkerArray pushBack _objectString;
missionNamespace setVariable ["A3XAI_mapMarkerArray",_mapMarkerArray];
};

View File

@ -0,0 +1,20 @@
#include "\A3XAI\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 A3XAI_getNoAggroStatus) exitWith {false};
if ((isPlayer _hitSource) && {(combatMode _unitGroup isEqualTo "BLUE")}) then {
_aggroExpiry = diag_tickTime + DEFENSIVE_AGGRESSION_TIME;
_vehicle setVariable ["AggroTime",_aggroExpiry];
[_unitGroup,"Default"] call A3XAI_forceBehavior;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Defensive aggression enabled for %1 %2",_unitGroup,(typeOf _vehicle)];};
};
true

View File

@ -0,0 +1,42 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger","_triggerType"];
_trigger = call {
_triggerType = (typeName _this);
if (_triggerType isEqualTo "OBJECT") exitWith {
_this
};
if (_triggerType isEqualTo "GROUP") exitWith {
_this getVariable ["trigger",objNull]
};
_this
};
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
_trigger setTriggerStatements ["this","true","false"]; //Disable trigger from activating or deactivating while cleanup is performed
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Deleting custom-defined AI spawn %1 at %2 in 30 seconds.",_trigger getVariable ["TriggerText","Unknown Trigger"], mapGridPosition _trigger];};
uiSleep 30;
{
_x setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_updateGroupSizeManual_PVC = [_x,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
} forEach (_trigger getVariable ["GroupArray",[]]);
[_trigger,"A3XAI_staticTriggerArray",false] call A3XAI_updateSpawnCount;
if (_trigger in A3XAI_staticSpawnObjects) then {
A3XAI_staticSpawnObjects = A3XAI_staticSpawnObjects - [_trigger,objNull];
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Deleting custom-defined AI spawn %1 at %2.",_trigger getVariable ["TriggerText","Unknown Trigger"], mapGridPosition _trigger];};
deleteVehicle _trigger;
true

View File

@ -0,0 +1,28 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle"];
_unitGroup = _this;
{
if (alive _x) then {
deleteVehicle _x;
} else {
[_x] joinSilent grpNull;
};
} count (units _unitGroup);
if (_unitGroup getVariable ["RecycleGroup",false]) then {
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull]; //If infantry AI have vehicle assigned, will need to change this line
if (isNull _vehicle) then { //Groups with assigned vehicles do not need to be preserved
_unitGroup call A3XAI_protectGroup;
} else {
deleteGroup _unitGroup;
A3XAI_activeGroups = A3XAI_activeGroups - [_unitGroup,grpNull];
};
} else {
A3XAI_activeGroups = A3XAI_activeGroups - [_unitGroup,grpNull];
deleteGroup _unitGroup;
};
true

View File

@ -0,0 +1,75 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger","_grpArray","_grpCount","_permDelete"];
_trigger = _this select 0; //Get the trigger object
_grpArray = _trigger getVariable ["GroupArray",[]]; //Find the groups spawned by the trigger.
_grpCount = count _grpArray;
if (A3XAI_debugLevel > 0) then {
diag_log format["A3XAI Debug: No players remain in trigger area at %1. Deleting %2 AI groups.", (_trigger getVariable ["TriggerText","Unknown Trigger"]),_grpCount]; //replace trigger text with function suitable for non-triggers
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Trigger %1 Group Array: %2. In static trigger array: %3",_trigger getVariable ["TriggerText","Unknown Trigger"],_grpArray,(_trigger in A3XAI_staticTriggerArray)];};
};
_permDelete = _trigger getVariable ["permadelete",false];
{
if (!isNull _x) then {
_groupSize = (_x getVariable ["GroupSize",0]);
if ((_groupSize > 0) or {_permDelete}) then { //If trigger is not set to permanently despawn, then ignore empty groups.
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Despawning group %1 with %2 active units.",_x,(_x getVariable ["GroupSize",0])];};
_x setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_updateGroupSizeManual_PVC = [_x,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
_grpArray set [_forEachIndex,grpNull];
};
};
} forEach _grpArray;
if !(_permDelete) then {
//Cleanup variables attached to trigger
_trigger setVariable ["GroupArray",_grpArray - [grpNull]];
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["unitLevelEffective",(_trigger getVariable ["unitLevel",1])];
if !((_trigger getVariable ["respawnLimitOriginal",-1]) isEqualTo -1) then {_trigger setVariable ["respawnLimit",_trigger getVariable ["respawnLimitOriginal",-1]];};
if (A3XAI_enableDebugMarkers) then {
_marker = _trigger getVariable ["MarkerName",""];
call {
if (_trigger in A3XAI_staticSpawnObjects) exitWith {
if (_marker in allMapMarkers) then {
_marker setMarkerText "STATIC TRIGGER (INACTIVE)";
_marker setMarkerColor "ColorGreen";
};
};
if (_trigger in A3XAI_randomTriggerArray) exitWith {
deleteMarker _marker;
};
if (_trigger in A3XAI_dynamicTriggerArray) exitWith {
deleteMarker _marker;
};
deleteMarker _marker;
diag_log format ["Debug: Unhandled case for static spawn %1 in %2.",_trigger getVariable ["TriggerText","Unknown Spawn"],__FILE__];
};
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Despawned AI units at %1. Reset trigger's group array to: %2.",(_trigger getVariable ["TriggerText","Unknown Trigger"]),_trigger getVariable "GroupArray"];};
} else {
if (A3XAI_enableDebugMarkers) then {
_marker = str (_trigger);
if (_marker in allMapMarkers) then {
deleteMarker _marker;
};
};
//Replace trigger-specific functions
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Permanently deleting a static spawn at %1.",_trigger getVariable ["TriggerText","Unknown Trigger"]]};
deleteVehicle _trigger;
};
true

View File

@ -0,0 +1,84 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger","_triggerLocation","_isForceDespawn","_grpArray","_canDespawn","_triggerExists","_triggerStatements","_deactStatements"];
_trigger = _this select 0; //Get the trigger object
_isForceDespawn = if ((count _this) > 1) then {_this select 1} else {false};
_triggerStatements = triggerStatements _trigger;
_grpArray = _trigger getVariable ["GroupArray",[]]; //Find the groups spawned by the trigger. Or set an empty group array if none are found.
if ((_trigger getVariable ["isCleaning",false]) && (!_isForceDespawn)) exitWith {if (A3XAI_debugLevel > 1) then {diag_log "A3XAI Debug: Despawn script is already running. Exiting despawn script.";};};
_trigger setVariable["isCleaning",true]; //Mark the trigger as being in a cleanup state so that subsequent requests to despawn for the same trigger will not run.
_deactStatements = _triggerStatements select 2;
_trigger setTriggerStatements (_triggerStatements set [2,""]);
_canDespawn = true;
_triggerExists = true;
if (_isForceDespawn) then {
_trigger setTriggerStatements ["this","",""];
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: All units of dynamic AI group spawned by trigger %1 have been killed. Starting force despawn in 30 seconds.",_trigger getVariable ["TriggerText","Unknown Spawn"]];};
uiSleep 30;
} else {
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: No players remain in %1. Deleting spawned AI in %2 seconds.",_trigger getVariable ["TriggerText","Unknown Spawn"],A3XAI_despawnDynamicSpawnTime];};
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_marker = str(_this);
_marker setMarkerColor "ColorGreen";
_marker setMarkerAlpha 0.7; //Light green: Active trigger awaiting despawn.
};
};
uiSleep A3XAI_despawnDynamicSpawnTime; //Wait some time before deleting units. (amount of time to allow units to exist when the trigger area has no players)
if !(isNull _trigger) then { //Check if dynamic spawn area has been force-despawned (deleted). Force despawn will happen when all units have been killed.
_canDespawn = ((!triggerActivated _trigger) or {isNull (_grpArray select 0)}); //Can despawn dynamic spawn area if trigger isn't activated or spawned group is null
} else {
_triggerExists = false;
};
};
if !(_triggerExists) exitWith {}; //Cancel despawn process if it has already happened
if (_canDespawn) then {
_trigger setTriggerStatements ["this","",""]; //temporarily disable trigger from activating or deactivating while cleanup is performed
_grpArray = _grpArray - [grpNull];
{
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Deleting group %1 with %2 active units.",_x,(_x getVariable ["GroupSize",0])];};
_x setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_updateGroupSizeManual_PVC = [_x,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
} forEach _grpArray;
//Remove dynamic trigger from global dyn trigger array and clean up trigger
[_trigger,"A3XAI_dynamicTriggerArray",false] call A3XAI_updateSpawnCount;
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
//Begin deletion timer for temporary blacklist area and add it to global dyn location array to allow deletion
_triggerLocation = _trigger getVariable "triggerLocation";
_triggerLocation setVariable ["deletetime",(diag_tickTime + A3XAI_tempBlacklistTime)];
A3XAI_areaBlacklists pushBack _triggerLocation;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Removing expired dynamic trigger at %1.",mapGridPosition _trigger];};
deleteVehicle _trigger;
true
} else {
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: A player has entered the trigger area at %1. Cancelling despawn.",(_trigger getVariable ["TriggerText","Unknown Spawn"])];}; //Exit script if trigger has been reactivated since A3XAI_despawnDynamicSpawnTime seconds has passed.
_trigger setVariable ["isCleaning",false]; //Allow next despawn request.
_triggerStatements set [2,_deactStatements];
_trigger setTriggerStatements _triggerStatements;
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_marker = str(_this);
_marker setMarkerColor "ColorOrange";
_marker setMarkerAlpha 0.9; //Reset trigger indicator color to Active.
};
};
false
};

View File

@ -0,0 +1,84 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger","_triggerLocation","_isForceDespawn","_grpArray","_canDespawn","_triggerExists","_triggerStatements","_deactStatements"];
_trigger = _this select 0; //Get the trigger object
_isForceDespawn = if ((count _this) > 1) then {_this select 1} else {false};
_triggerStatements = triggerStatements _trigger;
_grpArray = _trigger getVariable ["GroupArray",[]]; //Find the groups spawned by the trigger. Or set an empty group array if none are found.
if ((_trigger getVariable ["isCleaning",false]) && (!_isForceDespawn)) exitWith {if (A3XAI_debugLevel > 1) then {diag_log "A3XAI Debug: Despawn script is already running. Exiting despawn script.";};};
_trigger setVariable["isCleaning",true]; //Mark the trigger as being in a cleanup state so that subsequent requests to despawn for the same trigger will not run.
_deactStatements = _triggerStatements select 2;
_trigger setTriggerStatements (_triggerStatements set [2,""]);
_canDespawn = true;
_triggerExists = true;
if (_isForceDespawn) then {
_trigger setTriggerStatements ["this","",""];
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: All units of random AI group spawned by trigger %1 have been killed. Starting force despawn in 30 seconds.",_trigger getVariable ["TriggerText","Unknown Spawn"]];};
uiSleep 30;
} else {
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: No players remain in %1. Deleting spawned AI in %2 seconds.",_trigger getVariable ["TriggerText","Unknown Spawn"],A3XAI_despawnRandomSpawnTime];};
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_marker = str(_this);
_marker setMarkerColor "ColorGreen";
_marker setMarkerAlpha 0.7; //Light green: Active trigger awaiting despawn.
};
};
uiSleep A3XAI_despawnRandomSpawnTime; //Wait some time before deleting units. (amount of time to allow units to exist when the trigger area has no players)
if !(isNull _trigger) then { //Check if random spawn area has been force-despawned (deleted). Force despawn will happen when all units have been killed.
_canDespawn = ((!triggerActivated _trigger) or {isNull (_grpArray select 0)}); //Can despawn random spawn area if trigger isn't activated or spawned group is null
} else {
_triggerExists = false;
};
};
if !(_triggerExists) exitWith {}; //Cancel despawn process if it has already happened
if (_canDespawn) then {
_trigger setTriggerStatements ["this","",""]; //temporarily disable trigger from activating or deactivating while cleanup is performed
_grpArray = _grpArray - [grpNull];
{
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Deleting group %1 with %2 active units.",_x,(_x getVariable ["GroupSize",0])];};
_x setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_updateGroupSizeManual_PVC = [_x,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
} forEach _grpArray;
//Remove random trigger from global dyn trigger array and clean up trigger
[_trigger,"A3XAI_randomTriggerArray",false] call A3XAI_updateSpawnCount;
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
//Begin deletion timer for temporary blacklist area and add it to global dyn location array to allow deletion
_triggerLocation = _trigger getVariable "triggerLocation";
_triggerLocation setVariable ["deletetime",(diag_tickTime + A3XAI_tempBlacklistTime)];
A3XAI_areaBlacklists pushBack _triggerLocation;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Removing expired random trigger at %1.",mapGridPosition _trigger];};
deleteVehicle _trigger;
true
} else {
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: A player has entered the trigger area at %1. Cancelling despawn script.",(_trigger getVariable ["TriggerText","Unknown Spawn"])];}; //Exit script if trigger has been reactivated since A3XAI_despawnRandomSpawnTime seconds has passed.
_trigger setVariable ["isCleaning",false]; //Allow next despawn request.
_triggerStatements set [2,_deactStatements];
_trigger setTriggerStatements _triggerStatements;
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_marker = str(_this);
_marker setMarkerColor "ColorOrange";
_marker setMarkerAlpha 0.9; //Reset trigger indicator color to Active.
};
};
false
};

View File

@ -0,0 +1,92 @@
#include "\A3XAI\globaldefines.hpp"
private ["_trigger","_grpArray","_isCleaning","_grpCount","_triggerStatements","_deactStatements","_permDelete"];
_trigger = _this select 0; //Get the trigger object
_grpArray = _trigger getVariable ["GroupArray",[]]; //Find the groups spawned by the trigger.
_isCleaning = _trigger getVariable ["isCleaning",true]; //Find whether or not the trigger has been marked for cleanup. Triggers will flag themselves for cleaning after a successful spawn/respawn with setVariable ["isCleaning",false];
_triggerStatements = triggerStatements _trigger;
_grpCount = count _grpArray;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Trigger %1 Group Array: %2. isCleaning: %3. In static trigger array: %4",_trigger getVariable ["TriggerText","Unknown Spawn"],_grpArray,_isCleaning,(_trigger in A3XAI_staticTriggerArray)];};
if (!(_trigger in A3XAI_staticTriggerArray) or {_isCleaning}) exitWith {if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Trigger %1 has a despawn script already running. Exiting despawn script.",_trigger getVariable ["TriggerText","Unknown Spawn"]];};};
_trigger setVariable["isCleaning",true]; //Mark the trigger as being in a cleanup state so that subsequent requests to despawn for the same trigger will not run.
_deactStatements = _triggerStatements select 2;
_triggerStatements set [2,""];
_trigger setTriggerStatements _triggerStatements;
if (A3XAI_debugLevel > 0) then {diag_log format["A3XAI Debug: No players remain in trigger area at %3. Deleting %1 AI groups in %2 seconds.",_grpCount, A3XAI_despawnWait,(_trigger getVariable ["TriggerText","Unknown Spawn"])];};
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_tMarker = str (_this);
_tMarker setMarkerText "STATIC TRIGGER (DESPAWNING)";
_tMarker setMarkerColor "ColorOrange";
};
};
if (({isNull _x} count _grpArray) < _grpCount) then {uiSleep A3XAI_despawnWait};
if (isNull _trigger) exitWith {[_trigger,"A3XAI_staticTriggerArray",false] call A3XAI_updateSpawnCount};
if ((triggerActivated _trigger) && {({isNull _x} count _grpArray) < _grpCount}) exitWith { //Exit script if trigger has been reactivated since A3XAI_despawnWait seconds has passed.
_trigger setVariable ["isCleaning",false]; //Allow next despawn request.
_triggerStatements set [2,_deactStatements];
_trigger setTriggerStatements _triggerStatements;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: A player has entered the trigger area at %1. Cancelling despawn script.",(_trigger getVariable ["TriggerText","Unknown Spawn"])];};
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_tMarker = str (_this);
_tMarker setMarkerText "STATIC TRIGGER (ACTIVE)";
_tMarker setMarkerColor "ColorRed";
};
};
};
_trigger setTriggerStatements ["this","true","false"]; //temporarily disable trigger from activating or deactivating while cleanup is performed
_permDelete = _trigger getVariable ["permadelete",false];
{
if (!isNull _x) then {
_groupSize = (_x getVariable ["GroupSize",0]);
if ((_groupSize > 0) or {_permDelete}) then { //If trigger is not set to permanently despawn, then ignore empty groups.
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Despawning group %1 with %2 active units.",_x,(_x getVariable ["GroupSize",0])];};
_x setVariable ["GroupSize",-1];
if (A3XAI_HCIsConnected) then {
A3XAI_updateGroupSizeManual_PVC = [_x,-1];
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_updateGroupSizeManual_PVC";
};
_grpArray set [_forEachIndex,grpNull];
};
};
} forEach _grpArray;
[_trigger,"A3XAI_staticTriggerArray",false] call A3XAI_updateSpawnCount;
if !(_permDelete) then {
//Cleanup variables attached to trigger
_trigger setVariable ["GroupArray",_grpArray - [grpNull]];
_trigger setVariable ["isCleaning",false];
_trigger setVariable ["unitLevelEffective",(_trigger getVariable ["unitLevel",1])];
_trigger setTriggerArea [TRIGGER_SIZE_NORMAL,TRIGGER_SIZE_NORMAL,0,false];
_trigger setTriggerStatements (_trigger getVariable "triggerStatements"); //restore original trigger statements
if !((_trigger getVariable ["respawnLimitOriginal",-1]) isEqualTo -1) then {_trigger setVariable ["respawnLimit",_trigger getVariable ["respawnLimitOriginal",-1]];};
if (A3XAI_enableDebugMarkers) then {
_nul = _trigger spawn {
_tMarker = str (_this);
_tMarker setMarkerText "STATIC TRIGGER (INACTIVE)";
_tMarker setMarkerColor "ColorGreen";
};
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Despawned AI units at %1. Reset trigger's group array to: %2 and statements to %3.",(_trigger getVariable ["TriggerText","Unknown Spawn"]),_trigger getVariable "GroupArray",_trigger getVariable "triggerStatements"];};
} else {
if (A3XAI_enableDebugMarkers) then {
deleteMarker (_trigger getVariable ["MarkerName",""]);
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Permanently deleting a static spawn at %1.",_trigger getVariable ["TriggerText","Unknown Spawn"]]};
deleteVehicle _trigger;
};
true

View File

@ -0,0 +1,13 @@
#include "\A3XAI\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,30 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_leader", "_inArea", "_assignedTarget"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_leader = (leader _unitGroup);
_inArea = [_vehicle,NO_AGGRO_RANGE_AIR] call A3XAI_checkInActiveNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_AIR) then {
_inArea = [_assignedTarget,300] call A3XAI_checkInActiveNoAggroArea;
};
};
if (_inArea) exitWith {
[_unitGroup,_vehicle,(typeOf _vehicle)] call A3XAI_recycleGroup;
};
if (((_unitGroup getVariable ["unitType",""]) == "air") && {!(_unitGroup getVariable ["IsDetecting",false])} && {[_vehicle,BEGIN_DETECT_DIST_AIR] call A3XAI_checkInActiveStaticSpawnArea}) then {
[_unitGroup] spawn A3XAI_heliDetection;
if (A3XAI_debugLevel > 1) then {
diag_log format ["A3XAI Debug: %1 %2 is scanning for players in active trigger area at %3.",_unitGroup,(typeOf _vehicle),(getPosATL _vehicle)];
};
};
true

View File

@ -0,0 +1,22 @@
#include "\A3XAI\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 A3XAI_checkInActiveNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_MAN) then {
_inArea = [_assignedTarget,300] call A3XAI_checkInActiveNoAggroArea;
};
};
if (_inArea) exitWith {
[_unitGroup,objNull,""] call A3XAI_recycleGroup;
};
true

View File

@ -0,0 +1,43 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_leader", "_inArea", "_assignedTarget", "_lastAggro"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_inArea = false;
if ((combatMode _unitGroup) == "YELLOW") then {
_leader = (leader _unitGroup);
_inArea = [_leader,NO_AGGRO_RANGE_UAV] call A3XAI_checkInActiveNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UAV) then {
_inArea = [_assignedTarget,300] call A3XAI_checkInActiveNoAggroArea;
};
};
if (_inArea) exitWith {
[_unitGroup,_vehicle,(typeOf _vehicle)] call A3XAI_recycleGroup;
};
_lastAggro = _vehicle getVariable "AggroTime";
if (!(isNil "_lastAggro") && {diag_tickTime > _lastAggro}) then {
_vehicle setVariable ["AggroTime",nil];
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Reset Group %1 %2 UAV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
};
};
if (_inArea) exitWith {};
if (((_unitGroup getVariable ["unitType",""]) == "uav") && {!(_unitGroup getVariable ["IsDetecting",false])} && {[_vehicle,BEGIN_DETECT_DIST_UAV] call A3XAI_checkInActiveStaticSpawnArea}) then {
[_unitGroup] spawn A3XAI_UAVDetection;
if (A3XAI_debugLevel > 1) then {
diag_log format ["A3XAI Debug: %1 %2 is scanning for players in active trigger area at %3.",_unitGroup,(typeOf _vehicle),(getPosATL _vehicle)];
};
};
true

View File

@ -0,0 +1,43 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_leader", "_inArea", "_assignedTarget", "_lastAggro"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_inArea = false;
if ((combatMode _unitGroup) == "YELLOW") then {
_leader = (leader _unitGroup);
_inArea = [_leader,NO_AGGRO_RANGE_UGV] call A3XAI_checkInActiveNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UGV) then {
_inArea = [_assignedTarget,300] call A3XAI_checkInActiveNoAggroArea;
};
};
if (_inArea) exitWith {
[_unitGroup,_vehicle,(typeOf _vehicle)] call A3XAI_recycleGroup;
};
_lastAggro = _vehicle getVariable "AggroTime";
if (!(isNil "_lastAggro") && {diag_tickTime > _lastAggro}) then {
_vehicle setVariable ["AggroTime",nil];
[_unitGroup,"Nonhostile"] call A3XAI_forceBehavior;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Reset Group %1 %2 UGV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
};
};
if (_inArea) exitWith {};
if (((_unitGroup getVariable ["unitType",""]) == "ugv") && {!(_unitGroup getVariable ["IsDetecting",false])} && {[_vehicle,BEGIN_DETECT_DIST_UGV] call A3XAI_checkInActiveStaticSpawnArea}) then {
[_unitGroup] spawn A3XAI_UGVDetection;
if (A3XAI_debugLevel > 1) then {
diag_log format ["A3XAI Debug: %1 %2 is scanning for players in active trigger area at %3.",_unitGroup,(typeOf _vehicle),(getPosATL _vehicle)];
};
};
true

View File

@ -0,0 +1,37 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_lastRegroupCheck","_respawnType","_inArea","_result","_leader","_unitType"];
_unitGroup = _this select 0;
_vehicle = _this select 1;
_leader = (leader _unitGroup);
_inArea = [_leader,NO_AGGRO_RANGE_LAND] call A3XAI_checkInActiveNoAggroArea;
if !(_inArea) then {
_assignedTarget = (assignedTarget (vehicle _leader));
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_LAND) then {
_inArea = [_assignedTarget,300] call A3XAI_checkInActiveNoAggroArea;
};
};
if (_inArea) exitWith {
[_unitGroup,_vehicle,(typeOf _vehicle)] call A3XAI_recycleGroup;
};
_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 A3XAI_vehCrewRegroup;
};
_vehicle setVariable ["LastRegroupCheck",diag_tickTime];
};
true

View File

@ -0,0 +1,31 @@
#include "\A3XAI\globaldefines.hpp"
//Finds a position that does not have a player within a certain distance.
private ["_spawnPos","_attempts","_continue","_spawnpool","_maxAttempts"];
_attempts = 0;
_continue = true;
_spawnPos = [];
_spawnpool = +_this;
_maxAttempts = ((count _spawnpool) min 3); //3: Maximum number of attempts
while {_continue && {(_attempts < _maxAttempts)}} do {
_index = floor (random (count _spawnpool));
_spawnPosSelected = (getPosATL (_spawnpool select _index)) findEmptyPosition [0.5,30,SPACE_FOR_OBJECT];
if !(_spawnPosSelected isEqualTo []) then {
_spawnPosSelected = _spawnPosSelected isFlatEmpty [0,0,0.75,5,0,false,objNull];
};
if (
!(_spawnPosSelected isEqualTo []) &&
{({if ((isPlayer _x) && {([eyePos _x,[(_spawnPosSelected select 0),(_spawnPosSelected select 1),(_spawnPosSelected select 2) + 1.7],_x] call A3XAI_hasLOS) or ((_x distance _spawnPosSelected) < PLAYER_DISTANCE_NO_LOS_STATIC)}) exitWith {1}} count (_spawnPosSelected nearEntities [[PLAYER_UNITS,"LandVehicle"],PLAYER_DISTANCE_WITH_LOS_STATIC])) isEqualTo 0}
) then {
_spawnPos = _spawnPosSelected;
_spawnPos set [2,0];
_continue = false;
} else {
_spawnpool deleteAt _index;
_attempts = _attempts + 1;
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Unable to find suitable spawn position. (attempt %1/%2).",_attempts,_maxAttempts];};
};
};
_spawnPos

View File

@ -0,0 +1,69 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_vehicle", "_isInfantry", "_nearPlayers", "_leaderPos", "_newPosEmpty","_unitType","_vehicleType","_leader"];
_unitGroup = _this select 0;
_vehicle = (_unitGroup getVariable ["assignedVehicle",objNull]);
_isInfantry = (isNull _vehicle);
_unitType = _unitGroup getVariable ["unitType",""];
_leaderPos = getPosATL (leader _unitGroup);
if (_isInfantry) then {
_newPosEmpty = _leaderPos findEmptyPosition [0.5,30,SPACE_FOR_OBJECT];
if !(_newPosEmpty isEqualTo []) then {
_newPosEmpty = _newPosEmpty isFlatEmpty [0,0,0.75,5,0,false,objNull];
};
if (_newPosEmpty isEqualTo []) then {
_newPosEmpty = [_leaderPos,10 + random(25),random(360),0,[0,0],[25,SPACE_FOR_OBJECT]] call A3XAI_SHK_pos;
};
if (({isPlayer _x} count (_newPosEmpty nearEntities [[PLAYER_UNITS,"AllVehicles"], PLAYER_DISTANCE_WITH_LOS_ANTISTUCK]) isEqualTo 0) && {((_newPosEmpty nearObjects [PLOTPOLE_OBJECT,PLOTPOLE_RADIUS]) isEqualTo [])}) then {
_newPosEmpty set [2,0];
{
_x setPosATL _newPosEmpty;
_x setVelocity [0,0,0.25];
} forEach (units _unitGroup);
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Relocated stuck group %1 (%2) to new location %3m away.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"]),(_leaderPos distance _newPosEmpty)];};
} else {
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Unable to relocate stuck group %1 (%2).",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])];};
};
} else {
_newPosEmpty = [0,0,0];
if (_unitType in ["land","ugv"]) then {
_keepLooking = true;
_vehicleType = (typeOf _vehicle);
while {_keepLooking} do {
_newPosEmpty = [(getMarkerPos "A3XAI_centerMarker"),300 + random((getMarkerSize "A3XAI_centerMarker") select 0),random(360),0,[2,750],[25,_vehicleType]] call A3XAI_SHK_pos;
if ((count _newPosEmpty) > 1) then {
if (({isPlayer _x} count (_newPosEmpty nearEntities [[PLAYER_UNITS,"AllVehicles"], PLAYER_DISTANCE_WITH_LOS_ANTISTUCK]) isEqualTo 0) && {((_newPosEmpty nearObjects [PLOTPOLE_OBJECT,PLOTPOLE_RADIUS]) isEqualTo [])}) then {
_keepLooking = false;
};
} else {
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Unable to find road position to relocate AI group %1 %2. Retrying in 15 seconds.",_unitGroup,_vehicleType]};
uiSleep 15;
};
};
} else {
_newPosEmpty = [_leaderPos,10 + random(25),random(360),0,[1,300],[25,(typeOf _vehicle)]] call A3XAI_SHK_pos;
};
_leader = (leader _unitGroup);
if ((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_RANGE_ANTISTUCK) then {
_vehicle setPosATL _newPosEmpty;
_vehicle setVelocity [0,0,0.25];
{
if ((isNull (objectParent _x)) && {(_x distance _vehicle) > 100}) then {
_newUnitPos = [_vehicle,25,random(360),0,[0,0],[25,DEFAULT_UNIT_CLASSNAME]] call A3XAI_SHK_pos;
_x setPosATL _newUnitPos;
_x setVelocity [0,0,0.25];
};
} forEach (units _unitGroup);
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Relocated stuck group %1 (%2) to new location %3m away.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"]),(_leaderPos distance _newPosEmpty)];};
} else {
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Unable to relocate stuck group %1 (%2) due to nearby enemy presence.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])];};
};
};
true

View File

@ -0,0 +1,39 @@
#include "\A3XAI\globaldefines.hpp"
private ["_action", "_unitGroup", "_result"];
_action = _this select 1;
_unitGroup = _this select 0;
_result = call {
if (_action isEqualTo "Nonhostile") exitWith {
_unitGroup setBehaviour "CARELESS";
_unitGroup setCombatMode "BLUE";
{_x doWatch objNull} forEach (units _unitGroup);
true
};
if (_action isEqualTo "Default") exitWith {
_unitGroup setBehaviour "AWARE";
_unitGroup setCombatMode "YELLOW";
false
};
if (_action isEqualTo "DefendOnly") exitWith {
_unitGroup setBehaviour "AWARE";
_unitGroup setCombatMode "GREEN";
{_x doWatch objNull} forEach (units _unitGroup);
false
};
false
};
_unitGroup setVariable ["EnemiesIgnored",_result];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Setting group %1 behavior mode to %2 (result: %3).",_unitGroup,_action,_result];};
_result

View File

@ -0,0 +1,20 @@
#include "\A3XAI\globaldefines.hpp"
private [];
_unitGroup = _this select 0;
_unitType = _this select 1;
_retryOnFail = _this select 2;
_fnc_respawnGroup = missionNamespace getVariable [format ["A3XAI_respawn_%1",_unitType],{}];
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
if !(isNull _vehicle) then {
_vehicle setVariable ["DeleteVehicle",true];
};
_result = [_unitType] call _fnc_respawnGroup;
_unitGroup setVariable ["GroupSize",-1];
true

View File

@ -0,0 +1,29 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unitGroup", "_lootPool", "_updateServerLoot", "_pullChance", "_lootUnit", "_lootIndex", "_loot", "_unitLevel"];
_unitGroup = _this select 0;
_unitLevel = _this select 1;
_lootPool = _unitGroup getVariable ["LootPool",[]];
_updateServerLoot = (A3XAI_enableHC && {!isDedicated});
_pullChance = missionNamespace getVariable [format ["A3XAI_lootPullChance%1",_unitLevel],0.40];
if !(_lootPool isEqualTo []) then {
if (_pullChance call A3XAI_chance) then {
_lootUnit = (units _unitGroup) call A3XAI_selectRandom;
_lootIndex = floor (random (count _lootPool));
_loot = _lootPool select _lootIndex;
if (alive _lootUnit) then {
if ([_lootUnit,_loot] call A3XAI_addItem) then {
_lootPool deleteAt _lootIndex;
if (_updateServerLoot) then {
[_unitGroup,_lootIndex] call A3XAI_updateServerLoot;
};
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI 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,163 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unit", "_unitLevel", "_unitLevelInvalid", "_loadout", "_weaponSelected", "_unitLevelString", "_uniforms", "_uniformItem", "_backpackChance", "_backpacks", "_backpackItem",
"_vestChance", "_vests", "_vestItem", "_headgearChance", "_headgears", "_headgearItem", "_magazine", "_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 ["A3XAI Error: Unit already has loadout! (%1)",__FILE__];};
if !(_unitLevel in A3XAI_unitLevelsAll) then {
_unitLevelInvalid = _unitLevel;
_unitLevel = A3XAI_unitLevels call A3XAI_selectRandom;
diag_log format ["A3XAI Error: Invalid unitLevel provided: %1. Generating new unitLevel value: %2. (%3)",_unitLevelInvalid,_unitLevel,__FILE__];
};
_unit call A3XAI_purgeUnitGear; //Clear unwanted gear from unit first.
_loadout = [[],[]];
_weaponSelected = _unitLevel call A3XAI_getWeapon;
_unitLevelString = str (_unitLevel);
_uniforms = missionNamespace getVariable ["A3XAI_uniformTypes"+_unitLevelString,[]];
if !(_uniforms isEqualTo []) then {
_uniformItem = _uniforms call A3XAI_selectRandom;
_unit forceAddUniform _uniformItem;
//diag_log format ["DEBUG: %1",_uniformItem];
};
_backpackChance = missionNamespace getVariable ["A3XAI_addBackpackChance"+_unitLevelString,1.00];
if (_backpackChance call A3XAI_chance) then {
_backpacks = missionNamespace getVariable ["A3XAI_backpackTypes"+_unitLevelString,[]];
if !(_backpacks isEqualTo []) then {
_backpackItem = _backpacks call A3XAI_selectRandom;
_unit addBackpack _backpackItem;
clearAllItemsFromBackpack _unit;
//diag_log format ["DEBUG: %1",_backpackItem];
};
};
_vestChance = missionNamespace getVariable ["A3XAI_addVestChance"+_unitLevelString,1.00];
if (_vestChance call A3XAI_chance) then {
_vests = missionNamespace getVariable ["A3XAI_vestTypes"+_unitLevelString,[]];
if !(_vests isEqualTo []) then {
_vestItem = _vests call A3XAI_selectRandom;
_unit addVest _vestItem;
//diag_log format ["DEBUG: %1",_vestItem];
};
};
_headgearChance = missionNamespace getVariable ["A3XAI_addHeadgearChance"+_unitLevelString,1.00];
if (_headgearChance call A3XAI_chance) then {
_headgears = missionNamespace getVariable ["A3XAI_headgearTypes"+_unitLevelString,[]];
if !(_headgears isEqualTo []) then {
_headgearItem = _headgears call A3XAI_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 !(A3XAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3XAI_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 (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI 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 (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Modified unit %1 loadout to %2.",_unit,_loadout];};
}
};
};
};
//Select weapon optics
_isRifle = ((getNumber (configFile >> "CfgWeapons" >> _weaponSelected >> "type")) isEqualTo 1);
if ((missionNamespace getVariable [("A3XAI_opticsChance"+_unitLevelString),3]) call A3XAI_chance) then {
_opticsList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems");
if !(_opticsList isEqualTo []) then {
_opticsType = A3XAI_weaponOpticsList call A3XAI_selectRandom;
if (_opticsType in _opticsList) then {
if (_isRifle) then {_unit addPrimaryWeaponItem _opticsType} else {_unit addHandGunItem _opticsType};
};
};
};
//Select weapon pointer
if ((missionNamespace getVariable [("A3XAI_pointerChance"+_unitLevelString),3]) call A3XAI_chance) then {
_pointersList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "PointerSlot" >> "compatibleItems");
if !(_pointersList isEqualTo []) then {
_pointerType = _pointersList call A3XAI_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 [("A3XAI_muzzleChance"+_unitLevelString),3]) call A3XAI_chance) then {
_muzzlesList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems");
if !(_muzzlesList isEqualTo []) then {
_muzzleType = _muzzlesList call A3XAI_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 [("A3XAI_underbarrelChance"+_unitLevelString),3]) call A3XAI_chance) then {
_underbarrelList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "UnderBarrelSlot" >> "compatibleItems");
if !(_underbarrelList isEqualTo []) then {
_underbarrelType = _underbarrelList call A3XAI_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 ["A3XAI_gadgetsList"+_unitLevelString,[]];
for "_i" from 0 to ((count _gadgetsArray) - 1) do {
if (((_gadgetsArray select _i) select 1) call A3XAI_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 (A3XAI_enableTempNVGs && {sunOrMoon < 1}) then {
_unit call A3XAI_addTempNVG;
};
//Give unit temporary first aid kits to allow self-healing (unit level 1+)
if (A3XAI_enableHealing) then {
for "_i" from 1 to (_unitLevel min 3) do {
[_unit,FIRST_AID_ITEM_AI] call A3XAI_addItem;
};
};
_unit setVariable ["loadout",_loadout];
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Created loadout for unit %1 (unitLevel: %2): %3.",_unit,_unitLevel,_loadout];};
true

View File

@ -0,0 +1,47 @@
#include "\A3XAI\globaldefines.hpp"
private ["_unit", "_unitLevel", "_weaponLoot", "_toolLoot", "_pistol", "_magazine", "_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 (A3XAI_debugLevel > 1) then {diag_log format["A3XAI Debug: Generating loot for AI unit with unitLevel %2.",_unit,_unitLevel];};
_weaponLoot = [];
_toolLoot = [];
_loadout = _unit getVariable ["loadout",[[],[]]];
_primaryWeapon = [_loadout select 0,0,""] call A3XAI_param;
//Generate a pistol if one wasn't assigned with loadout script.
if ((getNumber (configFile >> "CfgWeapons" >> _primaryWeapon >> "type")) != 2) then {
_pistol = A3XAI_pistolList call A3XAI_selectRandom;
_magazine = getArray (configFile >> "CfgWeapons" >> _pistol >> "magazines") select 0;
_unit addMagazine _magazine;
_unit addWeapon _pistol;
if (A3XAI_debugLevel > 1) then {
_weaponLoot pushBack _pistol;
_weaponLoot pushBack _magazine
};
};
//Add tool items
_toolsArray = missionNamespace getVariable ["A3XAI_toolsList"+str(_unitLevel),[]];
{
_item = _x select 0;
if (((_x select 1) call A3XAI_chance) && {[_item,"weapon"] call A3XAI_checkClassname}) then {
_unit addWeapon _item;
if (A3XAI_debugLevel > 1) then {
_toolLoot pushBack _item;
};
}
} forEach _toolsArray;
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Generated loot for AI death: %1,%2,%3.",_weaponLoot,_toolLoot];};

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