Re-upload.
This commit is contained in:
parent
5c3eec93d8
commit
61a27ec36a
1
4. SQF/addons/a3xai/$PREFIX$
Normal file
1
4. SQF/addons/a3xai/$PREFIX$
Normal file
@ -0,0 +1 @@
|
||||
A3XAI
|
1
4. SQF/addons/a3xai/PboPrefix.txt
Normal file
1
4. SQF/addons/a3xai/PboPrefix.txt
Normal file
@ -0,0 +1 @@
|
||||
A3EAI
|
@ -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
|
@ -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
|
@ -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
4. SQF/addons/a3xai/SHK_pos/A3XAI_SHK_pos_fnc_getpos.sqf
Normal file
13
4. SQF/addons/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]
|
@ -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]
|
@ -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]
|
@ -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]
|
@ -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]
|
@ -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
4. SQF/addons/a3xai/SHK_pos/A3XAI_SHK_pos_fnc_isincircle.sqf
Normal file
36
4. SQF/addons/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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
4. SQF/addons/a3xai/SHK_pos/A3XAI_SHK_pos_getpos.sqf
Normal file
170
4. SQF/addons/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
4. SQF/addons/a3xai/SHK_pos/A3XAI_SHK_pos_getposmarker.sqf
Normal file
101
4. SQF/addons/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
4. SQF/addons/a3xai/SHK_pos/A3XAI_SHK_pos_init.sqf
Normal file
105
4. SQF/addons/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
|
||||
};
|
@ -0,0 +1,233 @@
|
||||
#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 select 2;
|
||||
_unitType = _unitGroup getVariable ["unitType",""];
|
||||
_allowWater = (_unitType in ["aircustom","air_reinforce"]);
|
||||
_searchLoot = _unitType in ["static","vehiclecrew","dynamic","random"];
|
||||
_isVehicle = (_unitType isEqualTo "landcustom");
|
||||
_combatMode = (combatMode _unitGroup);
|
||||
_behavior = (behaviour (leader _unitGroup));
|
||||
|
||||
if (_max_dist < 75) then {_unitGroup setSpeedMode "LIMITED"};
|
||||
|
||||
_randomizeChance = linearConversion [125,350,_max_dist,0.25,0.45,true];
|
||||
//diag_log format ["DEBUG: PatrolDist %1 has RandomizeChance %2",_max_dist,_randomizeChance];
|
||||
|
||||
_wpStatements = call {
|
||||
if (_searchLoot && {_max_dist > 100}) exitWith {format ["if !(local this) exitWith {}; if (%1 call 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;};
|
||||
|
||||
_allowInNoAggroArea = ([_pos,NO_AGGRO_RANGE_MAN] call A3XAI_checkInNoAggroArea);
|
||||
_wp_count = 4 + (floor random 3) + (floor (_max_dist / 100 ));
|
||||
_angle = (360 / (_wp_count -1));
|
||||
|
||||
_newangle = 0;
|
||||
_wp_array = [];
|
||||
_slack = _max_dist / 5.5;
|
||||
_completionRadius = if (_isVehicle) then {(25 + _slack)} else {(10 + _slack)};
|
||||
if ( _slack < 20 ) then { _slack = 20 };
|
||||
|
||||
_angle_offset = random 180;
|
||||
while {count _wp_array < _wp_count} do {
|
||||
private ["_x1","_y1","_wp_pos", "_prepos","_bldgpos","_bldgs","_a","_b"];
|
||||
|
||||
_newangle = (count _wp_array * _angle) + _angle_offset;
|
||||
|
||||
if ((_newangle > 360) || {_newangle < 0}) then
|
||||
{
|
||||
_newangle = abs (abs (_newangle) - 360);
|
||||
};
|
||||
|
||||
if ((random 1) < 0.5) then
|
||||
{
|
||||
_newangle = -_newangle;
|
||||
|
||||
if ((_newangle > 360) || {_newangle < 0}) then
|
||||
{
|
||||
_newangle = abs (abs (_newangle) - 360);
|
||||
};
|
||||
};
|
||||
|
||||
_x1 = _center_x - (sin _newangle * _max_dist);
|
||||
_y1 = _center_y - (cos _newangle * _max_dist);
|
||||
|
||||
_prepos = [_x1, _y1, _center_z];
|
||||
if ( isNil "_center_z" ) then {
|
||||
_prepos = [_x1, _y1];
|
||||
};
|
||||
|
||||
_wp_pos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
|
||||
|
||||
_retry = false;
|
||||
if (((surfaceIsWater _wp_pos) && {!_allowWater}) or {([_wp_pos,NO_AGGRO_RANGE_MAN] call A3XAI_checkInNoAggroArea) or {_allowInNoAggroArea}}) then {
|
||||
_retry = true;
|
||||
_retryCount = 0;
|
||||
_retryPos = [];
|
||||
_newMaxDist = _max_dist;
|
||||
while {_retry && {_retryCount < 2}} do {
|
||||
_newMaxDist = _newMaxDist * 0.5;
|
||||
_x1 = _center_x - (sin _newangle * _newMaxDist);
|
||||
_y1 = _center_y - (cos _newangle * _newMaxDist);
|
||||
|
||||
_prepos = [_x1, _y1, _center_z];
|
||||
if ( isNil "_center_z" ) then {
|
||||
_prepos = [_x1, _y1];
|
||||
};
|
||||
|
||||
_retryPos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
|
||||
_retryCount = _retryCount + 1;
|
||||
if ((!(surfaceIsWater _wp_pos) or {_allowWater}) && (!([_wp_pos,NO_AGGRO_RANGE_MAN] call A3XAI_checkInNoAggroArea) or {_allowInNoAggroArea})) then {
|
||||
_retry = false;
|
||||
_wp_pos = _retryPos;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if !(_retry) then {
|
||||
_a = 0 + (_wp_pos select 0);
|
||||
_b = 0 + (_wp_pos select 1);
|
||||
|
||||
if (_searchLoot) then {
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// The following code is an extract from Random Building Position Script v1.0 by Tophe of Östgöta Ops
|
||||
//////////////////////////////////////////////////////////////////
|
||||
_bldgpos = [];
|
||||
_bldgs = nearestObjects [[_a,_b,0], ["HouseBase"], 50];
|
||||
{
|
||||
private["_i","_y"];
|
||||
_i = 0;
|
||||
_y = _x buildingPos _i;
|
||||
//while {format["%1", _y] != "[0,0,0]"} do {
|
||||
while {!(_y isEqualTo [0,0,0]) } do {
|
||||
//_bldgpos = _bldgpos + [_y];
|
||||
_bldgpos pushBack _y;
|
||||
_i = _i + 1;
|
||||
_y = _x buildingPos _i;
|
||||
};
|
||||
} forEach _bldgs;
|
||||
|
||||
if(count _bldgpos != 0) then {_wp_pos = _bldgpos call A3XAI_selectRandom;};
|
||||
} else {
|
||||
if (_isVehicle) then {
|
||||
_nearRoads = _wp_pos nearRoads ((_max_dist/2) min 100);
|
||||
_roadsCount = count _nearRoads;
|
||||
_returnPos = [];
|
||||
if (_roadsCount > 0) then {
|
||||
_returnPos = getPosATL (_nearRoads select 0);
|
||||
if (_roadsCount > 1) then {
|
||||
for "_i" from 1 to (_roadsCount -1) do {
|
||||
_comparePos = getPosATL (_nearRoads select _i);
|
||||
if ((_comparePos distance _wp_pos) < (_returnPos distance _wp_pos)) then {
|
||||
_returnPos = _comparePos;
|
||||
};
|
||||
};
|
||||
};
|
||||
_wp_pos = _returnPos;
|
||||
};
|
||||
};
|
||||
};
|
||||
//_wp_array = _wp_array + [_wp_pos];
|
||||
_wp_array pushBack _wp_pos;
|
||||
};
|
||||
|
||||
uiSleep 0.25;
|
||||
};
|
||||
|
||||
for "_i" from 1 to (_wp_count - 1) do
|
||||
{
|
||||
private ["_wp","_cur_pos"];
|
||||
|
||||
_cur_pos = (_wp_array select _i);
|
||||
|
||||
_wp = _unitGroup addWaypoint [_cur_pos, 0];
|
||||
_wp setWaypointType "MOVE";
|
||||
_wp setWaypointCompletionRadius _completionRadius;
|
||||
_wp setWaypointTimeout [_wpTimeouts select 0, _wpTimeouts select 1, _wpTimeouts select 2];
|
||||
_wp setWaypointStatements ["true",_wpStatements];
|
||||
_wp setWaypointCombatMode _combatMode;
|
||||
_wp setWaypointBehaviour _behavior;
|
||||
uiSleep 0.25;
|
||||
};
|
||||
|
||||
_endWP = [_pos, 0, 50, 6, 0, 50 * (pi / 180), 0, [],[_pos]] call BIS_fnc_findSafePos;
|
||||
|
||||
// End back near start point and then pick a new random point
|
||||
_wp1 = _unitGroup addWaypoint [_endWP, 0];
|
||||
_wp1 setWaypointType "MOVE";
|
||||
_wp1 setWaypointCompletionRadius (_max_dist max 50);
|
||||
_wp1 setWaypointCombatMode _combatMode;
|
||||
_wp1 setWaypointBehaviour _behavior;
|
||||
[_unitGroup,(count waypoints _unitGroup)] setWaypointStatements ["true", "if !(local this) exitWith {}; group this setCurrentWaypoint [(group this), (round (random 2) + 1)];"];
|
||||
|
||||
// Cycle in case we reach the end
|
||||
_wp2 = _unitGroup addWaypoint [_endWP, 0];
|
||||
_wp2 setWaypointType "CYCLE";
|
||||
_wp2 setWaypointCompletionRadius (_max_dist max 50);
|
||||
_wp2 setWaypointCombatMode _combatMode;
|
||||
_wp2 setWaypointBehaviour _behavior;
|
||||
|
||||
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
|
||||
if ((getWPPos [_unitGroup,_i]) isEqualTo [0,0,0]) then {
|
||||
diag_log format ["A3XAI Error: Waypoint %1 is invalid position.",[_unitGroup,_i]];
|
||||
deleteWaypoint [_unitGroup,_i];
|
||||
};
|
||||
};
|
||||
|
||||
if (A3XAI_enableHC && {_unitType in A3XAI_HCAllowedTypes}) then {_unitGroup setVariable ["HC_Ready",true];};
|
||||
|
||||
true
|
@ -0,0 +1,62 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_canCall","_vehicle","_detectStartPos","_searchLength"];
|
||||
_unitGroup = _this select 0;
|
||||
|
||||
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3XAI_forceBehavior};
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||
_canCall = true;
|
||||
_searchLength = _unitGroup getVariable "SearchLength";
|
||||
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
|
||||
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
|
||||
|
||||
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 getVariable ["IsDetecting",true];
|
||||
|
||||
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||
_vehPos = getPosATL _vehicle;
|
||||
_canReveal = ((combatMode _unitGroup) in ["YELLOW","RED"]);
|
||||
_detected = (getPosATL _vehicle) nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UAV];
|
||||
if ((count _detected) > 5) then {_detected resize 5};
|
||||
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||
{
|
||||
_playerPos = getPosATL _x;
|
||||
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {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 (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||
_unitGroup reveal [_x,2.5];
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[41+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3XAI_radioSend;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
uiSleep 0.1;
|
||||
} forEach _detected;
|
||||
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||
uiSleep 15;
|
||||
|
||||
_unitGroup getVariable ["IsDetecting",false];
|
||||
};
|
||||
|
||||
_vehicle flyInHeight (FLYINHEIGHT_UAV_PATROLLING_BASE + (random FLYINHEIGHT_UAV_PATROLLING_VARIANCE));
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -0,0 +1,30 @@
|
||||
#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];
|
||||
|
||||
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance2D _exitWaypoint)];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};
|
@ -0,0 +1,58 @@
|
||||
#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,"Behavior_Reset"] 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 getVariable ["IsDetecting",true];
|
||||
|
||||
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||
private ["_detected","_detectOrigin","_startPos","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||
_vehPos = getPosATL _vehicle;
|
||||
_startPos = getPosATL _vehicle;
|
||||
_canReveal = ((combatMode _unitGroup) in ["YELLOW","RED"]);
|
||||
_detectOrigin = [_startPos,0,getDir _vehicle,1] call A3XAI_SHK_pos;
|
||||
_detected = _detectOrigin nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UGV];
|
||||
if ((count _detected) > 5) then {_detected resize 5};
|
||||
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||
{
|
||||
_playerPos = getPosATL _x;
|
||||
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {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 (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||
_unitGroup reveal [_x,2.5];
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[51+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3XAI_radioSend;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
uiSleep 0.1;
|
||||
} forEach _detected;
|
||||
if (((_vehicle distance2D _detectStartPos) > DETECT_LENGTH_UGV_2D) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||
uiSleep 15;
|
||||
};
|
||||
|
||||
_unitGroup getVariable ["IsDetecting",false];
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -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];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};
|
@ -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
|
@ -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 ["vehicle_disabled",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];
|
@ -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) && {_damage > 0.1} && {(combatMode _unitGroup isEqualTo "BLUE")}) then {
|
||||
_aggroExpiry = diag_tickTime + DEFENSIVE_AGGRESSION_TIME;
|
||||
_vehicle setVariable ["AggroTime",_aggroExpiry];
|
||||
[_unitGroup,"Behavior_Reset"] call A3XAI_forceBehavior;
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Defensive aggression enabled for %1 %2",_unitGroup,(typeOf _vehicle)];};
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,31 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_action", "_unitGroup"];
|
||||
|
||||
_action = _this select 1;
|
||||
_unitGroup = _this select 0;
|
||||
|
||||
if (_action isEqualTo "IgnoreEnemies") exitWith {
|
||||
_unitGroup setBehaviour "CARELESS";
|
||||
_unitGroup setCombatMode "BLUE";
|
||||
{_x doWatch objNull} forEach (units _unitGroup);
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
if (_action isEqualTo "Behavior_Reset") exitWith {
|
||||
_unitGroup setBehaviour "AWARE";
|
||||
_unitGroup setCombatMode "YELLOW";
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
if (_action isEqualTo "DefendOnly") exitWith {
|
||||
_unitGroup setBehaviour "AWARE";
|
||||
_unitGroup setCombatMode "GREEN";
|
||||
{_x doWatch objNull} forEach (units _unitGroup);
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
false
|
@ -0,0 +1,57 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_detectBase","_vehicle","_canParaDrop","_detectStartPos","_searchLength"];
|
||||
_unitGroup = _this select 0;
|
||||
|
||||
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3XAI_forceBehavior};
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||
_searchLength = _unitGroup getVariable "SearchLength";
|
||||
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
|
||||
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
|
||||
|
||||
_detectStartPos = getPosATL _vehicle;
|
||||
_canParaDrop = ((diag_tickTime - (_unitGroup getVariable ["HeliLastParaDrop",-A3XAI_paraDropCooldown])) > A3XAI_paraDropCooldown);
|
||||
_vehicle flyInHeight (FLYINHEIGHT_AIR_SEARCHING_BASE + (random FLYINHEIGHT_AIR_SEARCHING_VARIANCE));
|
||||
_unitGroup getVariable ["IsDetecting",true];
|
||||
|
||||
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||
_vehPos = getPosATL _vehicle;
|
||||
_canReveal = ((combatMode _unitGroup) in ["YELLOW","RED"]);
|
||||
_detected = _vehPos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR];
|
||||
if ((count _detected) > 5) then {_detected resize 5};
|
||||
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||
{
|
||||
_playerPos = getPosATL _x;
|
||||
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||
if (_canParaDrop) then {
|
||||
_canParaDrop = false;
|
||||
_unitGroup setVariable ["HeliLastParaDrop",diag_tickTime];
|
||||
_nul = [_unitGroup,_vehicle,_x] spawn A3XAI_heliParaDrop;
|
||||
};
|
||||
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||
_heliAimPos = aimPos _vehicle;
|
||||
_playerEyePos = eyePos _x;
|
||||
if (((lineIntersectsSurfaces [_heliAimPos,_playerEyePos,_vehicle,_x,true,1]) isEqualTo []) && {A3XAI_airDetectChance call A3XAI_chance}) then {
|
||||
_unitGroup reveal [_x,2.5];
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3XAI_radioSend;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
uiSleep 0.1;
|
||||
} forEach _detected;
|
||||
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||
uiSleep 15;
|
||||
|
||||
_unitGroup getVariable ["IsDetecting",false];
|
||||
};
|
||||
|
||||
_vehicle flyInHeight (FLYINHEIGHT_AIR_PATROLLING_BASE + (random FLYINHEIGHT_AIR_PATROLLING_VARIANCE));
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -0,0 +1,30 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_tooClose","_detectionWaypoint","_exitWaypoint","_vehicle","_dir","_locationSelected"];
|
||||
_unitGroup = _this select 0;
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||
|
||||
_tooClose = true;
|
||||
_locationSelected = [0,0,0];
|
||||
|
||||
while {_tooClose} do {
|
||||
_locationSelected = (A3XAI_locationsAir call A3XAI_selectRandom) select 1;
|
||||
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > NEXT_WP_DIST_AIR) then {
|
||||
_tooClose = false;
|
||||
} else {
|
||||
uiSleep 0.1;
|
||||
};
|
||||
};
|
||||
|
||||
_dir = [_locationSelected,_vehicle] call BIS_fnc_dirTo;
|
||||
_detectionWaypoint = [_locationSelected,WP_POS_INGRESS_BASE_AIR + (random WP_POS_INGRESS_VARIANCE_AIR),_dir,1] call A3XAI_SHK_pos;
|
||||
[_unitGroup,0] setWaypointPosition [_detectionWaypoint,0];
|
||||
|
||||
_dir = [_vehicle,_locationSelected] call BIS_fnc_dirTo;
|
||||
_exitWaypoint = [_detectionWaypoint,WP_POS_EGRESS_BASE_AIR + (random WP_POS_EGRESS_VARIANCE_AIR),_dir,1] call A3XAI_SHK_pos;
|
||||
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
|
||||
|
||||
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance2D _exitWaypoint)];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};
|
141
4. SQF/addons/a3xai/compile/A3XAI_behavior/A3XAI_huntKiller.sqf
Normal file
141
4. SQF/addons/a3xai/compile/A3XAI_behavior/A3XAI_huntKiller.sqf
Normal file
@ -0,0 +1,141 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_targetPlayer","_startPos","_chaseDistance","_enableHCReady","_nearBlacklistedAreas","_targetPlayerPos"];
|
||||
|
||||
_targetPlayer = _this select 0;
|
||||
_unitGroup = _this select 1;
|
||||
|
||||
//Disable killer-finding for dynamic AI in hunting mode
|
||||
if (_unitGroup getVariable ["seekActive",false]) exitWith {};
|
||||
|
||||
//If group is already pursuing player and target player has killed another group member, then extend pursuit time.
|
||||
if (((_unitGroup getVariable ["pursuitTime",0]) > 0) && {((_unitGroup getVariable ["targetKiller",""]) isEqualTo (name _targetPlayer))}) exitWith {
|
||||
_unitGroup setVariable ["pursuitTime",((_unitGroup getVariable ["pursuitTime",0]) + 20)];
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Pursuit time +20 sec for Group %1 (Target: %2) to %3 seconds.",_unitGroup,name _targetPlayer,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime]};
|
||||
};
|
||||
|
||||
_enableHCReady = false;
|
||||
if (_unitGroup getVariable ["HC_Ready",false]) then { //If HC mode enabled and AI group is controlled by server, prevent it from being transferred to HC until hunting mode is over.
|
||||
_unitGroup setVariable ["HC_Ready",false];
|
||||
_enableHCReady = true;
|
||||
};
|
||||
|
||||
_startPos = _unitGroup getVariable ["trigger",(getPosASL (leader _unitGroup))];
|
||||
_chaseDistance = _unitGroup getVariable ["patrolDist",250];
|
||||
_targetPlayerPos = getPosATL _targetPlayer;
|
||||
_nearBlacklistedAreas = nearestLocations [_targetPlayerPos,[BLACKLIST_OBJECT_GENERAL],1500];
|
||||
|
||||
_unitGroup setFormDir ([(leader _unitGroup),_targetPlayerPos] call BIS_fnc_dirTo);
|
||||
|
||||
if ((_startPos distance _targetPlayerPos) < _chaseDistance) then {
|
||||
private ["_leader","_ableToChase","_marker"];
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Group %1 has entered pursuit state for 180 seconds. Target: %2.",_unitGroup,_targetPlayer];};
|
||||
|
||||
//Set pursuit timer
|
||||
_unitGroup setVariable ["pursuitTime",diag_tickTime+180];
|
||||
_unitGroup setVariable ["targetKiller",name _targetPlayer];
|
||||
|
||||
|
||||
if (A3XAI_enableDebugMarkers) then {
|
||||
_markername = format ["%1 Target",_unitGroup];
|
||||
if (_markername in allMapMarkers) then {deleteMarker _markername; uiSleep 0.5;};
|
||||
_marker = createMarker [_markername,getPosASL _targetPlayer];
|
||||
_marker setMarkerText _markername;
|
||||
_marker setMarkerType "mil_warning";
|
||||
_marker setMarkerColor "ColorRed";
|
||||
_marker setMarkerBrush "Solid";
|
||||
};
|
||||
|
||||
//Begin pursuit state.
|
||||
_ableToChase = true;
|
||||
while {
|
||||
_ableToChase &&
|
||||
{isPlayer _targetPlayer} &&
|
||||
{alive _targetPlayer} &&
|
||||
{((_startPos distance _targetPlayer) < _chaseDistance)} &&
|
||||
{(vehicle _targetPlayer) isKindOf "Land"}
|
||||
} do {
|
||||
_targetPlayerPos = getPosATL _targetPlayer;
|
||||
if (({_targetPlayerPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
|
||||
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
|
||||
(units _unitGroup) doMove _targetPlayerPos;
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: AI group %1 in pursuit state. Pursuit time remaining: %2 seconds.",_unitGroup,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime];};
|
||||
|
||||
if ((A3XAI_enableRadioMessages) && {0.7 call A3XAI_chance}) then {
|
||||
_leader = (leader _unitGroup);
|
||||
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER}) then {
|
||||
_nearbyUnits = _targetPlayerPos nearEntities [[PLAYER_UNITS,"LandVehicle"],TRANSMIT_RANGE_RADIO_HUNTKILLER];
|
||||
if !(_nearbyUnits isEqualTo []) then { //Have at least 1 player to send a message to
|
||||
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then { //Have at least 1 AI unit to send a message from
|
||||
_speechIndex = (floor (random 3));
|
||||
_radioSpeech = call {
|
||||
if (_speechIndex isEqualTo 0) exitWith {
|
||||
[1,[(name _leader),(name _targetPlayer)]]
|
||||
};
|
||||
if (_speechIndex isEqualTo 1) exitWith {
|
||||
[2,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]
|
||||
};
|
||||
if (_speechIndex isEqualTo 2) exitWith {
|
||||
[3,[(name _leader),round (_leader distance _targetPlayer)]]
|
||||
};
|
||||
[0,[]]
|
||||
};
|
||||
{
|
||||
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||
[_x,_radioSpeech] call A3XAI_radioSend;
|
||||
};
|
||||
} count _nearbyUnits;
|
||||
} else {
|
||||
{
|
||||
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||
[_x,[0,[]]] call A3XAI_radioSend;
|
||||
};
|
||||
} count _nearbyUnits;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (A3XAI_enableDebugMarkers) then {
|
||||
_marker setMarkerPos (getPosASL _targetPlayer);
|
||||
};
|
||||
_ableToChase = ((!isNull _unitGroup) && {diag_tickTime < (_unitGroup getVariable ["pursuitTime",0])} && {(_unitGroup getVariable ["GroupSize",0]) > 0});
|
||||
if (_ableToChase) then {uiSleep 20};
|
||||
};
|
||||
|
||||
if !(isNull _unitGroup) then {
|
||||
//End of pursuit state. Re-enable patrol state.
|
||||
_unitGroup setVariable ["pursuitTime",0];
|
||||
_unitGroup setVariable ["targetKiller",""];
|
||||
//_unitGroup lockWP false;
|
||||
|
||||
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
|
||||
_waypoints = (waypoints _unitGroup);
|
||||
_unitGroup setCurrentWaypoint (_waypoints call A3XAI_selectRandom);
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Pursuit state ended for group %1. Returning to patrol state.",_unitGroup];};
|
||||
|
||||
if (A3XAI_enableRadioMessages) then {
|
||||
_leader = (leader _unitGroup);
|
||||
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER} && {((_unitGroup getVariable ["GroupSize",0]) > 1)} && {isPlayer _targetPlayer}) then {
|
||||
_radioText = if (alive _targetPlayer) then {4} else {5};
|
||||
_radioSpeech = [_radioText,[name (leader _unitGroup)]];
|
||||
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTKILLER];
|
||||
{
|
||||
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||
[_x,_radioSpeech] call A3XAI_radioSend;
|
||||
};
|
||||
} count _nearbyUnits;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (_enableHCReady) then {
|
||||
_unitGroup setVariable ["HC_Ready",true];
|
||||
};
|
||||
};
|
||||
|
||||
if (A3XAI_enableDebugMarkers) then {
|
||||
deleteMarker _marker;
|
||||
};
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_targetPlayer", "_waypoint", "_leader", "_nearbyUnits", "_index", "_radioSpeech", "_searchPos","_triggerPos","_nearBlacklistedAreas","_targetPos"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
_triggerPos = getPosATL (_unitGroup getVariable ["trigger",objNull]);
|
||||
_targetPlayer = _unitGroup getVariable ["targetplayer",objNull];
|
||||
|
||||
try {
|
||||
if !(isPlayer _targetPlayer) then {
|
||||
throw "Target is not a player.";
|
||||
};
|
||||
|
||||
_nearBlacklistedAreas = nearestLocations [_targetPlayer,[BLACKLIST_OBJECT_GENERAL],1500];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Hunter group %1 has target player %2 and anchor pos %3.",_unitGroup,_targetPlayer,_triggerPos];};
|
||||
|
||||
if (
|
||||
(isPlayer _targetPlayer) &&
|
||||
{alive _targetPlayer} &&
|
||||
{(vehicle _targetPlayer) isKindOf "Land"} &&
|
||||
{(_targetPlayer distance _triggerPos) < SEEK_RANGE_HUNTER}
|
||||
) then {
|
||||
_waypoint = [_unitGroup,0];
|
||||
_targetPos = getPosATL _targetPlayer;
|
||||
if (({_targetPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
|
||||
if (((getWPPos _waypoint) distance _targetPlayer) > 20) then {
|
||||
_waypoint setWPPos _targetPos;
|
||||
//diag_log format ["Debug: Hunter group %1 is seeking player %2 (position: %3).",_unitGroup,_targetPlayer,(getPosATL _targetPlayer)];
|
||||
} else {
|
||||
_searchPos = [(getWPPos _waypoint),20+(random 20),(random 360),0] call A3XAI_SHK_pos;
|
||||
_waypoint setWPPos _searchPos;
|
||||
};
|
||||
};
|
||||
|
||||
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
|
||||
_unitGroup setCurrentWaypoint _waypoint;
|
||||
|
||||
if (A3XAI_enableRadioMessages) then {
|
||||
_leader = (leader _unitGroup);
|
||||
if ((_leader distance _targetPlayer) < RADIO_RECEPTION_RANGE) then {
|
||||
_nearbyUnits = _targetPos nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTER];
|
||||
if !(_nearbyUnits isEqualTo []) then {
|
||||
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
|
||||
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then {
|
||||
_index = (floor (random 4));
|
||||
_radioSpeech = call {
|
||||
if (_index isEqualTo 0) exitWith {[11,[(name _leader),(name _targetPlayer)]]};
|
||||
if (_index isEqualTo 1) exitWith {[12,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]};
|
||||
if (_index isEqualTo 2) exitWith {[13,[(name _leader),round (_leader distance _targetPlayer)]]};
|
||||
if (_index > 2) exitWith {[0,[]]};
|
||||
[0,[]]
|
||||
};
|
||||
{
|
||||
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||
[_x,_radioSpeech] call A3XAI_radioSend;
|
||||
};
|
||||
} count _nearbyUnits;
|
||||
} else {
|
||||
{
|
||||
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||
[_x,[0,[]]] call A3XAI_radioSend;
|
||||
};
|
||||
} count _nearbyUnits;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Dynamic group %1 has located player %2.",_unitGroup,_targetPlayer];};
|
||||
} else {
|
||||
throw "Hunt ended.";
|
||||
};
|
||||
} catch {
|
||||
[_unitGroup,0] setWaypointStatements ["true","if !(local this) exitWith {}; if ((random 1) < 0.50) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];};"];
|
||||
0 = [_unitGroup,_triggerPos,PATROL_DIST_DYNAMIC] spawn A3XAI_BIN_taskPatrol;
|
||||
_unitGroup setSpeedMode "FULL";
|
||||
if (A3XAI_enableHC && {isDedicated}) then {_unitGroup setVariable ["MiscData",nil];};
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Dynamic group %1 is patrolling area. (%2)",_unitGroup,_exception];};
|
||||
};
|
@ -0,0 +1,85 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_waypoint", "_vehicle", "_endTime", "_vehiclePos", "_nearUnits", "_vehPos", "_despawnPos", "_reinforcePos","_vehicleArmed","_paraDrop","_reinforceTime"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
|
||||
if (!hasInterface && !isDedicated) exitWith {diag_log format ["Error: %1 executed on headless client.",__FILE__];};
|
||||
if !((typeName _unitGroup) isEqualTo "GROUP") exitWith {diag_log format ["A3XAI Error: Invalid group %1 provided to %2.",_unitGroup,__FILE__];};
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||
_vehicleArmed = ((({_x call A3XAI_checkIsWeapon} count (weapons _vehicle)) > 0) || {({_x call A3XAI_checkIsWeapon} count (_vehicle weaponsTurret [-1])) > 0} || {(_vehicle call A3XAI_countVehicleGunners) > 0});
|
||||
_reinforcePos = _unitGroup getVariable ["ReinforcePos",[0,0,0]];
|
||||
|
||||
if (_vehicleArmed) then {
|
||||
_waypoint = [_unitGroup,0];
|
||||
_waypoint setWaypointStatements ["true",""];
|
||||
_waypoint setWaypointType "GUARD";
|
||||
_waypoint setWaypointBehaviour "AWARE";
|
||||
_waypoint setWaypointCombatMode "RED";
|
||||
|
||||
if (local _unitGroup) then {
|
||||
_unitGroup setCurrentWaypoint _waypoint;
|
||||
} else {
|
||||
A3XAI_setCurrentWaypoint_PVC = _waypoint;
|
||||
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_setCurrentWaypoint_PVC";
|
||||
};
|
||||
|
||||
_reinforceTime = missionNamespace getVariable [format ["A3XAI_airReinforcementDuration%1",_unitGroup getVariable ["unitLevel",0]],0];
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Group %1 is now reinforcing for %2 seconds.",_unitGroup,_reinforceTime];};
|
||||
|
||||
_unitGroup setSpeedMode "LIMITED";
|
||||
_endTime = diag_tickTime + _reinforceTime;
|
||||
while {(diag_tickTime < _endTime) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {(_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce"}} do {
|
||||
if (local _unitGroup) then {
|
||||
_vehiclePos = getPosATL _vehicle;
|
||||
_vehiclePos set [2,0];
|
||||
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR_REINFORCE];
|
||||
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
|
||||
{
|
||||
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3} && {(lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []}) then {
|
||||
_unitGroup reveal [_x,3];
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3XAI_radioSend;
|
||||
};
|
||||
};
|
||||
} forEach _nearUnits;
|
||||
};
|
||||
uiSleep 15;
|
||||
};
|
||||
_unitGroup setSpeedMode "NORMAL";
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Group %1 reinforcement timer complete.",_unitGroup];};
|
||||
} else {
|
||||
_paraDrop = [_unitGroup,_vehicle,objNull] spawn A3XAI_heliParaDrop;
|
||||
waitUntil {uiSleep 0.1; scriptDone _paraDrop};
|
||||
};
|
||||
|
||||
if (((_unitGroup getVariable ["GroupSize",-1]) < 1) or {!((_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce")}) exitWith {
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (type: %2) is no longer reinforcing, reinforce timer exited.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])];};
|
||||
};
|
||||
|
||||
_vehPos = (getPosATL _vehicle);
|
||||
_despawnPos = [_vehPos,AIR_REINFORCE_DESPAWN_DIST,random(360),1] call A3XAI_SHK_pos;
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: %1 Vehicle %2 (pos %3) assigned despawn pos %4.",_unitGroup,(typeOf _vehicle),_vehPos,_despawnPos];};
|
||||
|
||||
_waypoint = _unitGroup addWaypoint [_despawnPos,0];
|
||||
_waypoint setWaypointType "MOVE";
|
||||
_waypoint setWaypointBehaviour "CARELESS";
|
||||
if (_vehicleArmed) then {_waypoint setWaypointCombatMode "BLUE";};
|
||||
if (local _unitGroup) then {
|
||||
_unitGroup setCurrentWaypoint _waypoint;
|
||||
} else {
|
||||
A3XAI_setCurrentWaypoint_PVC = _waypoint;
|
||||
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_setCurrentWaypoint_PVC";
|
||||
};
|
||||
|
||||
waitUntil {uiSleep 15; (((getPosATL _vehicle) distance2D _vehPos) > 1200) or {!(alive _vehicle)}};
|
||||
|
||||
_unitGroup call A3XAI_cleanupReinforcementGroup;
|
||||
A3XAI_reinforcedPositions = A3XAI_reinforcedPositions - _reinforcePos;
|
||||
|
||||
true
|
@ -0,0 +1,47 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_triggerPos", "_targetPlayer", "_nearbyUnits", "_waypoint", "_patrolDist","_targetPos"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_patrolDist = _this select 1;
|
||||
_targetPlayer = _this select 2;
|
||||
_triggerPos = _this select 3;
|
||||
|
||||
_targetPos = getPosATL _targetPlayer;
|
||||
if ((isPlayer _targetPlayer) && {(vehicle _targetPlayer) isKindOf "Land"}) then {
|
||||
if (A3XAI_enableRadioMessages) then {
|
||||
//diag_log "DEBUG: Sending radio static";
|
||||
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
|
||||
_nearbyUnits = _targetPlayer nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTKILLER];
|
||||
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
|
||||
{
|
||||
if (isPlayer _x) then {
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[0,[]]] call A3XAI_radioSend;
|
||||
};
|
||||
}
|
||||
} count _nearbyUnits;
|
||||
};
|
||||
};
|
||||
|
||||
_unitGroup setSpeedMode "FULL";
|
||||
|
||||
_waypoint = [_unitGroup,0]; //Group will move to waypoint index 0 (first waypoint).
|
||||
_waypoint setWaypointType "MOVE";
|
||||
_waypoint setWaypointCompletionRadius 50;
|
||||
_waypoint setWaypointTimeout [3, 3, 3];
|
||||
_waypoint setWPPos _targetPos;
|
||||
_waypoint setWaypointStatements ["true","if !(local this) exitWith {}; (group this) spawn A3XAI_hunterLocate;"];
|
||||
|
||||
_unitGroup setCurrentWaypoint _waypoint;
|
||||
|
||||
_unitGroup setVariable ["targetplayer",_targetPlayer];
|
||||
if (A3XAI_enableHC && {"dynamic" in A3XAI_HCAllowedTypes}) then {
|
||||
_unitGroup setVariable ["HC_Ready",true];
|
||||
_unitGroup setVariable ["MiscData",_targetPlayer];
|
||||
};
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Dynamic group %1 is now hunting player %2.",_unitGroup,_targetPlayer];};
|
||||
} else {
|
||||
0 = [_unitGroup,_triggerPos,_patrolDist] spawn A3XAI_BIN_taskPatrol;
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Dynamic group %1 is patrolling area.",_unitGroup];};
|
||||
};
|
@ -0,0 +1,43 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_vehicle","_loadWP","_loadWPCond","_unit","_regroupPos","_waypointCycle"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
if ((count (waypoints _unitGroup)) > 1) exitWith {
|
||||
if (isNull (driver _vehicle)) then {
|
||||
[_unitGroup,1] setWaypointPosition [(getPosATL _vehicle),0];
|
||||
_unitGroup setCurrentWaypoint [_unitGroup,1];
|
||||
};
|
||||
};
|
||||
|
||||
_unit = objNull;
|
||||
{
|
||||
if (isNull (objectParent _x)) exitWith {_unit = _x};
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
if (isNull _unit) exitWith {_unitGroup call A3XAI_setVehicleRegrouped}; //If no units outside of vehicle, consider crew regrouped and exit script
|
||||
|
||||
_regroupPos = if (isNull (driver _vehicle)) then {
|
||||
(getPosATL _vehicle)
|
||||
} else {
|
||||
([_vehicle,_unit,(_unit distance _vehicle)/2] call A3XAI_getPosBetween)
|
||||
};
|
||||
|
||||
_loadWP = _unitGroup addWaypoint [_regroupPos,0];
|
||||
_loadWP setWaypointType "LOAD";
|
||||
_loadWPCond = "_vehicle = (group this) getVariable ['assignedVehicle',objNull]; ({_x isEqualTo (vehicle _x)} count (assignedCargo _vehicle)) isEqualTo 0";
|
||||
_loadWP setWaypointStatements [_loadWPCond,"if !(local this) exitWith {}; (group this) spawn A3XAI_vehCrewRegroupComplete;"];
|
||||
|
||||
_waypointCycle = _unitGroup addWaypoint [_regroupPos, 0];
|
||||
_waypointCycle setWaypointType "CYCLE";
|
||||
_waypointCycle setWaypointStatements ["true","if !(local this) exitWith {}; _unitGroup = (group this); deleteWaypoint [_unitGroup,2]; deleteWaypoint [_unitGroup,1];"];
|
||||
_waypointCycle setWaypointCompletionRadius 150;
|
||||
|
||||
_loadWP setWaypointCompletionRadius 10;
|
||||
_unitGroup setCurrentWaypoint _loadWP;
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Regroup order issued for AI group %1 to vehicle %2. Check WP count: %3.",_unitGroup,typeOf _vehicle,(count (waypoints _unitGroup))];};
|
||||
|
||||
true
|
@ -0,0 +1,16 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_vehicle","_vehiclePos"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||
if (isNull _vehicle) exitWith {diag_log format ["A3XAI Error: Group %1 has null vehicle.",_unitGroup];};
|
||||
_vehiclePos = getPosATL _vehicle;
|
||||
[_unitGroup,0] setWaypointPosition [_vehiclePos,0];
|
||||
[_unitGroup,2] setWaypointPosition [_vehiclePos,0];
|
||||
_unitGroup call A3XAI_setVehicleRegrouped;
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Regroup completed for vehicle group %1.",_unitGroup];};
|
||||
|
||||
true
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
_locationSelected = [_locationSelected,random(300),random(360),0,[1,300]] call A3XAI_SHK_pos;
|
||||
[_unitGroup,0] setWPPos _locationSelected;
|
||||
[_unitGroup,0] setWaypointCompletionRadius 150;
|
||||
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
|
||||
_unitGroup setCurrentWaypoint [_unitGroup,0];
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};
|
@ -0,0 +1,243 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_unitType", "_unitTypeRef", "_vehicle", "_stuckCheckTime", "_groupLeadMarker", "_groupWPMarker", "_fncArray", "_fnc_execEveryLoop", "_fnc_checkUnits",
|
||||
"_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck", "_currentTime", "_managerStartTime", "_updateServerLoot", "_pullRate", "_markname", "_mark", "_markername", "_unitPos",
|
||||
"_unitMarker", "_lootPool", "_result", "_debugStartTime"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_unitLevel = _this select 1;
|
||||
|
||||
if (_unitGroup getVariable ["isManaged",false]) exitWith {};
|
||||
_unitGroup setVariable ["isManaged",true];
|
||||
|
||||
_unitType = (_unitGroup getVariable ["unitType",""]);
|
||||
_unitTypeRef = _unitType;
|
||||
_vehicle = if (_unitType in ["air","land","aircustom","landcustom","air_reinforce","uav","ugv"]) then {_unitGroup getVariable ["assignedVehicle",(assignedVehicle (leader _unitGroup))]} else {objNull};
|
||||
|
||||
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||
if (isNil {_unitGroup getVariable "GroupSize"}) then {_unitGroup setVariable ["GroupSize",(count (units _unitGroup))]};
|
||||
_stuckCheckTime = _unitType call A3XAI_getAntistuckTime;
|
||||
|
||||
//set up debug variables
|
||||
_groupLeadMarker = "";
|
||||
_groupWPMarker = "";
|
||||
|
||||
//Set up local functions
|
||||
_fncArray = [_unitGroup,_unitType] call A3XAI_getLocalFunctions;
|
||||
_fnc_execEveryLoop = _fncArray select 0;
|
||||
_fnc_checkUnits = _fncArray select 1;
|
||||
_fnc_generateLoot = _fncArray select 2;
|
||||
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
|
||||
_fnc_antistuck = _fncArray select 4;
|
||||
|
||||
//Set up timer variables
|
||||
_currentTime = diag_tickTime;
|
||||
_managerStartTime = _currentTime;
|
||||
_unitGroup setVariable ["lastRearmTime",_currentTime];
|
||||
_unitGroup setVariable ["antistuckTime",_currentTime];
|
||||
_unitGroup setVariable ["lootGenTime",_currentTime];
|
||||
|
||||
//Setup loot variables
|
||||
_updateServerLoot = (A3XAI_enableHC && {!isDedicated});
|
||||
_pullRate = 30;
|
||||
|
||||
if (isDedicated) then {
|
||||
[_unitGroup,_unitType,_unitLevel] call A3XAI_setLoadoutVariables;
|
||||
|
||||
if (A3XAI_enableDebugMarkers) then {
|
||||
_groupLeadMarker = format ["%1_Lead",_unitGroup];
|
||||
if (_groupLeadMarker in allMapMarkers) then {deleteMarker _groupLeadMarker; uiSleep 0.5}; //Delete the previous marker if it wasn't deleted for some reason.
|
||||
_groupLeadMarker = createMarker [_groupLeadMarker,getPosATL (leader _unitGroup)];
|
||||
_groupLeadMarker setMarkerType "mil_warning";
|
||||
_groupLeadMarker setMarkerBrush "Solid";
|
||||
|
||||
if (isNull _vehicle) then {
|
||||
_groupLeadMarker setMarkerText format ["%1 (AI L%2)",_unitGroup,_unitLevel];
|
||||
} else {
|
||||
_groupLeadMarker setMarkerText format ["%1 (AI L%2 %3)",_unitGroup,_unitLevel,(typeOf (vehicle (leader _unitGroup)))];
|
||||
};
|
||||
|
||||
_groupWPMarker = (format ["%1_WP",_unitGroup]);
|
||||
if (_groupWPMarker in allMapMarkers) then {deleteMarker _groupWPMarker; uiSleep 0.5;}; //Delete the previous marker if it wasn't deleted for some reason.
|
||||
_groupWPMarker = createMarker [_groupWPMarker,(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||
_groupWPMarker setMarkerText format ["%1 Waypoint",_unitGroup];
|
||||
_groupWPMarker setMarkerType "Waypoint";
|
||||
_groupWPMarker setMarkerColor "ColorBlue";
|
||||
_groupWPMarker setMarkerBrush "Solid";
|
||||
|
||||
[_unitGroup] spawn {
|
||||
_unitGroup = _this select 0;
|
||||
{
|
||||
_markname = str(_x);
|
||||
if (_markname in allMapMarkers) then {deleteMarker _markname; uiSleep 0.5};
|
||||
_mark = createMarker [_markname,getPosATL _x];
|
||||
_mark setMarkerShape "ELLIPSE";
|
||||
_mark setMarkerType "Dot";
|
||||
_mark setMarkerColor "ColorRed";
|
||||
_mark setMarkerBrush "SolidBorder";
|
||||
_nul = _x spawn {
|
||||
_markername = str (_this);
|
||||
_unitGroup = group _this;
|
||||
while {alive _this} do {
|
||||
if (local _this) then {
|
||||
_unitPos = getPosATL _this;
|
||||
if ((leader _unitGroup) isEqualTo _this) then {
|
||||
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
|
||||
_color = call {
|
||||
_combatMode = (combatMode _unitGroup);
|
||||
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
|
||||
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
|
||||
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
|
||||
"ColorBlack"
|
||||
};
|
||||
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
|
||||
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
|
||||
};
|
||||
_markername setMarkerPos _unitPos;
|
||||
};
|
||||
uiSleep 10;
|
||||
};
|
||||
deleteMarker _markername;
|
||||
};
|
||||
} forEach (units _unitGroup);
|
||||
};
|
||||
};
|
||||
|
||||
} else {
|
||||
waitUntil {uiSleep 0.25; (local _unitGroup)};
|
||||
[_unitGroup,_unitType,_unitLevel] call A3XAI_setLoadoutVariables_HC;
|
||||
|
||||
if (A3XAI_enableDebugMarkers) then {
|
||||
{
|
||||
_nul = _x spawn {
|
||||
waitUntil {sleep 5; ((local _this) or {!(alive _this)})};
|
||||
_unitMarker = str (_this);
|
||||
_unitGroup = group _this;
|
||||
while {alive _this} do {
|
||||
if (local _this) then {
|
||||
_unitPos = getPosATL _this;
|
||||
if ((leader _unitGroup) isEqualTo _this) then {
|
||||
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
|
||||
_color = call {
|
||||
_combatMode = (combatMode _unitGroup);
|
||||
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
|
||||
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
|
||||
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
|
||||
"ColorBlack"
|
||||
};
|
||||
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
|
||||
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
|
||||
};
|
||||
_unitMarker setMarkerPos _unitPos;
|
||||
};
|
||||
uiSleep 10;
|
||||
};
|
||||
};
|
||||
} forEach (units _unitGroup);
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {
|
||||
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||
//diag_log format ["Debug: Found loot pool for group %1 from server: %2",_unitGroup,_lootPool];
|
||||
};
|
||||
};
|
||||
|
||||
//Main loop
|
||||
while {(!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
|
||||
_unitType = (_unitGroup getVariable ["unitType",""]);
|
||||
if !(_unitType isEqualTo _unitTypeRef) then {
|
||||
_fncArray = [_unitGroup,_unitType] call A3XAI_getLocalFunctions;
|
||||
_fnc_execEveryLoop = _fncArray select 0;
|
||||
_fnc_checkUnits = _fncArray select 1;
|
||||
_fnc_generateLoot = _fncArray select 2;
|
||||
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
|
||||
_fnc_antistuck = _fncArray select 4;
|
||||
_stuckCheckTime = _unitType call A3XAI_getAntistuckTime;
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Reassigned group %1 type from %2 to %3.",_unitGroup,_unitTypeRef,_unitType];};
|
||||
|
||||
_unitTypeRef = _unitType;
|
||||
};
|
||||
|
||||
[_unitGroup,_vehicle] call _fnc_execEveryLoop;
|
||||
|
||||
[_unitGroup] call _fnc_checkUnits;
|
||||
|
||||
//Generate loot
|
||||
if ((diag_tickTime - (_unitGroup getVariable ["lootGenTime",diag_tickTime])) > _pullRate) then {
|
||||
[_unitGroup,_unitLevel] call _fnc_generateLoot;
|
||||
};
|
||||
|
||||
//Vehicle ammo/fuel check
|
||||
if ((alive _vehicle) && {(diag_tickTime - (_unitGroup getVariable ["lastRearmTime",0])) > 180}) then { //If _vehicle is objNull (if no vehicle was assigned to the group) then nothing in this bracket should be executed
|
||||
[_unitGroup,_vehicle] call _fnc_vehicleAmmoFuelCheck;
|
||||
};
|
||||
|
||||
//Antistuck
|
||||
if ((diag_tickTime - (_unitGroup getVariable ["antistuckTime",diag_tickTime])) > _stuckCheckTime) then {
|
||||
[_unitGroup,_vehicle,_stuckCheckTime] call _fnc_antistuck;
|
||||
};
|
||||
|
||||
if (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.",_unitType,_unitGroup,A3XAI_HCObjectOwnerID];};
|
||||
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).",_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];
|
||||
};
|
||||
};
|
||||
|
||||
//diag_log format ["DEBUG: Group Manager cycle time for group %1: %2 seconds.",_unitGroup,(diag_tickTime - _debugStartTime)];
|
||||
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {uiSleep 15};
|
||||
};
|
||||
|
||||
if (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]) isEqualTo -1) 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"])]};
|
||||
_unitGroup call A3XAI_deleteGroup;
|
||||
};
|
||||
};
|
||||
} else {
|
||||
diag_log "A3XAI Error: An A3XAI-managed group was deleted unexpectedly!";
|
||||
};
|
||||
|
||||
if ((local _vehicle) && {isEngineOn _vehicle}) then {
|
||||
_vehicle engineOn false;
|
||||
};
|
@ -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_checkInNoAggroArea}) && {_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,"IgnoreEnemies"] 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
|
@ -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_checkInNoAggroArea}) && {_checkPos isEqualTo (_unitGroup getVariable ["antistuckPos",[0,0,0]])} && {canMove _vehicle}) then {
|
||||
_currentWP = (currentWaypoint _unitGroup);
|
||||
_allWP = (waypoints _unitGroup);
|
||||
_nextWP = _currentWP + 1;
|
||||
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 1}; //Cycle back to first added waypoint if group is currently on last waypoint.
|
||||
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
|
||||
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||
if (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
|
@ -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_checkInNoAggroArea}) && ((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_INFANTRY) then {
|
||||
_currentWP = (currentWaypoint _unitGroup);
|
||||
_nextWP = _currentWP + 1;
|
||||
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 0}; //Cycle back to first waypoint if group is currently on last waypoint.
|
||||
[_unitGroup] call 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
|
@ -0,0 +1,35 @@
|
||||
#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_checkInNoAggroArea}) && {((_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 {
|
||||
[_unitGroup,0] setWaypointPosition [_checkPos,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 ["vehicle_disabled",false])) then {
|
||||
[_vehicle] 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
|
@ -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_UAV] call A3XAI_checkInNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < 750} && {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,"IgnoreEnemies"] call A3XAI_forceBehavior;
|
||||
_unitGroup setVariable ["antistuckPos",_wpSelect];
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Antistuck triggered for UAV %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
|
||||
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||
} else {
|
||||
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,34 @@
|
||||
#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_checkInNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < 100}) then {
|
||||
if (canMove _vehicle) then {
|
||||
[_unitGroup] call A3XAI_fixStuckGroup;
|
||||
[_unitGroup,0] setWaypointPosition [_checkPos,0];
|
||||
[_unitGroup,1] setWaypointPosition [_checkPos,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 ["vehicle_disabled",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
|
@ -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
|
@ -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
|
@ -0,0 +1,20 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_vehicle","_inNoAggroArea","_inArea","_result","_leader"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
_leader = (leader _unitGroup);
|
||||
_inArea = [_vehicle,NO_AGGRO_RANGE_AIR] call A3XAI_checkInNoAggroArea;
|
||||
|
||||
if !(_inArea) then {
|
||||
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_AIR) then { //900: replace with engagement range
|
||||
_inArea = [_assignedTarget,300] call A3XAI_checkInNoAggroArea;
|
||||
};
|
||||
}; //To test!
|
||||
|
||||
_result = [_unitGroup,_inArea] call A3XAI_noAggroAreaToggle;
|
||||
|
||||
true
|
@ -0,0 +1,34 @@
|
||||
#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_checkInNoAggroArea;
|
||||
|
||||
if !(_inArea) then {
|
||||
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_MAN) then { //900: replace with engagement range
|
||||
_inArea = [_assignedTarget,300] call A3XAI_checkInNoAggroArea;
|
||||
};
|
||||
};
|
||||
|
||||
_result = [_unitGroup,_inArea] call A3XAI_noAggroAreaToggle;
|
||||
|
||||
/*
|
||||
if !(_inArea) then {
|
||||
_trigger = _unitGroup getVariable "trigger";
|
||||
if !(isNil "_trigger") then {
|
||||
_maxDistance = _unitGroup getVariable ["patrolDist",250];
|
||||
if ((_leader distance2D _trigger) > (_maxDistance + PATROL_DISTANCE_BUFFER)) then {
|
||||
_randomWaypoint = _unitGroup call A3XAI_setRandomWaypoint;
|
||||
(units _unitGroup) doMove (waypointPosition _randomWaypoint);
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Group %1 moved beyond allowed patrol radius, ordering group towards spawn center.",_unitGroup];};
|
||||
};
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
true
|
@ -0,0 +1,36 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_vehicle", "_lastAggro","_inNoAggroArea","_inArea","_result","_leader"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
if (A3XAI_detectOnlyUAVs) then {
|
||||
_lastAggro = _vehicle getVariable "AggroTime";
|
||||
if (isNil "AggroTime") then {
|
||||
_lastAggro = 0;
|
||||
_vehicle setVariable ["AggroTime",0];
|
||||
[_unitGroup,"IgnoreEnemies"] call A3XAI_forceBehavior;
|
||||
};
|
||||
|
||||
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
|
||||
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UAV] call A3XAI_checkInNoAggroArea}) then {
|
||||
[_unitGroup,"IgnoreEnemies"] 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)]};
|
||||
};
|
||||
};
|
||||
} else {
|
||||
_leader = (leader _unitGroup);
|
||||
_inArea = [_vehicle,NO_AGGRO_RANGE_UAV] call A3XAI_checkInNoAggroArea;
|
||||
|
||||
if !(_inArea) then {
|
||||
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UAV) then { //900: replace with engagement range
|
||||
_inArea = [_assignedTarget,300] call A3XAI_checkInNoAggroArea;
|
||||
};
|
||||
};
|
||||
|
||||
_result = [_unitGroup,_inArea] call A3XAI_noAggroAreaToggle;
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,36 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_vehicle", "_lastAggro", "_lastRepaired", "_vehicleType", "_hitArray", "_hitName", "_hitPoint","_inNoAggroArea","_inArea","_result","_leader"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
if (A3XAI_detectOnlyUGVs) then {
|
||||
_lastAggro = _vehicle getVariable "AggroTime";
|
||||
if (isNil "AggroTime") then {
|
||||
_lastAggro = 0;
|
||||
_vehicle setVariable ["AggroTime",0];
|
||||
[_unitGroup,"IgnoreEnemies"] call A3XAI_forceBehavior;
|
||||
};
|
||||
|
||||
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
|
||||
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UGV] call A3XAI_checkInNoAggroArea}) then {
|
||||
[_unitGroup,"IgnoreEnemies"] 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)]};
|
||||
};
|
||||
};
|
||||
} else {
|
||||
_leader = (leader _unitGroup);
|
||||
_inArea = [_vehicle,NO_AGGRO_RANGE_UGV] call A3XAI_checkInNoAggroArea;
|
||||
|
||||
if !(_inArea) then {
|
||||
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UGV) then { //900: replace with engagement range
|
||||
_inArea = [_assignedTarget,300] call A3XAI_checkInNoAggroArea;
|
||||
};
|
||||
};
|
||||
|
||||
_result = [_unitGroup,_inArea] call A3XAI_noAggroAreaToggle;
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,35 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_vehicle", "_lastRegroupCheck","_inNoAggroArea","_inArea","_result","_leader"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
_leader = (leader _unitGroup);
|
||||
_inArea = [_leader,NO_AGGRO_RANGE_LAND] call A3XAI_checkInNoAggroArea;
|
||||
|
||||
if !(_inArea) then {
|
||||
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_LAND) then { //900: replace with engagement range
|
||||
_inArea = [_assignedTarget,300] call A3XAI_checkInNoAggroArea;
|
||||
};
|
||||
}; //To test!
|
||||
|
||||
_result = [_unitGroup,_inArea] call A3XAI_noAggroAreaToggle;
|
||||
|
||||
_lastRegroupCheck = _vehicle getVariable "LastRegroupCheck";
|
||||
if (isNil "_lastRegroupCheck") then {
|
||||
_lastRegroupCheck = diag_tickTime;
|
||||
_vehicle setVariable ["LastRegroupCheck",0];
|
||||
};
|
||||
|
||||
if ((diag_tickTime - _lastRegroupCheck) > 30) then {
|
||||
if ((alive _vehicle) && {_unitGroup getVariable ["regrouped",true]} && {({if ((_x distance2D _vehicle) > REGROUP_VEHICLEGROUP_DIST) exitWith {1}} count (assignedCargo _vehicle)) > 0}) then {
|
||||
_unitGroup setVariable ["regrouped",false];
|
||||
[_unitGroup,_vehicle] call A3XAI_vehCrewRegroup;
|
||||
};
|
||||
|
||||
_vehicle setVariable ["LastRegroupCheck",diag_tickTime];
|
||||
};
|
||||
|
||||
true
|
@ -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
|
@ -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
|
@ -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];};
|
@ -0,0 +1,57 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_lootPool","_groupSize"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||
_groupSize = _unitGroup getVariable ["GroupSize",0];
|
||||
_unitType = _unitGroup getVariable ["unitType",""];
|
||||
|
||||
if (_unitType != "dynamic") then {
|
||||
for "_j" from 1 to _groupSize do {
|
||||
if (A3XAI_firstAidKitChance call A3XAI_chance) then {
|
||||
_lootPool pushBack FIRST_AID_ITEM_PLAYER;
|
||||
};
|
||||
|
||||
//Add food to loot list
|
||||
for "_i" from 1 to A3XAI_foodLootCount do {
|
||||
_lootPool pushBack (A3XAI_foodLoot call A3XAI_selectRandom);
|
||||
};
|
||||
|
||||
//Add items to loot list
|
||||
for "_i" from 1 to A3XAI_miscLootCount do {
|
||||
_lootPool pushBack (A3XAI_MiscLoot call A3XAI_selectRandom);
|
||||
};
|
||||
|
||||
sleep 0.25;
|
||||
};
|
||||
} else {
|
||||
for "_j" from 1 to _groupSize do {
|
||||
if (A3XAI_firstAidKitChance call A3XAI_chance) then {
|
||||
_lootUnit = (units _unitGroup) call A3XAI_selectRandom;
|
||||
[_lootUnit,FIRST_AID_ITEM_PLAYER] call A3XAI_addItem;
|
||||
};
|
||||
|
||||
//Add food to randomly chosen unit
|
||||
for "_i" from 1 to A3XAI_foodLootCount do {
|
||||
_lootUnit = (units _unitGroup) call A3XAI_selectRandom;
|
||||
_lootItem = (A3XAI_foodLoot call A3XAI_selectRandom);
|
||||
[_lootUnit,_lootItem] call A3XAI_addItem;
|
||||
};
|
||||
|
||||
//Add items to randomly chosen unit
|
||||
for "_i" from 1 to A3XAI_miscLootCount do {
|
||||
_lootUnit = (units _unitGroup) call A3XAI_selectRandom;
|
||||
_lootItem = (A3XAI_MiscLoot call A3XAI_selectRandom);
|
||||
[_lootUnit,_lootItem] call A3XAI_addItem;
|
||||
};
|
||||
|
||||
sleep 0.25;
|
||||
};
|
||||
};
|
||||
|
||||
//Update local group loot pool
|
||||
_unitGroup setVariable ["LootPool",_lootPool];
|
||||
|
||||
true
|
@ -0,0 +1,12 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitType"];
|
||||
|
||||
_unitType = _this;
|
||||
|
||||
call {
|
||||
if (_unitType in ["static","staticcustom","vehiclecrew","aircustom","landcustom"]) exitWith {ANTISTUCK_CHECK_TIME_INFANTRY};
|
||||
if (_unitType in ["air","uav"]) exitWith {ANTISTUCK_CHECK_TIME_AIR};
|
||||
if (_unitType in ["land","ugv"]) exitWith {ANTISTUCK_CHECK_TIME_LAND};
|
||||
300
|
||||
};
|
@ -0,0 +1,101 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitType", "_fnc_execEveryLoop", "_fnc_checkUnits", "_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_unitType = _this select 1;
|
||||
|
||||
call {
|
||||
if (_unitType isEqualTo "static") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_infantry;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
if (_unitType isEqualTo "random") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_infantry;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
if (_unitType isEqualTo "dynamic") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_infantry;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
if (_unitType isEqualTo "air") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_air;
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_air;
|
||||
};
|
||||
if (_unitType isEqualTo "land") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_vehicle;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_land;
|
||||
};
|
||||
if (_unitType isEqualTo "uav") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_uav;
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = {};
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_uav;
|
||||
};
|
||||
if (_unitType isEqualTo "ugv") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_ugv;
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = {};
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_ugv;
|
||||
};
|
||||
if (_unitType isEqualTo "air_reinforce") exitWith {
|
||||
_fnc_execEveryLoop = {};
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = {};
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = {};
|
||||
};
|
||||
if (_unitType isEqualTo "vehiclecrew") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_infantry;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
if (_unitType isEqualTo "staticcustom") exitWith {
|
||||
_fnc_execEveryLoop = {};
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
if (_unitType isEqualTo "aircustom") exitWith {
|
||||
_fnc_execEveryLoop = {};
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_aircustom;
|
||||
};
|
||||
if (_unitType isEqualTo "landcustom") exitWith {
|
||||
_fnc_execEveryLoop = A3XAI_execEveryLoop_vehicle;
|
||||
_fnc_checkUnits = A3XAI_checkGroupUnits;
|
||||
_fnc_generateLoot = A3XAI_generateGroupLoot;
|
||||
_fnc_vehicleAmmoFuelCheck = A3XAI_checkAmmoFuel;
|
||||
_fnc_antistuck = A3XAI_antistuck_generic;
|
||||
};
|
||||
_fnc_execEveryLoop = {};
|
||||
_fnc_checkUnits = {};
|
||||
_fnc_generateLoot = {};
|
||||
_fnc_vehicleAmmoFuelCheck = {};
|
||||
_fnc_antistuck = {};
|
||||
diag_log format ["A3XAI Warning: Group functions for unit type %1 not found.",_unitType];
|
||||
};
|
||||
|
||||
[_fnc_execEveryLoop,_fnc_checkUnits,_fnc_generateLoot,_fnc_vehicleAmmoFuelCheck,_fnc_antistuck]
|
@ -0,0 +1,47 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo","_launchersAdded"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_unitType = _this select 1;
|
||||
_unitLevel = _this select 2;
|
||||
|
||||
if !(_unitType in ["uav","ugv"]) then {
|
||||
_useLaunchers = if !(A3XAI_levelRequiredLauncher isEqualTo -1) then {((count A3XAI_launcherTypes) > 0) && {(_unitLevel >= A3XAI_levelRequiredLauncher)}} else {false};
|
||||
_maxLaunchers = if (_useLaunchers) then {A3XAI_launchersPerGroup min _unitLevel} else {0};
|
||||
_launchersAdded = 0;
|
||||
|
||||
_unitGroup setVariable ["LootPool",[]];
|
||||
_unitGroup spawn A3XAI_generateLootPool;
|
||||
|
||||
//Set up individual group units
|
||||
{
|
||||
_loadout = _x getVariable "loadout";
|
||||
if (isNil "_loadout") then {
|
||||
_weapon = primaryWeapon _x;
|
||||
_magazine = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines") select 0;
|
||||
_loadout = [[_weapon],[_magazine]];
|
||||
_x setVariable ["loadout",_loadout];
|
||||
};
|
||||
|
||||
|
||||
if (_launchersAdded < _maxLaunchers) then {
|
||||
_launchWeapon = A3XAI_launcherTypes call A3XAI_selectRandom;
|
||||
_launchAmmo = getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
|
||||
if (_x canAdd _launchAmmo) then {
|
||||
_x addMagazine _launchAmmo;
|
||||
_x addWeapon _launchWeapon;
|
||||
(_loadout select 1) pushBack _launchAmmo;
|
||||
(_loadout select 0) pushBack _launchWeapon;
|
||||
_launchersAdded = _launchersAdded + 1;
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Successfully added weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
|
||||
} else {
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Unable to add weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
|
||||
};
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
|
||||
} forEach (units _unitGroup);
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,27 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_currentTime", "_monitorReport", "_getUptime", "_currentSec", "_outHour", "_outMin", "_outSec", "_uptime"];
|
||||
|
||||
_currentTime = diag_tickTime;
|
||||
_monitorReport = _currentTime;
|
||||
|
||||
_getUptime = {
|
||||
private ["_currentSec","_outSec","_outMin","_outHour"];
|
||||
_currentSec = diag_tickTime;
|
||||
_outHour = floor (_currentSec/3600);
|
||||
_outMin = floor ((_currentSec - (_outHour*3600))/60);
|
||||
_outSec = floor (_currentSec - (_outHour*3600) - (_outMin*60));
|
||||
|
||||
[_outHour,_outMin,_outSec]
|
||||
};
|
||||
|
||||
while {true} do {
|
||||
_currentTime = diag_tickTime;
|
||||
|
||||
if ((A3XAI_monitorReportRate > 0) && {((_currentTime - _monitorReport) > A3XAI_monitorReportRate)}) then {
|
||||
_uptime = [] call _getUptime;
|
||||
diag_log format ["A3XAI Monitor: Uptime: %1:%2:%3. FPS: %4. HC Groups: %5.",_uptime select 0, _uptime select 1, _uptime select 2,round(diag_fps),A3XAI_HCGroupsCount];
|
||||
_monitorReport = _currentTime;
|
||||
};
|
||||
uiSleep 30;
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_targetPlayer"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_targetPlayer = _this select 1;
|
||||
|
||||
_unitGroup setVariable ["targetPlayer",_targetPlayer];
|
||||
|
||||
true
|
@ -0,0 +1,65 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_anchor", "_unitType", "_groupSize", "_functionCall", "_check", "_lootPool","_miscData1","_miscData2","_anchorType"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_unitLevel = _this select 1;
|
||||
_anchor = _this select 2;
|
||||
_unitType = _this select 3;
|
||||
_groupSize = _this select 4;
|
||||
_lootPool = _this select 5;
|
||||
_miscData1 = if ((count _this) > 6) then {_this select 6};
|
||||
_miscData2 = if ((count _this) > 7) then {_this select 7};
|
||||
|
||||
call {
|
||||
_anchorType = (typeName _anchor);
|
||||
if (_anchorType isEqualTo "ARRAY") exitWith {
|
||||
_anchor = createTrigger [TRIGGER_OBJECT,_anchor,false];
|
||||
_unitGroup setVariable ["trigger",_anchor];
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Created group trigger for %1 group %2.",_unitType,_unitGroup];};
|
||||
};
|
||||
if (_anchorType isEqualTo "OBJECT") exitWith {
|
||||
_unitGroup setVariable ["assignedVehicle",_anchor];
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: %1 group %2 has assigned vehicle %3 (%4).",_unitType,_unitGroup,_anchor,(typeOf _anchor)];};
|
||||
};
|
||||
_anchor = objNull;
|
||||
};
|
||||
|
||||
_unitGroup setVariable ["unitLevel",_unitLevel];
|
||||
_unitGroup setVariable ["unitType",_unitType];
|
||||
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||
|
||||
_unitGroup call A3XAI_initNoAggroStatus;
|
||||
|
||||
if !(_lootPool isEqualTo []) then {_unitGroup setVariable ["LootPool",_lootPool];};
|
||||
|
||||
if !(isNil "_miscData1") then {
|
||||
call {
|
||||
if (_unitType isEqualTo "dynamic") exitWith {
|
||||
_unitGroup setVariable ["targetplayer",_miscData1];
|
||||
_anchor setVariable ["targetplayer",_miscData1];
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: %1 group %2 has target player %3.",_unitType,_unitGroup,_miscData1];};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (!isNil "_miscData2") then {
|
||||
|
||||
};
|
||||
|
||||
_functionCall = missionNamespace getVariable ["A3XAI_handle"+_unitType,{false}];
|
||||
_check = _unitGroup call _functionCall;
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {
|
||||
if (_check) then {
|
||||
diag_log format ["A3XAI Debug: HC received new group from server: %1. Processing new group with function %2.",_unitGroup,("A3XAI_handle"+_unitType)];
|
||||
} else {
|
||||
diag_log format ["A3XAI Debug: Function %1 not found.","A3XAI_handle"+_unitType]
|
||||
};
|
||||
};
|
||||
|
||||
0 = [_unitGroup,_unitLevel] spawn A3XAI_addGroupManager;
|
||||
|
||||
A3XAI_HCGroupsCount = A3XAI_HCGroupsCount + 1;
|
||||
|
||||
true
|
@ -0,0 +1,28 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_unitType", "_groupSize", "_vehicle"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Waiting for reinforcement group %1 ready state.",_unitGroup];};
|
||||
waitUntil {uiSleep 10; diag_log format ["Debug: Group %1 behavior is %2, combat mode %3.",_unitGroup,(behaviour (leader _unitGroup)),(combatMode _unitGroup)]; !((behaviour (leader _unitGroup)) isEqualTo "CARELESS")};
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 has now entered ready state.",_unitGroup];};
|
||||
|
||||
while {((behaviour (leader _unitGroup)) in ["AWARE","COMBAT"]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
|
||||
if (local _unitGroup) then {
|
||||
_vehiclePos = getPosATL _vehicle;
|
||||
_vehiclePos set [2,0];
|
||||
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],250];
|
||||
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
|
||||
{
|
||||
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3}) then {
|
||||
_unitGroup reveal [_x,3];
|
||||
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3XAI_radioSend;
|
||||
};
|
||||
};
|
||||
} forEach _nearUnits;
|
||||
};
|
||||
uiSleep 15;
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_vehicle"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_vehicle = _this select 1;
|
||||
|
||||
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed","Hit"];
|
||||
_unitGroup setVariable ["GroupSize",-1];
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Releasing ownership of reinforcement group %1 to server.",_unitGroup];};
|
||||
|
||||
true
|
@ -0,0 +1,12 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_trigger","_triggerPos"];
|
||||
_unitGroup = _this select 0;
|
||||
_triggerPos = _this select 1;
|
||||
|
||||
_trigger = createTrigger [TRIGGER_OBJECT,_triggerPos,false];
|
||||
_unitGroup setVariable ["trigger",_trigger];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Created group trigger object for %1 at %2.",_unitGroup,_triggerPos];};
|
||||
|
||||
_trigger
|
@ -0,0 +1,24 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addVehAirEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,26 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addVehAirEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
[_unitGroup,_vehicle] spawn A3XAI_airReinforcementDetection;
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,24 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addVehAirEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,20 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_unitGroup call A3XAI_requestGroupVars;
|
||||
|
||||
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||
|
||||
true
|
@ -0,0 +1,25 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = assignedVehicle (leader _unitGroup);
|
||||
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addLandVehEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,25 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = assignedVehicle (leader _unitGroup);
|
||||
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addLandVehEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,20 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_unitGroup call A3XAI_requestGroupVars;
|
||||
|
||||
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||
|
||||
true
|
@ -0,0 +1,20 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_unitGroup call A3XAI_requestGroupVars;
|
||||
|
||||
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||
|
||||
true
|
@ -0,0 +1 @@
|
||||
#include "A3XAI_handlestatic.sqf"
|
@ -0,0 +1,24 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUVUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addUAVEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1,25 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||
|
||||
_unitGroup = _this;
|
||||
|
||||
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||
|
||||
{
|
||||
_x call A3XAI_addUVUnitEH;
|
||||
} forEach (units _unitGroup);
|
||||
|
||||
_vehicle = assignedVehicle (leader _unitGroup);
|
||||
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||
_vehicle call A3XAI_addUGVEH;
|
||||
_vehicle call A3XAI_secureVehicle;
|
||||
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||
|
||||
//if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||
|
||||
true
|
@ -0,0 +1 @@
|
||||
#include "A3XAI_handlestatic.sqf"
|
@ -0,0 +1,3 @@
|
||||
A3XAI_getGroupTriggerVars_PVS = _this;
|
||||
publicVariableServer "A3XAI_getGroupTriggerVars_PVS";
|
||||
true
|
@ -0,0 +1,18 @@
|
||||
private ["_unitGroup","_mode"];
|
||||
_unitGroup = _this select 0;
|
||||
_mode = _this select 1;
|
||||
|
||||
call {
|
||||
if (_mode isEqualTo 0) exitWith {
|
||||
_unitGroup setBehaviour "CARELESS";
|
||||
{_x doWatch objNull} forEach (units _unitGroup);
|
||||
_unitGroup setVariable ["EnemiesIgnored",true];
|
||||
true
|
||||
};
|
||||
if (_mode isEqualTo 1) exitWith {
|
||||
_unitGroup setBehaviour "AWARE";
|
||||
_unitGroup setVariable ["EnemiesIgnored",false];
|
||||
true
|
||||
};
|
||||
false
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
private ["_unitGroup","_waypointIndex"];
|
||||
_unitGroup = _this select 0;
|
||||
_waypointIndex = _this select 1;
|
||||
_unitGroup setCurrentWaypoint [_unitGroup,_waypointIndex];
|
||||
true
|
@ -0,0 +1,35 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_arrayData", "_unitGroup", "_trigger"];
|
||||
_arrayData = _this;
|
||||
_unitGroup = _arrayData select 0;
|
||||
|
||||
/*
|
||||
if !(local _unitGroup) then {
|
||||
diag_log format ["Debug: Server sent group trigger variables for remote group %1.",_unitGroup];
|
||||
};
|
||||
*/
|
||||
|
||||
_trigger = _unitGroup getVariable "trigger";
|
||||
|
||||
if (isNil "_trigger") exitWith {diag_log format ["A3XAI Error: Group %1 has undefined trigger.",_unitGroup];};
|
||||
|
||||
//Remove array headers (Group reference)
|
||||
_arrayData deleteAt 0;
|
||||
|
||||
{
|
||||
_trigger setVariable [_x,_arrayData select _forEachIndex];
|
||||
//diag_log format ["Debug: Group %1 variable %2 has value %3.",_unitGroup,_x,_arrayData select _forEachIndex];
|
||||
} forEach [
|
||||
"GroupArray",
|
||||
"patrolDist",
|
||||
"unitLevel",
|
||||
"unitLevelEffective",
|
||||
"maxUnits",
|
||||
"spawnChance",
|
||||
"spawnType",
|
||||
"respawn",
|
||||
"permadelete"
|
||||
];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Set group trigger variables for group %1. Success check: %2.",_unitGroup,_trigger isKindOf TRIGGER_OBJECT];};
|
@ -0,0 +1,61 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo", "_useGL"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_unitType = _this select 1;
|
||||
_unitLevel = _this select 2;
|
||||
|
||||
if !(_unitType in ["uav","ugv"]) then {
|
||||
_useGL = if !(A3XAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3XAI_levelRequiredGL} else {false};
|
||||
{
|
||||
_x setVariable ["loadout",[[],[]]];
|
||||
_loadout = _x getVariable "loadout";
|
||||
_primaryWeapon = primaryWeapon _x;
|
||||
_secondaryWeapon = secondaryWeapon _x;
|
||||
_handgunWeapon = handgunWeapon _x;
|
||||
|
||||
if !(_primaryWeapon isEqualTo "") then {
|
||||
(_loadout select 0) pushBack _primaryWeapon;
|
||||
_primaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "magazines") select 0;
|
||||
(_loadout select 1) pushBack _primaryWeaponMagazine;
|
||||
} else {
|
||||
if !(_handgunWeapon isEqualTo "") then {
|
||||
(_loadout select 0) pushBack _handgunWeapon;
|
||||
_handgunWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _handgunWeapon >> "magazines") select 0;
|
||||
(_loadout select 1) pushBack _handgunWeaponMagazine;
|
||||
};
|
||||
};
|
||||
|
||||
if !(_secondaryWeapon isEqualTo "") then {
|
||||
(_loadout select 0) pushBack _secondaryWeapon;
|
||||
_secondaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _secondaryWeapon >> "magazines") select 0;
|
||||
(_loadout select 1) pushBack _secondaryWeaponMagazine;
|
||||
};
|
||||
|
||||
if ((getNumber (configFile >> "CfgMagazines" >> ((_loadout select 1) select 0) >> "count")) < 6) then {_x setVariable ["extraMag",true]};
|
||||
|
||||
if (_useGL) then {
|
||||
_weaponMuzzles = getArray(configFile >> "cfgWeapons" >> ((_loadout select 0) select 0) >> "muzzles");
|
||||
if ((count _weaponMuzzles) > 1) then {
|
||||
_GLWeapon = _weaponMuzzles select 1;
|
||||
_GLMagazines = (getArray (configFile >> "CfgWeapons" >> ((_loadout select 0) select 0) >> _GLWeapon >> "magazines"));
|
||||
if (GRENADE_AMMO_3RND in _GLMagazines) then {
|
||||
(_loadout select 0) pushBack _GLWeapon;
|
||||
(_loadout select 1) pushBack GRENADE_AMMO_3RND;
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
|
||||
} else {
|
||||
if (GRENADE_AMMO_1RND in _GLMagazines) then {
|
||||
(_loadout select 0) pushBack _GLWeapon;
|
||||
(_loadout select 1) pushBack GRENADE_AMMO_1RND;
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
|
||||
} forEach (units _unitGroup);
|
||||
};
|
||||
|
||||
true
|
@ -0,0 +1,9 @@
|
||||
private ["_unitGroup","_lootPool"];
|
||||
_unitGroup = _this select 0;
|
||||
_lootPool = _this select 1;
|
||||
|
||||
_unitGroup setVariable ["LootPool",_lootPool];
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Updated group %1 loot pool to %2.",_unitGroup,_lootPool];};
|
||||
|
||||
true
|
@ -0,0 +1,10 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_groupSize"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_groupSize = _this select 1;
|
||||
|
||||
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||
|
||||
true
|
@ -0,0 +1,3 @@
|
||||
A3XAI_updateGroupLoot_PVS = _this;
|
||||
publicVariableServer "A3XAI_updateGroupLoot_PVS";
|
||||
true
|
@ -0,0 +1,8 @@
|
||||
private ["_unitGroup","_status"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_status = _this select 1;
|
||||
|
||||
_unitGroup setVariable ["NoAggroStatus",_status];
|
||||
|
||||
true
|
@ -0,0 +1,49 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_HCObject","_versionHC","_compatibleVersions","_positionHC","_useRemoteConfigs"];
|
||||
_HCObject = _this select 0;
|
||||
_versionHC = _this select 1;
|
||||
_useRemoteConfigs = _this select 2;
|
||||
|
||||
A3XAI_HC_serverResponse = false;
|
||||
if (((owner A3XAI_HCObject) isEqualTo 0) && {(typeOf _HCObject) isEqualTo "HeadlessClient_F"}) then {
|
||||
_compatibleVersions = [configFile >> "CfgPatches" >> "A3XAI","compatibleHCVersions",[]] call BIS_fnc_returnConfigEntry;
|
||||
if (_versionHC in _compatibleVersions) then {
|
||||
A3XAI_HCObject = _HCObject;
|
||||
A3XAI_HCObject allowDamage false;
|
||||
A3XAI_HCObject enableSimulationGlobal false;
|
||||
A3XAI_HCObject addEventHandler ["Local",{
|
||||
if (_this select 1) then {
|
||||
private["_unit","_unitGroup"];
|
||||
A3XAI_HCIsConnected = false;
|
||||
A3XAI_HCObjectOwnerID = 0;
|
||||
A3XAI_HCObject = objNull;
|
||||
_unit = _this select 0;
|
||||
_unitGroup = (group _unit);
|
||||
_unit removeAllEventHandlers "Local";
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Deleting disconnected headless client unit %1.",typeOf _unit];};
|
||||
deleteVehicle _unit;
|
||||
deleteGroup _unitGroup;
|
||||
};
|
||||
}];
|
||||
A3XAI_HCObjectOwnerID = (owner A3XAI_HCObject);
|
||||
A3XAI_HCIsConnected = true;
|
||||
A3XAI_HC_serverResponse = if (_useRemoteConfigs) then {
|
||||
A3XAI_pushedHCVariables
|
||||
} else {
|
||||
true
|
||||
};
|
||||
_positionHC = getPosATL A3XAI_HCObject;
|
||||
if (({if (_positionHC in _x) exitWith {1}} count (nearestLocations [_positionHC,[BLACKLIST_OBJECT_GENERAL],BLACKLIST_AREA_HC_SIZE])) isEqualTo 0) then {
|
||||
[_positionHC,TEMP_BLACKLIST_AREA_HC_SIZE] call A3XAI_createBlackListArea;
|
||||
diag_log format ["[A3XAI] Created 750m radius blacklist area at HC position %1",_positionHC];
|
||||
};
|
||||
diag_log format ["[A3XAI] Headless client %1 (owner: %2) logged in successfully.",A3XAI_HCObject,A3XAI_HCObjectOwnerID];
|
||||
} else {
|
||||
diag_log format ["[A3XAI] Headless client %1 (owner: %2) has wrong A3XAI version %3 (Compatible versions: %4).",_HCObject,owner _HCObject,_versionHC,_compatibleVersions];
|
||||
};
|
||||
} else {
|
||||
diag_log format ["[A3XAI] Rejecting connection from HC %1. A headless client is already connected: %2. Client object type: %3.",(_this select 1),!((owner A3XAI_HCObject) isEqualTo 0),typeOf _HCObject];
|
||||
};
|
||||
|
||||
(owner _HCObject) publicVariableClient "A3XAI_HC_serverResponse";
|
@ -0,0 +1,27 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_trigger", "_triggerVars", "_value"];
|
||||
|
||||
_unitGroup = _this;
|
||||
_trigger = _unitGroup getVariable ["trigger",A3XAI_defaultTrigger];
|
||||
_triggerVars = [_unitGroup];
|
||||
|
||||
{
|
||||
_value = _trigger getVariable [_x select 0,_x select 1];
|
||||
_triggerVars pushBack _value;
|
||||
} forEach [
|
||||
["GroupArray",[]],
|
||||
["patrolDist",100],
|
||||
["unitLevel",1],
|
||||
["unitLevelEffective",1],
|
||||
["maxUnits",[0,0]],
|
||||
["spawnChance",0],
|
||||
["spawnType",""],
|
||||
["respawn",true],
|
||||
["permadelete",false]
|
||||
];
|
||||
|
||||
A3XAI_sendGroupTriggerVars_PVC = _triggerVars;
|
||||
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_sendGroupTriggerVars_PVC";
|
||||
|
||||
if (A3XAI_debugLevel > 1) then {diag_log format ["A3XAI Debug: Retrieved group %1 trigger variables: %2",_unitGroup,_triggerVars];};
|
@ -0,0 +1,5 @@
|
||||
private ["_unitGroup","_dummy"];
|
||||
_unitGroup = _this select 0;
|
||||
_dummy = _this select 1;
|
||||
_unitGroup setVariable ["dummyUnit",_dummy];
|
||||
true
|
@ -0,0 +1,22 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_victim", "_killer", "_unitGroup", "_unitLevel","_groupSize","_newGroupSize"];
|
||||
|
||||
_victim = _this select 0;
|
||||
_killer = _this select 1;
|
||||
_unitGroup = _this select 2;
|
||||
|
||||
_victim setVariable ["A3XAI_deathTime",diag_tickTime];
|
||||
_unitLevel = (_unitGroup getVariable ["unitLevel",0]);
|
||||
|
||||
_groupSize = (_unitGroup getVariable ["GroupSize",0]);
|
||||
if (_groupSize > 0) then {
|
||||
_newGroupSize = (_groupSize - 1);
|
||||
_unitGroup setVariable ["GroupSize",_newGroupSize];
|
||||
};
|
||||
|
||||
if ((_unitGroup getVariable ["ReinforceAvailable",false]) && {isPlayer _killer} && {(missionNamespace getVariable [format ["A3XAI_airReinforcementSpawnChance%1",_unitLevel],0]) call A3XAI_chance}) then {
|
||||
_unitGroup setVariable ["ReinforceAvailable",false];
|
||||
if (A3XAI_debugLevel > 0) then {diag_log format ["A3XAI Debug: Group %1 (Level %2) is calling reinforcements.",_unitGroup,_unitLevel];};
|
||||
_nul = [(getPosATL _victim),_killer,_unitLevel] spawn A3XAI_spawn_reinforcement;
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
private ["_unitGroup","_mode"];
|
||||
_unitGroup = _this select 0;
|
||||
_mode = _this select 1;
|
||||
|
||||
call {
|
||||
if (_mode isEqualTo 0) exitWith {
|
||||
_unitGroup setBehaviour "CARELESS";
|
||||
{_x doWatch objNull} forEach (units _unitGroup);
|
||||
_unitGroup setVariable ["EnemiesIgnored",true];
|
||||
true
|
||||
};
|
||||
if (_mode isEqualTo 1) exitWith {
|
||||
_unitGroup setBehaviour "AWARE";
|
||||
_unitGroup setVariable ["EnemiesIgnored",false];
|
||||
true
|
||||
};
|
||||
false
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_lootPool","_miscData","_miscData2","_groupData""_result","_vehicle"];
|
||||
_unitGroup = _this;
|
||||
|
||||
if ((diag_tickTime - A3XAI_lastGroupTransfer) < 5) exitWith {false};
|
||||
A3XAI_lastGroupTransfer = diag_tickTime;
|
||||
|
||||
_unitLevel = _unitGroup getVariable ["unitLevel",0];
|
||||
_trigger = _unitGroup getVariable ["trigger",nil];
|
||||
_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||
_groupSize = _unitGroup getVariable ["GroupSize",nil];
|
||||
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||
_miscData = _unitGroup getVariable ["MiscData",nil];
|
||||
_miscData2 = _unitGroup getVariable ["MiscData2",nil];
|
||||
_vehicle = _unitGroup getVariable ["assignedVehicle",nil];
|
||||
|
||||
_groupData = [_unitGroup,_unitLevel,nil,_unitType,_groupSize,_lootPool];
|
||||
|
||||
if (!isNil "_trigger") then {_groupData set [2,(getPosATL _trigger)];};
|
||||
if (!isNil "_vehicle") then {_groupData set [2,_vehicle];};
|
||||
if (!isNil "_miscData") then {_groupData set [6,_miscData];};
|
||||
if (!isNil "_miscData2") then {_groupData set [7,_miscData2];};
|
||||
|
||||
A3XAI_transferGroup_PVC = _groupData;
|
||||
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_transferGroup_PVC";
|
||||
|
||||
_result = _unitGroup setGroupOwner A3XAI_HCObjectOwnerID;
|
||||
|
||||
_result
|
@ -0,0 +1,7 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup"];
|
||||
_unitGroup = _this;
|
||||
_unitGroup setGroupOwner 2;
|
||||
|
||||
true
|
@ -0,0 +1,11 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_targetPlayer"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_targetPlayer = _this select 1;
|
||||
|
||||
A3XAI_sendHunterGroupHC = [_unitGroup,_targetPlayer];
|
||||
A3XAI_HCObjectOwnerID publicVariableClient "A3XAI_sendHunterGroupHC";
|
||||
|
||||
true
|
@ -0,0 +1,10 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_lootPool","_lootIndex"];
|
||||
_unitGroup = _this select 0;
|
||||
_lootIndex = _this select 1;
|
||||
|
||||
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||
_lootPool deleteAt _lootIndex;
|
||||
|
||||
true
|
@ -0,0 +1,10 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_unitGroup","_groupSize"];
|
||||
|
||||
_unitGroup = _this select 0;
|
||||
_groupSize = _this select 1;
|
||||
|
||||
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||
|
||||
true
|
@ -0,0 +1,21 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_vehicle","_unitGroup","_unitLevel"];
|
||||
|
||||
_vehicle = (_this select 0);
|
||||
|
||||
if (isNull _vehicle) exitWith {};
|
||||
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
|
||||
_vehicle setVariable ["vehicle_disabled",true];
|
||||
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed","Hit","Hit"];
|
||||
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
|
||||
_vehicle 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];};
|
@ -0,0 +1,21 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private ["_vehicle","_unitGroup","_unitsAlive"];
|
||||
|
||||
_vehicle = (_this select 0);
|
||||
|
||||
if (isNull _vehicle) exitWith {};
|
||||
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
|
||||
_vehicle setVariable ["vehicle_disabled",true];
|
||||
{_vehicle removeAllEventHandlers _x} count ["HandleDamage","GetOut","Killed","Hit","Hit"];
|
||||
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
|
||||
_vehicle 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];};
|
@ -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
|
@ -0,0 +1,77 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private["_object","_hit","_damage","_source","_ammo","_partdamage","_durability","_objectGroup","_currentDamage","_hitPoint"];
|
||||
|
||||
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
|
||||
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
|
||||
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
|
||||
_source = _this select 3; //The source unit that caused the damage.
|
||||
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
|
||||
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
|
||||
|
||||
_hitPoint = (_object getHitIndex _hitPartIndex);
|
||||
if (_damage > _hitPoint) then {
|
||||
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
|
||||
if ((group _object) call A3XAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
|
||||
|
||||
_durability = _object getVariable "durability";
|
||||
if (isNil "_durability") then {
|
||||
_object setVariable ["durability",[0,0,0,0]];
|
||||
_durability = _object getVariable "durability";
|
||||
};
|
||||
|
||||
if ((side _source) != A3XAI_side) then {
|
||||
_destroyed = false;
|
||||
_disabled = false;
|
||||
call {
|
||||
if (_hit isEqualTo "hull_hit") exitWith {
|
||||
//Structural damage
|
||||
_currentDamage = (_durability select 0);
|
||||
_partdamage = _currentDamage + (_damage - _currentDamage);
|
||||
_durability set [0,_partdamage];
|
||||
if ((_partdamage > 0.9) && {alive _object}) then {
|
||||
_damage = _hitPoint;
|
||||
_destroyed = true;
|
||||
_disabled = true;
|
||||
};
|
||||
};
|
||||
if (_hit in ["engine_hit","engine_1_hit","engine_2_hit","engine_3_hit","engine_4_hit"]) exitWith {
|
||||
_currentDamage = (_durability select 1);
|
||||
_partdamage =_currentDamage + (_damage - _currentDamage);
|
||||
_durability set [1,_partdamage];
|
||||
if ((_partdamage > 0.9) && {alive _object}) then {
|
||||
_damage = _hitPoint;
|
||||
_destroyed = true;
|
||||
_disabled = true;
|
||||
};
|
||||
};
|
||||
if (_hit in ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"]) exitWith {
|
||||
_currentDamage = (_durability select 2);
|
||||
_partdamage = _currentDamage + (_damage - _currentDamage);
|
||||
_durability set [2,_partdamage];
|
||||
if ((_partdamage > 0.9)&& {alive _object}) then {
|
||||
{
|
||||
_object setHit [_x,1];
|
||||
} forEach ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"];
|
||||
_destroyed = false;
|
||||
_disabled = true;
|
||||
};
|
||||
};
|
||||
if (_hit isEqualTo "fuel_hit") exitWith {_damage = _hitPoint};
|
||||
};
|
||||
if (_disabled) then {
|
||||
0 = [_object] call A3XAI_heliEvacuated;
|
||||
//{_object removeAllEventHandlers _x} forEach ["HandleDamage","GetOut","Killed","Hit"];
|
||||
if (_destroyed) then {
|
||||
_nul = _object spawn {
|
||||
uiSleep 3;
|
||||
_this setVehicleAmmo 0;
|
||||
_this setFuel 0;
|
||||
_this setDamage 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
_damage
|
@ -0,0 +1,22 @@
|
||||
#include "\A3XAI\globaldefines.hpp"
|
||||
|
||||
private["_object","_hit","_damage","_source","_ammo","_hitPoint"];
|
||||
|
||||
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
|
||||
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
|
||||
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
|
||||
_source = _this select 3; //The source unit that caused the damage.
|
||||
//_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
|
||||
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
|
||||
|
||||
_hitPoint = (_object getHitIndex _hitPartIndex);
|
||||
if (_damage > _hitPoint) then {
|
||||
call {
|
||||
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
|
||||
if ((group _object) call A3XAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
|
||||
if ((side _source) isEqualTo A3XAI_side) exitWith {_damage = _hitPoint;};
|
||||
if ((_hit find "wheel") > -1) exitWith {_damage = _hitPoint;};
|
||||
};
|
||||
};
|
||||
|
||||
_damage
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user