mirror of
https://github.com/SnarkIndustries/A3XAI-Final.git
synced 2024-08-30 17:22:13 +00:00
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:
parent
7abaffe24e
commit
c4a7084754
1
A3XAI/$PREFIX$
Normal file
1
A3XAI/$PREFIX$
Normal file
@ -0,0 +1 @@
|
||||
A3XAI
|
1
A3XAI/PboPrefix.txt
Normal file
1
A3XAI/PboPrefix.txt
Normal file
@ -0,0 +1 @@
|
||||
A3EAI
|
19
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_findclosestposition.sqf
Normal file
19
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_findclosestposition.sqf
Normal 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
|
59
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getmarkercorners.sqf
Normal file
59
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getmarkercorners.sqf
Normal 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
|
30
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getmarkershape.sqf
Normal file
30
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getmarkershape.sqf
Normal 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
|
13
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getpos.sqf
Normal file
13
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getpos.sqf
Normal 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]
|
26
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromcircle.sqf
Normal file
26
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromcircle.sqf
Normal 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]
|
43
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromellipse.sqf
Normal file
43
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromellipse.sqf
Normal 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]
|
37
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromrectangle.sqf
Normal file
37
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromrectangle.sqf
Normal 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]
|
36
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromsquare.sqf
Normal file
36
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_getposfromsquare.sqf
Normal 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]
|
85
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isblacklisted.sqf
Normal file
85
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isblacklisted.sqf
Normal 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
|
36
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isincircle.sqf
Normal file
36
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isincircle.sqf
Normal 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
|
54
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isinellipse.sqf
Normal file
54
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isinellipse.sqf
Normal 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
|
26
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isinrectangle.sqf
Normal file
26
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_isinrectangle.sqf
Normal 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
|
16
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_issameposition.sqf
Normal file
16
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_issameposition.sqf
Normal 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
|
13
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_rotateposition.sqf
Normal file
13
A3XAI/SHK_pos/A3XAI_SHK_pos_fnc_rotateposition.sqf
Normal 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]
|
170
A3XAI/SHK_pos/A3XAI_SHK_pos_getpos.sqf
Normal file
170
A3XAI/SHK_pos/A3XAI_SHK_pos_getpos.sqf
Normal 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
|
101
A3XAI/SHK_pos/A3XAI_SHK_pos_getposmarker.sqf
Normal file
101
A3XAI/SHK_pos/A3XAI_SHK_pos_getposmarker.sqf
Normal 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
|
105
A3XAI/SHK_pos/A3XAI_SHK_pos_init.sqf
Normal file
105
A3XAI/SHK_pos/A3XAI_SHK_pos_init.sqf
Normal 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
|
||||
};
|
262
A3XAI/compile/A3XAI_BIN_taskPatrol.sqf
Normal file
262
A3XAI/compile/A3XAI_BIN_taskPatrol.sqf
Normal 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
|
67
A3XAI/compile/A3XAI_UAVDetection.sqf
Normal file
67
A3XAI/compile/A3XAI_UAVDetection.sqf
Normal 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))];};
|
28
A3XAI/compile/A3XAI_UAVStartPatrol.sqf
Normal file
28
A3XAI/compile/A3XAI_UAVStartPatrol.sqf
Normal 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
|
21
A3XAI/compile/A3XAI_UAV_destroyed.sqf
Normal file
21
A3XAI/compile/A3XAI_UAV_destroyed.sqf
Normal 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];};
|
66
A3XAI/compile/A3XAI_UGVDetection.sqf
Normal file
66
A3XAI/compile/A3XAI_UGVDetection.sqf
Normal 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))];};
|
23
A3XAI/compile/A3XAI_UGVStartPatrol.sqf
Normal file
23
A3XAI/compile/A3XAI_UGVStartPatrol.sqf
Normal 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
|
21
A3XAI/compile/A3XAI_UGV_destroyed.sqf
Normal file
21
A3XAI/compile/A3XAI_UGV_destroyed.sqf
Normal 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];};
|
172
A3XAI/compile/A3XAI_addGroupManagerSingle.sqf
Normal file
172
A3XAI/compile/A3XAI_addGroupManagerSingle.sqf
Normal 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
|
99
A3XAI/compile/A3XAI_addGroupManangerGlobal.sqf
Normal file
99
A3XAI/compile/A3XAI_addGroupManangerGlobal.sqf
Normal 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
|
11
A3XAI/compile/A3XAI_addItem.sqf
Normal file
11
A3XAI/compile/A3XAI_addItem.sqf
Normal 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
|
8
A3XAI/compile/A3XAI_addLandVehEH.sqf
Normal file
8
A3XAI/compile/A3XAI_addLandVehEH.sqf
Normal 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
|
1
A3XAI/compile/A3XAI_addMapMarker.sqf
Normal file
1
A3XAI/compile/A3XAI_addMapMarker.sqf
Normal 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
|
41
A3XAI/compile/A3XAI_addParaGroup.sqf
Normal file
41
A3XAI/compile/A3XAI_addParaGroup.sqf
Normal 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
|
104
A3XAI/compile/A3XAI_addRespawnQueue.sqf
Normal file
104
A3XAI/compile/A3XAI_addRespawnQueue.sqf
Normal 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
|
8
A3XAI/compile/A3XAI_addTempNVG.sqf
Normal file
8
A3XAI/compile/A3XAI_addTempNVG.sqf
Normal 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
|
21
A3XAI/compile/A3XAI_addTemporaryWaypoint.sqf
Normal file
21
A3XAI/compile/A3XAI_addTemporaryWaypoint.sqf
Normal 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];
|
||||
};
|
11
A3XAI/compile/A3XAI_addToExternalObjectMonitor.sqf
Normal file
11
A3XAI/compile/A3XAI_addToExternalObjectMonitor.sqf
Normal 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
|
8
A3XAI/compile/A3XAI_addUAVEH.sqf
Normal file
8
A3XAI/compile/A3XAI_addUAVEH.sqf
Normal 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
|
9
A3XAI/compile/A3XAI_addUGVEH.sqf
Normal file
9
A3XAI/compile/A3XAI_addUGVEH.sqf
Normal 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
|
7
A3XAI/compile/A3XAI_addUVUnitEH.sqf
Normal file
7
A3XAI/compile/A3XAI_addUVUnitEH.sqf
Normal file
@ -0,0 +1,7 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
if (isNull _this) exitWith {};
|
||||
|
||||
_this addEventHandler ["Killed","_this call A3XAI_handle_death_UV;"];
|
||||
|
||||
true
|
10
A3XAI/compile/A3XAI_addUnitEH.sqf
Normal file
10
A3XAI/compile/A3XAI_addUnitEH.sqf
Normal 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
|
10
A3XAI/compile/A3XAI_addVehAirEH.sqf
Normal file
10
A3XAI/compile/A3XAI_addVehAirEH.sqf
Normal 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
|
104
A3XAI/compile/A3XAI_addVehicleGroup.sqf
Normal file
104
A3XAI/compile/A3XAI_addVehicleGroup.sqf
Normal 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
|
30
A3XAI/compile/A3XAI_addVehicleGunners.sqf
Normal file
30
A3XAI/compile/A3XAI_addVehicleGunners.sqf
Normal 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
|
37
A3XAI/compile/A3XAI_antistuck_air.sqf
Normal file
37
A3XAI/compile/A3XAI_antistuck_air.sqf
Normal 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
|
27
A3XAI/compile/A3XAI_antistuck_aircustom.sqf
Normal file
27
A3XAI/compile/A3XAI_antistuck_aircustom.sqf
Normal 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
|
27
A3XAI/compile/A3XAI_antistuck_generic.sqf
Normal file
27
A3XAI/compile/A3XAI_antistuck_generic.sqf
Normal 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
|
46
A3XAI/compile/A3XAI_antistuck_land.sqf
Normal file
46
A3XAI/compile/A3XAI_antistuck_land.sqf
Normal 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
|
BIN
A3XAI/compile/A3XAI_antistuck_uav.sqf
Normal file
BIN
A3XAI/compile/A3XAI_antistuck_uav.sqf
Normal file
Binary file not shown.
45
A3XAI/compile/A3XAI_antistuck_ugv.sqf
Normal file
45
A3XAI/compile/A3XAI_antistuck_ugv.sqf
Normal 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
|
31
A3XAI/compile/A3XAI_areaSearching.sqf
Normal file
31
A3XAI/compile/A3XAI_areaSearching.sqf
Normal 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
|
15
A3XAI/compile/A3XAI_cancelDynamicSpawn.sqf
Normal file
15
A3XAI/compile/A3XAI_cancelDynamicSpawn.sqf
Normal 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
|
15
A3XAI/compile/A3XAI_cancelRandomSpawn.sqf
Normal file
15
A3XAI/compile/A3XAI_cancelRandomSpawn.sqf
Normal 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
|
6
A3XAI/compile/A3XAI_chance.sqf
Normal file
6
A3XAI/compile/A3XAI_chance.sqf
Normal file
@ -0,0 +1,6 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_result"];
|
||||
_result = ((random 1) < _this);
|
||||
|
||||
_result
|
13
A3XAI/compile/A3XAI_checkAmmoFuel.sqf
Normal file
13
A3XAI/compile/A3XAI_checkAmmoFuel.sqf
Normal 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
|
66
A3XAI/compile/A3XAI_checkClassname.sqf
Normal file
66
A3XAI/compile/A3XAI_checkClassname.sqf
Normal 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
|
45
A3XAI/compile/A3XAI_checkGroupUnits.sqf
Normal file
45
A3XAI/compile/A3XAI_checkGroupUnits.sqf
Normal 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
|
18
A3XAI/compile/A3XAI_checkInActiveNoAggroArea.sqf
Normal file
18
A3XAI/compile/A3XAI_checkInActiveNoAggroArea.sqf
Normal 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
|
18
A3XAI/compile/A3XAI_checkInActiveStaticSpawnArea.sqf
Normal file
18
A3XAI/compile/A3XAI_checkInActiveStaticSpawnArea.sqf
Normal 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
|
18
A3XAI/compile/A3XAI_checkInNoAggroArea.sqf
Normal file
18
A3XAI/compile/A3XAI_checkInNoAggroArea.sqf
Normal 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
|
15
A3XAI/compile/A3XAI_checkIsWeapon.sqf
Normal file
15
A3XAI/compile/A3XAI_checkIsWeapon.sqf
Normal 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
|
20
A3XAI/compile/A3XAI_cleanupReinforcementGroup.sqf
Normal file
20
A3XAI/compile/A3XAI_cleanupReinforcementGroup.sqf
Normal 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
|
11
A3XAI/compile/A3XAI_clearVehicleCargo.sqf
Normal file
11
A3XAI/compile/A3XAI_clearVehicleCargo.sqf
Normal file
@ -0,0 +1,11 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_vehicle"];
|
||||
_vehicle = _this;
|
||||
|
||||
clearWeaponCargoGlobal _vehicle;
|
||||
clearMagazineCargoGlobal _vehicle;
|
||||
clearItemCargoGlobal _vehicle;
|
||||
clearBackpackCargoGlobal _vehicle;
|
||||
|
||||
true
|
11
A3XAI/compile/A3XAI_countVehicleGunners.sqf
Normal file
11
A3XAI/compile/A3XAI_countVehicleGunners.sqf
Normal 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
|
8
A3XAI/compile/A3XAI_createBlackListArea.sqf
Normal file
8
A3XAI/compile/A3XAI_createBlackListArea.sqf
Normal 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]
|
8
A3XAI/compile/A3XAI_createBlackListAreaDynamic.sqf
Normal file
8
A3XAI/compile/A3XAI_createBlackListAreaDynamic.sqf
Normal 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]
|
8
A3XAI/compile/A3XAI_createBlackListAreaRandom.sqf
Normal file
8
A3XAI/compile/A3XAI_createBlackListAreaRandom.sqf
Normal 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]
|
20
A3XAI/compile/A3XAI_createBlacklistAreaQueue.sqf
Normal file
20
A3XAI/compile/A3XAI_createBlacklistAreaQueue.sqf
Normal 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;
|
||||
};
|
15
A3XAI/compile/A3XAI_createCustomInfantryQueue.sqf
Normal file
15
A3XAI/compile/A3XAI_createCustomInfantryQueue.sqf
Normal 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;
|
||||
};
|
57
A3XAI/compile/A3XAI_createCustomInfantrySpawnQueue.sqf
Normal file
57
A3XAI/compile/A3XAI_createCustomInfantrySpawnQueue.sqf
Normal 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
|
44
A3XAI/compile/A3XAI_createCustomSpawn.sqf
Normal file
44
A3XAI/compile/A3XAI_createCustomSpawn.sqf
Normal 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
|
||||
};
|
20
A3XAI/compile/A3XAI_createCustomVehicleQueue.sqf
Normal file
20
A3XAI/compile/A3XAI_createCustomVehicleQueue.sqf
Normal 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;
|
||||
};
|
11
A3XAI/compile/A3XAI_createGroup.sqf
Normal file
11
A3XAI/compile/A3XAI_createGroup.sqf
Normal 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
|
74
A3XAI/compile/A3XAI_createInfantryQueue.sqf
Normal file
74
A3XAI/compile/A3XAI_createInfantryQueue.sqf
Normal 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
|
28
A3XAI/compile/A3XAI_createNoAggroArea.sqf
Normal file
28
A3XAI/compile/A3XAI_createNoAggroArea.sqf
Normal 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
|
46
A3XAI/compile/A3XAI_createRandomInfantrySpawnQueue.sqf
Normal file
46
A3XAI/compile/A3XAI_createRandomInfantrySpawnQueue.sqf
Normal 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
|
19
A3XAI/compile/A3XAI_createTriggerArea.sqf
Normal file
19
A3XAI/compile/A3XAI_createTriggerArea.sqf
Normal 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
|
24
A3XAI/compile/A3XAI_createUnit.sqf
Normal file
24
A3XAI/compile/A3XAI_createUnit.sqf
Normal 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
|
16
A3XAI/compile/A3XAI_create_UV_unit.sqf
Normal file
16
A3XAI/compile/A3XAI_create_UV_unit.sqf
Normal 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
|
34
A3XAI/compile/A3XAI_customHeliDetect.sqf
Normal file
34
A3XAI/compile/A3XAI_customHeliDetect.sqf
Normal 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];
|
16
A3XAI/compile/A3XAI_debugMarkerLocation.sqf
Normal file
16
A3XAI/compile/A3XAI_debugMarkerLocation.sqf
Normal 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];
|
||||
};
|
20
A3XAI/compile/A3XAI_defensiveAggression.sqf
Normal file
20
A3XAI/compile/A3XAI_defensiveAggression.sqf
Normal 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
|
42
A3XAI/compile/A3XAI_deleteCustomSpawn.sqf
Normal file
42
A3XAI/compile/A3XAI_deleteCustomSpawn.sqf
Normal 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
|
28
A3XAI/compile/A3XAI_deleteGroup.sqf
Normal file
28
A3XAI/compile/A3XAI_deleteGroup.sqf
Normal 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
|
75
A3XAI/compile/A3XAI_despawnUniversal.sqf
Normal file
75
A3XAI/compile/A3XAI_despawnUniversal.sqf
Normal 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
|
84
A3XAI/compile/A3XAI_despawn_dynamic.sqf
Normal file
84
A3XAI/compile/A3XAI_despawn_dynamic.sqf
Normal 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
|
||||
};
|
84
A3XAI/compile/A3XAI_despawn_random.sqf
Normal file
84
A3XAI/compile/A3XAI_despawn_random.sqf
Normal 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
|
||||
};
|
92
A3XAI/compile/A3XAI_despawn_static.sqf
Normal file
92
A3XAI/compile/A3XAI_despawn_static.sqf
Normal 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
|
13
A3XAI/compile/A3XAI_ejectParachute.sqf
Normal file
13
A3XAI/compile/A3XAI_ejectParachute.sqf
Normal 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
|
30
A3XAI/compile/A3XAI_execEveryLoop_air.sqf
Normal file
30
A3XAI/compile/A3XAI_execEveryLoop_air.sqf
Normal 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
|
22
A3XAI/compile/A3XAI_execEveryLoop_infantry.sqf
Normal file
22
A3XAI/compile/A3XAI_execEveryLoop_infantry.sqf
Normal 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
|
43
A3XAI/compile/A3XAI_execEveryLoop_uav.sqf
Normal file
43
A3XAI/compile/A3XAI_execEveryLoop_uav.sqf
Normal 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
|
43
A3XAI/compile/A3XAI_execEveryLoop_ugv.sqf
Normal file
43
A3XAI/compile/A3XAI_execEveryLoop_ugv.sqf
Normal 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
|
37
A3XAI/compile/A3XAI_execEveryLoop_vehicle.sqf
Normal file
37
A3XAI/compile/A3XAI_execEveryLoop_vehicle.sqf
Normal 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
|
31
A3XAI/compile/A3XAI_findSpawnPos.sqf
Normal file
31
A3XAI/compile/A3XAI_findSpawnPos.sqf
Normal 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
|
69
A3XAI/compile/A3XAI_fixStuckGroup.sqf
Normal file
69
A3XAI/compile/A3XAI_fixStuckGroup.sqf
Normal 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
|
39
A3XAI/compile/A3XAI_forceBehavior.sqf
Normal file
39
A3XAI/compile/A3XAI_forceBehavior.sqf
Normal 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
|
20
A3XAI/compile/A3XAI_forceRespawnGroup.sqf
Normal file
20
A3XAI/compile/A3XAI_forceRespawnGroup.sqf
Normal 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
|
29
A3XAI/compile/A3XAI_generateGroupLoot.sqf
Normal file
29
A3XAI/compile/A3XAI_generateGroupLoot.sqf
Normal 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
|
163
A3XAI/compile/A3XAI_generateLoadout.sqf
Normal file
163
A3XAI/compile/A3XAI_generateLoadout.sqf
Normal 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
|
47
A3XAI/compile/A3XAI_generateLootOnDeath.sqf
Normal file
47
A3XAI/compile/A3XAI_generateLootOnDeath.sqf
Normal 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
Loading…
Reference in New Issue
Block a user