Merge branch 'A3EAI-Test'
This commit is contained in:
commit
ecce8c725d
1
Server/@A3EAI/addons/a3eai/$PREFIX$
Normal file
1
Server/@A3EAI/addons/a3eai/$PREFIX$
Normal file
@ -0,0 +1 @@
|
|||||||
|
A3EAI
|
1
Server/@A3EAI/addons/a3eai/PboPrefix.txt
Normal file
1
Server/@A3EAI/addons/a3eai/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
|
@ -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 A3EAI_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 A3EAI_SHK_pos_fnc_getMarkerShape;
|
||||||
|
|
||||||
|
if (_shape == "ICON") then {
|
||||||
|
// Icon has only one position, so if it equals to the given position, then it's blacklisted.
|
||||||
|
if ([_pos,_center] call A3EAI_SHK_pos_fnc_isSamePosition) then {
|
||||||
|
_return = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Markers that have an area.
|
||||||
|
} else {
|
||||||
|
if (_shape in ["RECTANGLE","SQUARE"]) then {
|
||||||
|
private ["_corners"];
|
||||||
|
_corners = _area call A3EAI_SHK_pos_fnc_getMarkerCorners;
|
||||||
|
|
||||||
|
// If rectangle is not axis-aligned.
|
||||||
|
if (_dir % 90 != 0) then {
|
||||||
|
// Add the point position to the array to have it shifted by the FOR below
|
||||||
|
_corners set [4,_pos];
|
||||||
|
|
||||||
|
// Rotate each corner position so that the rectangle is aligned with x and y axises
|
||||||
|
// Use origo as center while rotating, but for comparison shift positions back
|
||||||
|
private ["_posCor","_posNew","_orgX","_orgY","_shiftedX","_shiftedY","_newX","_newY"];
|
||||||
|
for "_i" from 0 to (count _corners - 1) do {
|
||||||
|
_posCor = _corners select _i;
|
||||||
|
|
||||||
|
// Original coordinates
|
||||||
|
_orgX = _posCor select 0;
|
||||||
|
_orgY = _posCor select 1;
|
||||||
|
|
||||||
|
// Subtract the marker center coordinates from corner coordinates.
|
||||||
|
// Rotation is done using origo (0,0) as anchor/centerpoint.
|
||||||
|
_shiftedX = _orgX - _centerX;
|
||||||
|
_shiftedY = _orgY - _centerY;
|
||||||
|
|
||||||
|
// Axis-aligned corner position
|
||||||
|
_posNew = [[_shiftedX,_shiftedY],_dir] call A3EAI_SHK_pos_fnc_rotatePosition;
|
||||||
|
|
||||||
|
// Shift the aligned corner position back near to the original marker location.
|
||||||
|
_newX = _posNew select 0;
|
||||||
|
_newY = _posNew select 1;
|
||||||
|
_newX = _newX + _centerX;
|
||||||
|
_newY = _newY + _centerY;
|
||||||
|
|
||||||
|
_posCor = [_newX,_newY];
|
||||||
|
|
||||||
|
_corners set [_i,_posCor];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Point position
|
||||||
|
_pos = _corners select 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the position is within the marker area.
|
||||||
|
_return = [_pos,_corners] call A3EAI_SHK_pos_fnc_isInRectangle;
|
||||||
|
} else {
|
||||||
|
if (_shape == "CIRCLE") then {
|
||||||
|
_return = [_pos,_area] call A3EAI_SHK_pos_fnc_isInCircle;
|
||||||
|
} else {
|
||||||
|
_return = [_pos,_area] call A3EAI_SHK_pos_fnc_isInEllipse;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_return
|
@ -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 A3EAI_SHK_pos_fnc_rotatePosition;
|
||||||
|
_pos set [0,(_pos select 0) + _centerX];
|
||||||
|
_pos set [1,(_pos select 1) + _centerY];
|
||||||
|
};
|
||||||
|
// Dot position
|
||||||
|
private ["_posX","_posY"];
|
||||||
|
_posX = _pos select 0;
|
||||||
|
_posY = _pos select 1;
|
||||||
|
|
||||||
|
// Distance between dot and ellipse center
|
||||||
|
private ["_dstX","_dstY"];
|
||||||
|
_dstX = abs(_posX - _centerX);
|
||||||
|
_dstY = abs(_posY - _centerY);
|
||||||
|
|
||||||
|
private ["_sum"];
|
||||||
|
_sum = ((_dstX * _dstX)/(_sizeX * _sizeX)) + ((_dstY * _dstY)/(_sizeY * _sizeY));
|
||||||
|
|
||||||
|
if (_sum <= 1) then {
|
||||||
|
_return = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
_return
|
@ -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
Server/@A3EAI/addons/a3eai/SHK_pos/A3EAI_SHK_pos_getpos.sqf
Normal file
170
Server/@A3EAI/addons/a3eai/SHK_pos/A3EAI_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 A3EAI_SHK_pos_fnc_getPos;
|
||||||
|
|
||||||
|
// Water position
|
||||||
|
if (typeName _water == "SCALAR") then {
|
||||||
|
switch _water do {
|
||||||
|
case 0: { // Water not allowed
|
||||||
|
if (surfaceIsWater _pos) then {
|
||||||
|
private ["_p","_d","_l"];
|
||||||
|
_d = 0; _l = true;
|
||||||
|
|
||||||
|
// Search for a land position starting from the randomly picked position and
|
||||||
|
// then going outwards from it in full circles in 20m steps.
|
||||||
|
while {_d = _d + 20; _l && _d < 5000} do {
|
||||||
|
for "_i" from 0 to 340 step 20 do {
|
||||||
|
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
|
||||||
|
if (!surfaceIsWater _p) exitwith {_l = false};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
case 1: { // Water allowed
|
||||||
|
|
||||||
|
};
|
||||||
|
case 2: { // Only water allowed
|
||||||
|
if !(surfaceIsWater _pos) then {
|
||||||
|
private ["_p","_d","_l"];
|
||||||
|
_d = 0; _l = true;
|
||||||
|
|
||||||
|
// Search for a water position starting from the randomly picked position and
|
||||||
|
// then going outwards from it in full circles in 20m steps.
|
||||||
|
while {_d = _d + 20; _l && _d < 5000} do {
|
||||||
|
for "_i" from 0 to 340 step 20 do {
|
||||||
|
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
|
||||||
|
if (surfaceIsWater _p) exitwith {_l = false};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else { // For backward compatibility
|
||||||
|
// Water position is not allowed
|
||||||
|
if !_water then {
|
||||||
|
if (surfaceIsWater _pos) then {
|
||||||
|
private ["_p","_d","_l"];
|
||||||
|
_d = 0; _l = true;
|
||||||
|
|
||||||
|
// Search for a land position starting from the randomly picked position and
|
||||||
|
// then going outwards from it in full circles in 20m steps.
|
||||||
|
while {_d = _d + 20; _l && _d < 5000} do {
|
||||||
|
for "_i" from 0 to 340 step 20 do {
|
||||||
|
_p = [_pos,_d,_i] call A3EAI_SHK_pos_fnc_getpos;
|
||||||
|
if (!surfaceIsWater _p) exitwith {_l = false};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Road position.
|
||||||
|
if (count _road > 0) then {
|
||||||
|
if ((_road select 0) > 0) then {
|
||||||
|
private ["_mode","_range","_roads","_cnt","_p","_p2"];
|
||||||
|
_mode = _road select 0;
|
||||||
|
_range = _road select 1;
|
||||||
|
_roads = _pos nearroads _range;
|
||||||
|
_cnt = count _roads;
|
||||||
|
_p = [];
|
||||||
|
|
||||||
|
// Road position(s) found.
|
||||||
|
if (_cnt > 0) then {
|
||||||
|
_p = getpos (_roads select 0);
|
||||||
|
|
||||||
|
// Found more than one road position, return closest.
|
||||||
|
if (_cnt > 1) then {
|
||||||
|
for "_i" from 1 to (_cnt - 1) do {
|
||||||
|
_p2 = getpos (_roads select _i);
|
||||||
|
if ((_p2 distance _pos) < (_p distance _pos)) then {
|
||||||
|
_p = _p2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
switch _mode do {
|
||||||
|
// Road position preferred but not forced.
|
||||||
|
case 1: {
|
||||||
|
if (count _p > 0) then {
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Only accept road position, return empty array if none found.
|
||||||
|
case 2: {
|
||||||
|
if (count _p > 0) then {
|
||||||
|
_pos = _p;
|
||||||
|
} else {
|
||||||
|
_pos resize 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find empty position
|
||||||
|
private ["_dst","_veh","_p"];
|
||||||
|
|
||||||
|
_dst = 200;
|
||||||
|
_veh = "";
|
||||||
|
switch (typename _empty) do {
|
||||||
|
case "OBJECT": { _veh = typeof _empty }; // Only vehicle given, use default distance
|
||||||
|
case "SCALAR": {_dst = _empty;};
|
||||||
|
case "ARRAY": {
|
||||||
|
if (count _empty > 0) then {
|
||||||
|
_dst = _empty select 0;
|
||||||
|
_veh = _empty select 1;
|
||||||
|
if (typename _veh == typename objNull) then { _veh = typeof _veh };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_p = [];
|
||||||
|
if (count _pos > 0) then {_p = _pos findEmptyPosition [0,_dst,_veh];};
|
||||||
|
|
||||||
|
|
||||||
|
// If an empty position is found, use it. Otherwise, return the original position.
|
||||||
|
if (count _p > 0) then {
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return position
|
||||||
|
_pos
|
@ -0,0 +1,101 @@
|
|||||||
|
/* Select a random position from an area defined by a marker.
|
||||||
|
In: [marker,water,blacklist,emptySpace]
|
||||||
|
Out: position
|
||||||
|
*/
|
||||||
|
private ["_area","_water","_blist","_pos","_empty"];
|
||||||
|
_area = _this select 0;
|
||||||
|
_water = if (count _this > 1) then {_this select 1} else {0};
|
||||||
|
_blist = if (count _this > 2) then {_this select 2} else {[]};
|
||||||
|
_empty = if (count _this > 3) then {_this select 3} else {[]};
|
||||||
|
_pos = [];
|
||||||
|
|
||||||
|
if (typename _blist == "STRING") then {_blist = [_blist]};
|
||||||
|
|
||||||
|
private ["_shape"];
|
||||||
|
_shape = _area call A3EAI_SHK_pos_fnc_getMarkerShape;
|
||||||
|
|
||||||
|
// Limited loop so the script won't get stuck
|
||||||
|
private ["_i","_exit"];
|
||||||
|
_exit = false;
|
||||||
|
for [{_i = 0}, {_i < 1000 && !_exit}, {_i = _i + 1}] do {
|
||||||
|
|
||||||
|
// Rectangle or Ellipse marker given?
|
||||||
|
if (_shape in ["SQUARE","RECTANGLE"]) then {
|
||||||
|
_pos = _area call A3EAI_SHK_pos_fnc_getPosFromRectangle;
|
||||||
|
} else {
|
||||||
|
_pos = _area call A3EAI_SHK_pos_fnc_getPosFromEllipse;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find empty position
|
||||||
|
private ["_dst","_veh","_p"];
|
||||||
|
|
||||||
|
_dst = 200;
|
||||||
|
_veh = "";
|
||||||
|
switch (typename _empty) do {
|
||||||
|
case (typename objNull): { _veh = typeof _empty }; // Only vehicle given, use default distance
|
||||||
|
case ("STRING"): { _veh = _empty };
|
||||||
|
case (typename []): {
|
||||||
|
if (count _empty > 0) then {
|
||||||
|
_dst = _empty select 0;
|
||||||
|
_veh = _empty select 1;
|
||||||
|
if (typename _veh == typename objNull) then { _veh = typeof _veh };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_p = _pos findEmptyPosition [0,_dst,_veh];
|
||||||
|
|
||||||
|
// If an empty position is found, use it. Otherwise, return the original position.
|
||||||
|
if (count _p > 0) then {
|
||||||
|
_pos = _p;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Water position
|
||||||
|
if (typeName _water == "SCALAR") then {
|
||||||
|
switch _water do {
|
||||||
|
|
||||||
|
case 0: { // Water position is not allowed
|
||||||
|
// Position is on land, try to exit script.
|
||||||
|
if !(surfaceIsWater _pos) then {
|
||||||
|
_exit = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
case 1: { // Doesn't matter if position is on water or land.
|
||||||
|
_exit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
case 2: { // Only water position is allowed
|
||||||
|
// Position is on water, try to exit script.
|
||||||
|
if (surfaceIsWater _pos) then {
|
||||||
|
_exit = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else { // For backward compatibility
|
||||||
|
// Water position is not allowed
|
||||||
|
if !_water then {
|
||||||
|
// Position is on land, try to exit script.
|
||||||
|
if !(surfaceIsWater _pos) then {
|
||||||
|
_exit = true;
|
||||||
|
};
|
||||||
|
// Doesn't matter if position is on water or land.
|
||||||
|
} else {
|
||||||
|
_exit = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Position is not allowed in blacklisted areas
|
||||||
|
if (count _blist > 0 && _exit) then {
|
||||||
|
// Check each blacklist marker
|
||||||
|
{
|
||||||
|
// If blacklisted, jump out of blacklist check and continue main loop.
|
||||||
|
if ([_pos,_x] call A3EAI_SHK_pos_fnc_isBlacklisted) exitwith {
|
||||||
|
_exit = false;
|
||||||
|
};
|
||||||
|
} foreach _blist;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return position
|
||||||
|
_pos
|
105
Server/@A3EAI/addons/a3eai/SHK_pos/A3EAI_SHK_pos_init.sqf
Normal file
105
Server/@A3EAI/addons/a3eai/SHK_pos/A3EAI_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\A3EAI_SHK_pos_init.sqf";
|
||||||
|
|
||||||
|
Actually getting the position:
|
||||||
|
pos = [parameters] call A3EAI_SHK_pos;
|
||||||
|
*/
|
||||||
|
// Functions
|
||||||
|
A3EAI_SHK_pos_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_getpos.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_getPosMarker = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_getposmarker.sqf",A3EAI_directory];
|
||||||
|
|
||||||
|
// Sub functions
|
||||||
|
A3EAI_SHK_pos_fnc_findClosestPosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_findclosestposition.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getMarkerCorners = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getmarkercorners.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getMarkerShape = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getmarkershape.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getPos = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getpos.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getPosFromCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromcircle.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getPosFromEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromellipse.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getPosFromRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromrectangle.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_getPosFromSquare = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_getposfromsquare.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_isBlacklisted = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isblacklisted.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_isInCircle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isincircle.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_isInEllipse = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isinellipse.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_isInRectangle = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_isinrectangle.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_isSamePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_issameposition.sqf",A3EAI_directory];
|
||||||
|
A3EAI_SHK_pos_fnc_rotatePosition = compileFinal preprocessFileLineNumbers format ["%1\shk_pos\A3EAI_SHK_pos_fnc_rotateposition.sqf",A3EAI_directory];
|
||||||
|
|
||||||
|
// Wrapper function
|
||||||
|
// Decide which function to call based on parameters.
|
||||||
|
A3EAI_SHK_pos = {
|
||||||
|
private ["_pos"];
|
||||||
|
_pos = [];
|
||||||
|
|
||||||
|
// Only marker is given as parameter
|
||||||
|
if (typename _this isEqualTo "STRING") then {
|
||||||
|
_pos = [_this] call A3EAI_SHK_pos_getPosMarker;
|
||||||
|
|
||||||
|
// Parameter array
|
||||||
|
} else {
|
||||||
|
if (typename (_this select 0) isEqualTo "STRING") then {
|
||||||
|
_pos = _this call A3EAI_SHK_pos_getPosMarker;
|
||||||
|
} else {
|
||||||
|
_pos = _this call A3EAI_SHK_pos_getPos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return position
|
||||||
|
_pos
|
||||||
|
};
|
@ -0,0 +1,233 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=======================================================================================================================
|
||||||
|
Script: BIN_taskPatrol.sqf v1.3
|
||||||
|
Author(s): Binesi
|
||||||
|
Partly based on original code by BIS
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Creates a continually randomized patrol path which circles and intersects a given position.
|
||||||
|
|
||||||
|
Parameter(s):
|
||||||
|
_this select 0: the group to which to assign the waypoints (Group)
|
||||||
|
_this select 1: the position on which to base the patrol (Array)
|
||||||
|
_this select 2: the maximum distance between waypoints (Number)
|
||||||
|
_this select 3: (optional) debug markers on or off (Number)
|
||||||
|
_this select 4: (optional) blacklist of areas (Array)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Boolean - success flag
|
||||||
|
|
||||||
|
Example(s):
|
||||||
|
null = [group this,(getPos this),250] execVM "BIN_taskPatrol.sqf"
|
||||||
|
null = [group this,(getPos this),250,1] execVM "BIN_taskPatrol.sqf" // Same with debug markers
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
Notes: Wolffy.au
|
||||||
|
If anyone is interested, I've made some additions to Binesi's BIN_taskPatrol script.
|
||||||
|
Random initial patrol direction - I noticed every patrol started off in the same direction, so I've randomised it.
|
||||||
|
Fixed the 2D position / findSafePos errors
|
||||||
|
Added building positions as possible patrol locations using Random Building Position Script v1.0 by Tophe of Östgöta Ops
|
||||||
|
Added check that BIS Functions has been initialized
|
||||||
|
|
||||||
|
ArmaIIholic
|
||||||
|
-- added JTD direction normalization function
|
||||||
|
-- changed numbers for waypoints to match previous waypoints
|
||||||
|
-- randomized initial direction - Wolffy.au added only the offset
|
||||||
|
-- fixed error with building position format
|
||||||
|
-- randomized initial direction -- Wolffy.au added only the offset which had to be reduced to 180
|
||||||
|
- however this script is making full circle from wherever it starts
|
||||||
|
|
||||||
|
Edited version for A3EAI (https://github.com/dayzai/A3EAI)
|
||||||
|
=======================================================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_pos = _this select 1;
|
||||||
|
_max_dist = _this select 2;
|
||||||
|
_unitType = _unitGroup getVariable ["unitType",""];
|
||||||
|
_allowWater = (_unitType in ["aircustom","air_reinforce"]);
|
||||||
|
_searchLoot = _unitType in ["static","vehiclecrew","dynamic","random"];
|
||||||
|
_isVehicle = (_unitType isEqualTo "landcustom");
|
||||||
|
_combatMode = (combatMode _unitGroup);
|
||||||
|
_behavior = (behaviour (leader _unitGroup));
|
||||||
|
|
||||||
|
if (_max_dist < 75) then {_unitGroup setSpeedMode "LIMITED"};
|
||||||
|
|
||||||
|
_randomizeChance = linearConversion [125,350,_max_dist,0.25,0.45,true];
|
||||||
|
//diag_log format ["DEBUG: PatrolDist %1 has RandomizeChance %2",_max_dist,_randomizeChance];
|
||||||
|
|
||||||
|
_wpStatements = call {
|
||||||
|
if (_searchLoot && {_max_dist > 100}) exitWith {format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint;} else {_nul = [group this] spawn A3EAI_areaSearching;};",_randomizeChance]};
|
||||||
|
if (_unitType isEqualTo "aircustom") exitWith {format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint;} else {_nul = [(assignedVehicle this),(group this)] spawn A3EAI_customHeliDetect;};",_randomizeChance]};
|
||||||
|
format ["if !(local this) exitWith {}; if (%1 call A3EAI_chance) then {_nul = [group this] call A3EAI_setRandomWaypoint};",_randomizeChance]
|
||||||
|
};
|
||||||
|
|
||||||
|
_wpTimeouts = if (_max_dist >= 100) then {[0, 3, 5]} else {[3, 6, 9]};
|
||||||
|
|
||||||
|
_center_x = (_pos) select 0;
|
||||||
|
_center_y = (_pos) select 1;
|
||||||
|
_center_z = (_pos) select 2;
|
||||||
|
if(isNil "_center_z")then{_center_z = 0;};
|
||||||
|
|
||||||
|
_allowInNoAggroArea = ([_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea);
|
||||||
|
_wp_count = 4 + (floor random 3) + (floor (_max_dist / 100 ));
|
||||||
|
_angle = (360 / (_wp_count -1));
|
||||||
|
|
||||||
|
_newangle = 0;
|
||||||
|
_wp_array = [];
|
||||||
|
_slack = _max_dist / 5.5;
|
||||||
|
_completionRadius = if (_isVehicle) then {(25 + _slack)} else {(10 + _slack)};
|
||||||
|
if ( _slack < 20 ) then { _slack = 20 };
|
||||||
|
|
||||||
|
_angle_offset = random 180;
|
||||||
|
while {count _wp_array < _wp_count} do {
|
||||||
|
private ["_x1","_y1","_wp_pos", "_prepos","_bldgpos","_bldgs","_a","_b"];
|
||||||
|
|
||||||
|
_newangle = (count _wp_array * _angle) + _angle_offset;
|
||||||
|
|
||||||
|
if ((_newangle > 360) || {_newangle < 0}) then
|
||||||
|
{
|
||||||
|
_newangle = abs (abs (_newangle) - 360);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((random 1) < 0.5) then
|
||||||
|
{
|
||||||
|
_newangle = -_newangle;
|
||||||
|
|
||||||
|
if ((_newangle > 360) || {_newangle < 0}) then
|
||||||
|
{
|
||||||
|
_newangle = abs (abs (_newangle) - 360);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_x1 = _center_x - (sin _newangle * _max_dist);
|
||||||
|
_y1 = _center_y - (cos _newangle * _max_dist);
|
||||||
|
|
||||||
|
_prepos = [_x1, _y1, _center_z];
|
||||||
|
if ( isNil "_center_z" ) then {
|
||||||
|
_prepos = [_x1, _y1];
|
||||||
|
};
|
||||||
|
|
||||||
|
_wp_pos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
|
||||||
|
|
||||||
|
_retry = false;
|
||||||
|
if (((surfaceIsWater _wp_pos) && {!_allowWater}) or {([_wp_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea) or {_allowInNoAggroArea}}) then {
|
||||||
|
_retry = true;
|
||||||
|
_retryCount = 0;
|
||||||
|
_retryPos = [];
|
||||||
|
_newMaxDist = _max_dist;
|
||||||
|
while {_retry && {_retryCount < 2}} do {
|
||||||
|
_newMaxDist = _newMaxDist * 0.5;
|
||||||
|
_x1 = _center_x - (sin _newangle * _newMaxDist);
|
||||||
|
_y1 = _center_y - (cos _newangle * _newMaxDist);
|
||||||
|
|
||||||
|
_prepos = [_x1, _y1, _center_z];
|
||||||
|
if ( isNil "_center_z" ) then {
|
||||||
|
_prepos = [_x1, _y1];
|
||||||
|
};
|
||||||
|
|
||||||
|
_retryPos = [_prepos, 0, _slack, 6, 0, 50 * (pi / 180), 0, [],[_prepos]] call BIS_fnc_findSafePos;
|
||||||
|
_retryCount = _retryCount + 1;
|
||||||
|
if ((!(surfaceIsWater _wp_pos) or {_allowWater}) && (!([_wp_pos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea) or {_allowInNoAggroArea})) then {
|
||||||
|
_retry = false;
|
||||||
|
_wp_pos = _retryPos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if !(_retry) then {
|
||||||
|
_a = 0 + (_wp_pos select 0);
|
||||||
|
_b = 0 + (_wp_pos select 1);
|
||||||
|
|
||||||
|
if (_searchLoot) then {
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// The following code is an extract from Random Building Position Script v1.0 by Tophe of Östgöta Ops
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
_bldgpos = [];
|
||||||
|
_bldgs = nearestObjects [[_a,_b,0], ["HouseBase"], 50];
|
||||||
|
{
|
||||||
|
private["_i","_y"];
|
||||||
|
_i = 0;
|
||||||
|
_y = _x buildingPos _i;
|
||||||
|
//while {format["%1", _y] != "[0,0,0]"} do {
|
||||||
|
while {!(_y isEqualTo [0,0,0]) } do {
|
||||||
|
//_bldgpos = _bldgpos + [_y];
|
||||||
|
_bldgpos pushBack _y;
|
||||||
|
_i = _i + 1;
|
||||||
|
_y = _x buildingPos _i;
|
||||||
|
};
|
||||||
|
} forEach _bldgs;
|
||||||
|
|
||||||
|
if(count _bldgpos != 0) then {_wp_pos = _bldgpos call A3EAI_selectRandom;};
|
||||||
|
} else {
|
||||||
|
if (_isVehicle) then {
|
||||||
|
_nearRoads = _wp_pos nearRoads ((_max_dist/2) min 100);
|
||||||
|
_roadsCount = count _nearRoads;
|
||||||
|
_returnPos = [];
|
||||||
|
if (_roadsCount > 0) then {
|
||||||
|
_returnPos = getPosATL (_nearRoads select 0);
|
||||||
|
if (_roadsCount > 1) then {
|
||||||
|
for "_i" from 1 to (_roadsCount -1) do {
|
||||||
|
_comparePos = getPosATL (_nearRoads select _i);
|
||||||
|
if ((_comparePos distance _wp_pos) < (_returnPos distance _wp_pos)) then {
|
||||||
|
_returnPos = _comparePos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_wp_pos = _returnPos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//_wp_array = _wp_array + [_wp_pos];
|
||||||
|
_wp_array pushBack _wp_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
uiSleep 0.25;
|
||||||
|
};
|
||||||
|
|
||||||
|
for "_i" from 1 to (_wp_count - 1) do
|
||||||
|
{
|
||||||
|
private ["_wp","_cur_pos"];
|
||||||
|
|
||||||
|
_cur_pos = (_wp_array select _i);
|
||||||
|
|
||||||
|
_wp = _unitGroup addWaypoint [_cur_pos, 0];
|
||||||
|
_wp setWaypointType "MOVE";
|
||||||
|
_wp setWaypointCompletionRadius _completionRadius;
|
||||||
|
_wp setWaypointTimeout [_wpTimeouts select 0, _wpTimeouts select 1, _wpTimeouts select 2];
|
||||||
|
_wp setWaypointStatements ["true",_wpStatements];
|
||||||
|
_wp setWaypointCombatMode _combatMode;
|
||||||
|
_wp setWaypointBehaviour _behavior;
|
||||||
|
uiSleep 0.25;
|
||||||
|
};
|
||||||
|
|
||||||
|
_endWP = [_pos, 0, 50, 6, 0, 50 * (pi / 180), 0, [],[_pos]] call BIS_fnc_findSafePos;
|
||||||
|
|
||||||
|
// End back near start point and then pick a new random point
|
||||||
|
_wp1 = _unitGroup addWaypoint [_endWP, 0];
|
||||||
|
_wp1 setWaypointType "MOVE";
|
||||||
|
_wp1 setWaypointCompletionRadius (_max_dist max 50);
|
||||||
|
_wp1 setWaypointCombatMode _combatMode;
|
||||||
|
_wp1 setWaypointBehaviour _behavior;
|
||||||
|
[_unitGroup,(count waypoints _unitGroup)] setWaypointStatements ["true", "if !(local this) exitWith {}; group this setCurrentWaypoint [(group this), (round (random 2) + 1)];"];
|
||||||
|
|
||||||
|
// Cycle in case we reach the end
|
||||||
|
_wp2 = _unitGroup addWaypoint [_endWP, 0];
|
||||||
|
_wp2 setWaypointType "CYCLE";
|
||||||
|
_wp2 setWaypointCompletionRadius (_max_dist max 50);
|
||||||
|
_wp2 setWaypointCombatMode _combatMode;
|
||||||
|
_wp2 setWaypointBehaviour _behavior;
|
||||||
|
|
||||||
|
for "_i" from ((count (waypoints _unitGroup)) - 1) to 0 step -1 do {
|
||||||
|
if ((getWPPos [_unitGroup,_i]) isEqualTo [0,0,0]) then {
|
||||||
|
diag_log format ["A3EAI Error: Waypoint %1 is invalid position.",[_unitGroup,_i]];
|
||||||
|
deleteWaypoint [_unitGroup,_i];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_enableHC && {_unitType in A3EAI_HCAllowedTypes}) then {_unitGroup setVariable ["HC_Ready",true];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,62 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_canCall","_vehicle","_detectStartPos","_searchLength"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||||
|
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
_canCall = true;
|
||||||
|
_searchLength = _unitGroup getVariable "SearchLength";
|
||||||
|
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
|
||||||
|
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
|
||||||
|
|
||||||
|
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3EAI_UAVCallReinforceCooldown])) > A3EAI_UAVCallReinforceCooldown) then {
|
||||||
|
_detectStartPos = getPosATL _vehicle;
|
||||||
|
_vehicle flyInHeight (FLYINHEIGHT_UAV_SEARCHING_BASE + (random FLYINHEIGHT_UAV_SEARCHING_VARIANCE));
|
||||||
|
_unitGroup getVariable ["IsDetecting",true];
|
||||||
|
|
||||||
|
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||||
|
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||||
|
_vehPos = getPosATL _vehicle;
|
||||||
|
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
|
||||||
|
_detected = (getPosATL _vehicle) nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UAV];
|
||||||
|
if ((count _detected) > 5) then {_detected resize 5};
|
||||||
|
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||||
|
{
|
||||||
|
_playerPos = getPosATL _x;
|
||||||
|
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||||
|
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_UAVDetectChance call A3EAI_chance}) then {
|
||||||
|
if (_canCall) then {
|
||||||
|
if (isDedicated) then {
|
||||||
|
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3EAI_spawn_reinforcement;
|
||||||
|
} else {
|
||||||
|
A3EAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
|
||||||
|
publicVariableServer "A3EAI_spawnReinforcements_PVS";
|
||||||
|
};
|
||||||
|
_unitGroup setVariable ["UVLastCall",diag_tickTime];
|
||||||
|
_canCall = false;
|
||||||
|
};
|
||||||
|
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||||
|
_unitGroup reveal [_x,2.5];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[41+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uiSleep 0.1;
|
||||||
|
} forEach _detected;
|
||||||
|
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||||
|
uiSleep 15;
|
||||||
|
|
||||||
|
_unitGroup getVariable ["IsDetecting",false];
|
||||||
|
};
|
||||||
|
|
||||||
|
_vehicle flyInHeight (FLYINHEIGHT_UAV_PATROLLING_BASE + (random FLYINHEIGHT_UAV_PATROLLING_VARIANCE));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -0,0 +1,30 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_tooClose","_detectionWaypoint","_exitWaypoint","_vehicle","_dirPosToVehicle","_locationSelected"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
|
||||||
|
_tooClose = true;
|
||||||
|
_locationSelected = [0,0,0];
|
||||||
|
|
||||||
|
while {_tooClose} do {
|
||||||
|
_locationSelected = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance _locationSelected) > NEXT_WP_DIST_UAV) then {
|
||||||
|
_tooClose = false;
|
||||||
|
} else {
|
||||||
|
uiSleep 0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_dirPosToVehicle = [_locationSelected,_vehicle] call BIS_fnc_dirTo;
|
||||||
|
_detectionWaypoint = [_locationSelected,WP_POS_INGRESS_BASE_UAV+(random WP_POS_INGRESS_VARIANCE_UAV),_dirPosToVehicle,1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWaypointPosition [_detectionWaypoint,0];
|
||||||
|
|
||||||
|
_dirPosToVehicle = [_vehicle,_locationSelected] call BIS_fnc_dirTo;
|
||||||
|
_exitWaypoint = [_detectionWaypoint,WP_POS_EGRESS_BASE_UAV+(random WP_POS_EGRESS_VARIANCE_UAV),_dirPosToVehicle,1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
|
||||||
|
|
||||||
|
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance _exitWaypoint)];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};
|
@ -0,0 +1,58 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_vehicle","_canCall"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||||
|
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
_canCall = true;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection start.",_unitGroup,(typeOf (_vehicle))];};
|
||||||
|
|
||||||
|
if ((diag_tickTime - (_unitGroup getVariable ["UVLastCall",-A3EAI_UGVCallReinforceCooldown])) > A3EAI_UGVCallReinforceCooldown) then {
|
||||||
|
_detectStartPos = getPosATL _vehicle;
|
||||||
|
_unitGroup getVariable ["IsDetecting",true];
|
||||||
|
|
||||||
|
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||||
|
private ["_detected","_detectOrigin","_startPos","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||||
|
_vehPos = getPosATL _vehicle;
|
||||||
|
_startPos = getPosATL _vehicle;
|
||||||
|
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
|
||||||
|
_detectOrigin = [_startPos,0,getDir _vehicle,1] call A3EAI_SHK_pos;
|
||||||
|
_detected = _detectOrigin nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_UGV];
|
||||||
|
if ((count _detected) > 5) then {_detected resize 5};
|
||||||
|
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||||
|
{
|
||||||
|
_playerPos = getPosATL _x;
|
||||||
|
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||||
|
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_UGVDetectChance call A3EAI_chance}) then {
|
||||||
|
if (_canCall) then {
|
||||||
|
if (isDedicated) then {
|
||||||
|
_nul = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]] spawn A3EAI_spawn_reinforcement;
|
||||||
|
} else {
|
||||||
|
A3EAI_spawnReinforcements_PVS = [_playerPos,_x,_unitGroup getVariable ["unitLevel",0]];
|
||||||
|
publicVariableServer "A3EAI_spawnReinforcements_PVS";
|
||||||
|
};
|
||||||
|
_unitGroup setVariable ["UVLastCall",diag_tickTime];
|
||||||
|
_canCall = false;
|
||||||
|
};
|
||||||
|
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||||
|
_unitGroup reveal [_x,2.5];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[51+(floor (random 5)),[_unitGroup,[configFile >> "CfgVehicles" >> (typeOf _vehicle),"displayName",""] call BIS_fnc_returnConfigEntry]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uiSleep 0.1;
|
||||||
|
} forEach _detected;
|
||||||
|
if (((_vehicle distance2D _detectStartPos) > DETECT_LENGTH_UGV_2D) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||||
|
uiSleep 15;
|
||||||
|
};
|
||||||
|
|
||||||
|
_unitGroup getVariable ["IsDetecting",false];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -0,0 +1,23 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_tooClose","_locationSelected"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
_tooClose = true;
|
||||||
|
_locationSelected = [0,0,0];
|
||||||
|
|
||||||
|
while {_tooClose} do {
|
||||||
|
_locationSelected = (A3EAI_locationsLand call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > 300) then {
|
||||||
|
_tooClose = false;
|
||||||
|
} else {
|
||||||
|
uiSleep 0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_locationSelected = [_locationSelected,random(300),random(360),0,[1,300]] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWPPos _locationSelected;
|
||||||
|
[_unitGroup,1] setWPPos _locationSelected;
|
||||||
|
[_unitGroup,2] setWaypointPosition [_locationSelected,0];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};
|
@ -0,0 +1,31 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_searchPoints", "_trigger", "_radius", "_posBetween", "_searchType", "_objects", "_waypoint"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
if ((count (waypoints _unitGroup)) > 9) exitWith {};
|
||||||
|
|
||||||
|
_searchPoints = call {
|
||||||
|
_trigger = _unitGroup getVariable "trigger";
|
||||||
|
if (isNil "_trigger") exitWith {[]};
|
||||||
|
_radius = (_trigger getVariable ["patrolDist",100])/2;
|
||||||
|
_posBetween = [_trigger,(leader _unitGroup),_radius] call A3EAI_getPosBetween;
|
||||||
|
_searchType = floor (random 2);
|
||||||
|
if (_searchType isEqualTo 0) exitWith {
|
||||||
|
_objects = _posBetween nearObjects [LOOT_HOLDER_CLASS,_radius];
|
||||||
|
_objects
|
||||||
|
};
|
||||||
|
if (_searchType isEqualTo 1) exitWith {
|
||||||
|
_objects = _posBetween nearEntities [[PLAYER_UNITS,"LandVehicle"],_radius];
|
||||||
|
_objects
|
||||||
|
};
|
||||||
|
[]
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
if ((count (waypoints _unitGroup)) > 9) exitWith {};
|
||||||
|
_waypoint = [_unitGroup,getPosATL _x] call A3EAI_addTemporaryWaypoint;
|
||||||
|
} forEach _searchPoints;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,34 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_detectOrigin", "_vehicle", "_detected", "_unitGroup", "_heliAimPos", "_playerAimPos"];
|
||||||
|
|
||||||
|
_vehicle = _this select 0;
|
||||||
|
_unitGroup = _this select 1;
|
||||||
|
|
||||||
|
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||||
|
_unitGroup setVariable ["IsDetecting",true];
|
||||||
|
|
||||||
|
uiSleep (round (random 20));
|
||||||
|
|
||||||
|
if (!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}) then{
|
||||||
|
_detectOrigin = [getPosATL _vehicle,0,getDir _vehicle,1] call A3EAI_SHK_pos;
|
||||||
|
_detectOrigin set [2,0];
|
||||||
|
_detected = _detectOrigin nearEntities [[PLAYER_UNITS],DETECT_RANGE_AIR_CUSTOM];
|
||||||
|
if ((count _detected) > 5) then {_detected resize 5};
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||||
|
_heliAimPos = aimPos _vehicle;
|
||||||
|
_playerAimPos = aimPos _x;
|
||||||
|
if (((lineIntersectsSurfaces [_heliAimPos,_playerEyePos,_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_airDetectChance call A3EAI_chance}) then {
|
||||||
|
//if (!(terrainIntersectASL [_heliAimPos,_playerAimPos]) && {!(lineIntersects [_heliAimPos,_playerAimPos,_vehicle,_x])} && {A3EAI_airDetectChance call A3EAI_chance}) then { //if no intersection of terrain and objects between helicopter and player, then reveal player
|
||||||
|
_unitGroup reveal [_x,2.5];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uiSleep 0.1;
|
||||||
|
} forEach _detected;
|
||||||
|
};
|
||||||
|
|
||||||
|
_unitGroup setVariable ["IsDetecting",false];
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_vehicle", "_hitSource", "_damage", "_unitGroup", "_aggroExpiry"];
|
||||||
|
|
||||||
|
_vehicle = _this select 0;
|
||||||
|
_hitSource = _this select 1;
|
||||||
|
_damage = _this select 2;
|
||||||
|
|
||||||
|
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
|
||||||
|
|
||||||
|
if (_unitGroup call A3EAI_getNoAggroStatus) exitWith {false};
|
||||||
|
|
||||||
|
if ((isPlayer _hitSource) && {_damage > 0.1} && {(combatMode _unitGroup isEqualTo "BLUE")}) then {
|
||||||
|
_aggroExpiry = diag_tickTime + DEFENSIVE_AGGRESSION_TIME;
|
||||||
|
_vehicle setVariable ["AggroTime",_aggroExpiry];
|
||||||
|
[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Defensive aggression enabled for %1 %2",_unitGroup,(typeOf _vehicle)];};
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,23 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_action", "_unitGroup"];
|
||||||
|
|
||||||
|
_action = _this select 1;
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
if (_action isEqualTo "IgnoreEnemies") exitWith {
|
||||||
|
_unitGroup setBehaviour "CARELESS";
|
||||||
|
_unitGroup setCombatMode "BLUE";
|
||||||
|
{_x doWatch objNull} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_action isEqualTo "Behavior_Reset") exitWith {
|
||||||
|
_unitGroup setBehaviour "AWARE";
|
||||||
|
_unitGroup setCombatMode "YELLOW";
|
||||||
|
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
false
|
@ -0,0 +1,55 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_detectBase","_vehicle","_canParaDrop","_detectStartPos","_searchLength"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
if (_unitGroup getVariable ["IsDetecting",false]) exitWith {};
|
||||||
|
if (_unitGroup getVariable ["EnemiesIgnored",false]) then {[_unitGroup,"Behavior_Reset"] call A3EAI_forceBehavior};
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
_searchLength = _unitGroup getVariable "SearchLength";
|
||||||
|
if (isNil "_searchLength") then {_searchLength = (waypointPosition [_unitGroup,0]) distance2D (waypointPosition [_unitGroup,1]);};
|
||||||
|
if (_vehicle isKindOf "Plane") then {_searchLength = _searchLength * 2;};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection started with search length %3.",_unitGroup,(typeOf (_vehicle)),_searchLength];};
|
||||||
|
|
||||||
|
_detectStartPos = getPosATL _vehicle;
|
||||||
|
_canParaDrop = ((diag_tickTime - (_unitGroup getVariable ["HeliLastParaDrop",-A3EAI_paradropCooldown])) > A3EAI_paradropCooldown);
|
||||||
|
_vehicle flyInHeight (FLYINHEIGHT_AIR_SEARCHING_BASE + (random FLYINHEIGHT_AIR_SEARCHING_VARIANCE));
|
||||||
|
_unitGroup getVariable ["IsDetecting",true];
|
||||||
|
|
||||||
|
while {!(_vehicle getVariable ["vehicle_disabled",false]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {local _unitGroup}} do {
|
||||||
|
private ["_detected","_vehPos","_nearBlacklistAreas","_playerPos","_canReveal"];
|
||||||
|
_vehPos = getPosATL _vehicle;
|
||||||
|
_canReveal = !((combatMode _unitGroup) isEqualTo "BLUE");
|
||||||
|
_detected = _vehPos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR];
|
||||||
|
if ((count _detected) > 5) then {_detected resize 5};
|
||||||
|
_nearBlacklistAreas = if (_detected isEqualTo []) then {[]} else {nearestLocations [_vehPos,[BLACKLIST_OBJECT_GENERAL],1500]};
|
||||||
|
{
|
||||||
|
_playerPos = getPosATL _x;
|
||||||
|
if ((isPlayer _x) && {({if (_playerPos in _x) exitWith {1}} count _nearBlacklistAreas) isEqualTo 0}) then {
|
||||||
|
if (_canParaDrop) then {
|
||||||
|
_canParaDrop = false;
|
||||||
|
_unitGroup setVariable ["HeliLastParaDrop",diag_tickTime];
|
||||||
|
_nul = [_unitGroup,_vehicle,_x] spawn A3EAI_heliParaDrop;
|
||||||
|
};
|
||||||
|
if (_canReveal && {(_unitGroup knowsAbout _x) < 2}) then {
|
||||||
|
if (((lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []) && {A3EAI_airDetectChance call A3EAI_chance}) then {
|
||||||
|
_unitGroup reveal [_x,2.5];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uiSleep 0.1;
|
||||||
|
} forEach _detected;
|
||||||
|
if (((_vehicle distance2D _detectStartPos) > _searchLength) or {_vehicle getVariable ["vehicle_disabled",false]}) exitWith {};
|
||||||
|
uiSleep 15;
|
||||||
|
|
||||||
|
_unitGroup getVariable ["IsDetecting",false];
|
||||||
|
};
|
||||||
|
|
||||||
|
_vehicle flyInHeight (FLYINHEIGHT_AIR_PATROLLING_BASE + (random FLYINHEIGHT_AIR_PATROLLING_VARIANCE));
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 %2 detection end.",_unitGroup,(typeOf (_vehicle))];};
|
@ -0,0 +1,30 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_tooClose","_detectionWaypoint","_exitWaypoint","_vehicle","_dir","_locationSelected"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
|
||||||
|
_tooClose = true;
|
||||||
|
_locationSelected = [0,0,0];
|
||||||
|
|
||||||
|
while {_tooClose} do {
|
||||||
|
_locationSelected = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > NEXT_WP_DIST_AIR) then {
|
||||||
|
_tooClose = false;
|
||||||
|
} else {
|
||||||
|
uiSleep 0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_dir = [_locationSelected,_vehicle] call BIS_fnc_dirTo;
|
||||||
|
_detectionWaypoint = [_locationSelected,WP_POS_INGRESS_BASE_AIR + (random WP_POS_INGRESS_VARIANCE_AIR),_dir,1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWaypointPosition [_detectionWaypoint,0];
|
||||||
|
|
||||||
|
_dir = [_vehicle,_locationSelected] call BIS_fnc_dirTo;
|
||||||
|
_exitWaypoint = [_detectionWaypoint,WP_POS_EGRESS_BASE_AIR + (random WP_POS_EGRESS_VARIANCE_AIR),_dir,1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,2] setWaypointPosition [_detectionWaypoint,0];
|
||||||
|
|
||||||
|
_unitGroup setVariable ["SearchLength",(_detectionWaypoint distance2D _exitWaypoint)];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 search length %2, waypoint position %3.",_unitGroup,_unitGroup getVariable "SearchLength",_locationSelected];};
|
@ -0,0 +1,141 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_targetPlayer","_startPos","_chaseDistance","_enableHCReady","_nearBlacklistedAreas","_targetPlayerPos"];
|
||||||
|
|
||||||
|
_targetPlayer = _this select 0;
|
||||||
|
_unitGroup = _this select 1;
|
||||||
|
|
||||||
|
//Disable killer-finding for dynamic AI in hunting mode
|
||||||
|
if (_unitGroup getVariable ["seekActive",false]) exitWith {};
|
||||||
|
|
||||||
|
//If group is already pursuing player and target player has killed another group member, then extend pursuit time.
|
||||||
|
if (((_unitGroup getVariable ["pursuitTime",0]) > 0) && {((_unitGroup getVariable ["targetKiller",""]) isEqualTo (name _targetPlayer))}) exitWith {
|
||||||
|
_unitGroup setVariable ["pursuitTime",((_unitGroup getVariable ["pursuitTime",0]) + 20)];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Pursuit time +20 sec for Group %1 (Target: %2) to %3 seconds.",_unitGroup,name _targetPlayer,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime]};
|
||||||
|
};
|
||||||
|
|
||||||
|
_enableHCReady = false;
|
||||||
|
if (_unitGroup getVariable ["HC_Ready",false]) then { //If HC mode enabled and AI group is controlled by server, prevent it from being transferred to HC until hunting mode is over.
|
||||||
|
_unitGroup setVariable ["HC_Ready",false];
|
||||||
|
_enableHCReady = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
_startPos = _unitGroup getVariable ["trigger",(getPosASL (leader _unitGroup))];
|
||||||
|
_chaseDistance = _unitGroup getVariable ["patrolDist",250];
|
||||||
|
_targetPlayerPos = getPosATL _targetPlayer;
|
||||||
|
_nearBlacklistedAreas = nearestLocations [_targetPlayerPos,[BLACKLIST_OBJECT_GENERAL],1500];
|
||||||
|
|
||||||
|
_unitGroup setFormDir ([(leader _unitGroup),_targetPlayerPos] call BIS_fnc_dirTo);
|
||||||
|
|
||||||
|
if ((_startPos distance _targetPlayerPos) < _chaseDistance) then {
|
||||||
|
private ["_leader","_ableToChase","_marker"];
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 has entered pursuit state for 180 seconds. Target: %2.",_unitGroup,_targetPlayer];};
|
||||||
|
|
||||||
|
//Set pursuit timer
|
||||||
|
_unitGroup setVariable ["pursuitTime",diag_tickTime+180];
|
||||||
|
_unitGroup setVariable ["targetKiller",name _targetPlayer];
|
||||||
|
|
||||||
|
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
_markername = format ["%1 Target",_unitGroup];
|
||||||
|
if (_markername in allMapMarkers) then {deleteMarker _markername; uiSleep 0.5;};
|
||||||
|
_marker = createMarker [_markername,getPosASL _targetPlayer];
|
||||||
|
_marker setMarkerText _markername;
|
||||||
|
_marker setMarkerType "mil_warning";
|
||||||
|
_marker setMarkerColor "ColorRed";
|
||||||
|
_marker setMarkerBrush "Solid";
|
||||||
|
};
|
||||||
|
|
||||||
|
//Begin pursuit state.
|
||||||
|
_ableToChase = true;
|
||||||
|
while {
|
||||||
|
_ableToChase &&
|
||||||
|
{isPlayer _targetPlayer} &&
|
||||||
|
{alive _targetPlayer} &&
|
||||||
|
{((_startPos distance _targetPlayer) < _chaseDistance)} &&
|
||||||
|
{(vehicle _targetPlayer) isKindOf "Land"}
|
||||||
|
} do {
|
||||||
|
_targetPlayerPos = getPosATL _targetPlayer;
|
||||||
|
if (({_targetPlayerPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
|
||||||
|
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
|
||||||
|
(units _unitGroup) doMove _targetPlayerPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: AI group %1 in pursuit state. Pursuit time remaining: %2 seconds.",_unitGroup,(_unitGroup getVariable ["pursuitTime",0]) - diag_tickTime];};
|
||||||
|
|
||||||
|
if ((A3EAI_enableRadioMessages) && {0.7 call A3EAI_chance}) then {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER}) then {
|
||||||
|
_nearbyUnits = _targetPlayerPos nearEntities [[PLAYER_UNITS,"LandVehicle"],TRANSMIT_RANGE_RADIO_HUNTKILLER];
|
||||||
|
if !(_nearbyUnits isEqualTo []) then { //Have at least 1 player to send a message to
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then { //Have at least 1 AI unit to send a message from
|
||||||
|
_speechIndex = (floor (random 3));
|
||||||
|
_radioSpeech = call {
|
||||||
|
if (_speechIndex isEqualTo 0) exitWith {
|
||||||
|
[1,[(name _leader),(name _targetPlayer)]]
|
||||||
|
};
|
||||||
|
if (_speechIndex isEqualTo 1) exitWith {
|
||||||
|
[2,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]
|
||||||
|
};
|
||||||
|
if (_speechIndex isEqualTo 2) exitWith {
|
||||||
|
[3,[(name _leader),round (_leader distance _targetPlayer)]]
|
||||||
|
};
|
||||||
|
[0,[]]
|
||||||
|
};
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||||
|
[_x,_radioSpeech] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
} count _nearbyUnits;
|
||||||
|
} else {
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||||
|
[_x,[0,[]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
} count _nearbyUnits;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
_marker setMarkerPos (getPosASL _targetPlayer);
|
||||||
|
};
|
||||||
|
_ableToChase = ((!isNull _unitGroup) && {diag_tickTime < (_unitGroup getVariable ["pursuitTime",0])} && {(_unitGroup getVariable ["GroupSize",0]) > 0});
|
||||||
|
if (_ableToChase) then {uiSleep 20};
|
||||||
|
};
|
||||||
|
|
||||||
|
if !(isNull _unitGroup) then {
|
||||||
|
//End of pursuit state. Re-enable patrol state.
|
||||||
|
_unitGroup setVariable ["pursuitTime",0];
|
||||||
|
_unitGroup setVariable ["targetKiller",""];
|
||||||
|
//_unitGroup lockWP false;
|
||||||
|
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
|
||||||
|
_waypoints = (waypoints _unitGroup);
|
||||||
|
_unitGroup setCurrentWaypoint (_waypoints call A3EAI_selectRandom);
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Pursuit state ended for group %1. Returning to patrol state. (fn_findKiller)",_unitGroup];};
|
||||||
|
|
||||||
|
if (A3EAI_enableRadioMessages) then {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((alive _leader) && {(_targetPlayer distance _leader) <= RECEIVE_DIST_RADIO_HUNTKILLER} && {((_unitGroup getVariable ["GroupSize",0]) > 1)} && {isPlayer _targetPlayer}) then {
|
||||||
|
_radioText = if (alive _targetPlayer) then {4} else {5};
|
||||||
|
_radioSpeech = [_radioText,[name (leader _unitGroup)]];
|
||||||
|
_nearbyUnits = (getPosASL _targetPlayer) nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTKILLER];
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||||
|
[_x,_radioSpeech] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
} count _nearbyUnits;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_enableHCReady) then {
|
||||||
|
_unitGroup setVariable ["HC_Ready",true];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
deleteMarker _marker;
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,80 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_targetPlayer", "_waypoint", "_leader", "_nearbyUnits", "_index", "_radioSpeech", "_searchPos","_triggerPos","_nearBlacklistedAreas","_targetPos"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
_triggerPos = getPosATL (_unitGroup getVariable ["trigger",objNull]);
|
||||||
|
_targetPlayer = _unitGroup getVariable ["targetplayer",objNull];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if !(isPlayer _targetPlayer) then {
|
||||||
|
throw "Target is not a player.";
|
||||||
|
};
|
||||||
|
|
||||||
|
_nearBlacklistedAreas = nearestLocations [_targetPlayer,[BLACKLIST_OBJECT_GENERAL],1500];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Hunter group %1 has target player %2 and anchor pos %3.",_unitGroup,_targetPlayer,_triggerPos];};
|
||||||
|
|
||||||
|
if (
|
||||||
|
(isPlayer _targetPlayer) &&
|
||||||
|
{alive _targetPlayer} &&
|
||||||
|
{(vehicle _targetPlayer) isKindOf "Land"} &&
|
||||||
|
{(_targetPlayer distance _triggerPos) < SEEK_RANGE_HUNTER}
|
||||||
|
) then {
|
||||||
|
_waypoint = [_unitGroup,0];
|
||||||
|
_targetPos = getPosATL _targetPlayer;
|
||||||
|
if (({_targetPos in _x} count _nearBlacklistedAreas) isEqualTo 0) then {
|
||||||
|
if (((getWPPos _waypoint) distance _targetPlayer) > 20) then {
|
||||||
|
_waypoint setWPPos _targetPos;
|
||||||
|
//diag_log format ["Debug: Hunter group %1 is seeking player %2 (position: %3).",_unitGroup,_targetPlayer,(getPosATL _targetPlayer)];
|
||||||
|
} else {
|
||||||
|
_searchPos = [(getWPPos _waypoint),20+(random 20),(random 360),0] call A3EAI_SHK_pos;
|
||||||
|
_waypoint setWPPos _searchPos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((_unitGroup knowsAbout _targetPlayer) < 4) then {_unitGroup reveal [_targetPlayer,4]};
|
||||||
|
_unitGroup setCurrentWaypoint _waypoint;
|
||||||
|
|
||||||
|
if (A3EAI_enableRadioMessages) then {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((_leader distance _targetPlayer) < RADIO_RECEPTION_RANGE) then {
|
||||||
|
_nearbyUnits = _targetPos nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTER];
|
||||||
|
if !(_nearbyUnits isEqualTo []) then {
|
||||||
|
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",0]) > 1) then {
|
||||||
|
_index = (floor (random 4));
|
||||||
|
_radioSpeech = call {
|
||||||
|
if (_index isEqualTo 0) exitWith {[11,[(name _leader),(name _targetPlayer)]]};
|
||||||
|
if (_index isEqualTo 1) exitWith {[12,[(name _leader),(getText (configFile >> "CfgVehicles" >> (typeOf _targetPlayer) >> "displayName"))]]};
|
||||||
|
if (_index isEqualTo 2) exitWith {[13,[(name _leader),round (_leader distance _targetPlayer)]]};
|
||||||
|
if (_index > 2) exitWith {[0,[]]};
|
||||||
|
[0,[]]
|
||||||
|
};
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||||
|
[_x,_radioSpeech] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
} count _nearbyUnits;
|
||||||
|
} else {
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0}) then {
|
||||||
|
[_x,[0,[]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
} count _nearbyUnits;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 has located player %2.",_unitGroup,_targetPlayer];};
|
||||||
|
} else {
|
||||||
|
throw "Hunt ended.";
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
[_unitGroup,0] setWaypointStatements ["true","if !(local this) exitWith {}; if ((random 1) < 0.50) then { group this setCurrentWaypoint [(group this), (floor (random (count (waypoints (group this)))))];};"];
|
||||||
|
0 = [_unitGroup,_triggerPos,PATROL_DIST_DYNAMIC] spawn A3EAI_BIN_taskPatrol;
|
||||||
|
_unitGroup setSpeedMode "FULL";
|
||||||
|
if (A3EAI_enableHC && {isDedicated}) then {_unitGroup setVariable ["MiscData",nil];};
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is patrolling area. (%2)",_unitGroup,_exception];};
|
||||||
|
};
|
@ -0,0 +1,85 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_waypoint", "_vehicle", "_endTime", "_vehiclePos", "_nearUnits", "_vehPos", "_despawnPos", "_reinforcePos","_vehicleArmed","_paraDrop","_reinforceTime"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
|
||||||
|
if (!hasInterface && !isDedicated) exitWith {diag_log format ["Error: %1 executed on headless client.",__FILE__];};
|
||||||
|
if !((typeName _unitGroup) isEqualTo "GROUP") exitWith {diag_log format ["A3EAI Error: Invalid group %1 provided to %2.",_unitGroup,__FILE__];};
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
_vehicleArmed = ((({_x call A3EAI_checkIsWeapon} count (weapons _vehicle)) > 0) || {({_x call A3EAI_checkIsWeapon} count (_vehicle weaponsTurret [-1])) > 0} || {(_vehicle call A3EAI_countVehicleGunners) > 0});
|
||||||
|
_reinforcePos = _unitGroup getVariable ["ReinforcePos",[0,0,0]];
|
||||||
|
|
||||||
|
if (_vehicleArmed) then {
|
||||||
|
_waypoint = [_unitGroup,0];
|
||||||
|
_waypoint setWaypointStatements ["true",""];
|
||||||
|
_waypoint setWaypointType "GUARD";
|
||||||
|
_waypoint setWaypointBehaviour "AWARE";
|
||||||
|
_waypoint setWaypointCombatMode "RED";
|
||||||
|
|
||||||
|
if (local _unitGroup) then {
|
||||||
|
_unitGroup setCurrentWaypoint _waypoint;
|
||||||
|
} else {
|
||||||
|
A3EAI_setCurrentWaypoint_PVC = _waypoint;
|
||||||
|
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_setCurrentWaypoint_PVC";
|
||||||
|
};
|
||||||
|
|
||||||
|
_reinforceTime = missionNamespace getVariable [format ["A3EAI_airReinforcementDuration%1",_unitGroup getVariable ["unitLevel",0]],0];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 is now reinforcing for %2 seconds.",_unitGroup,_reinforceTime];};
|
||||||
|
|
||||||
|
_unitGroup setSpeedMode "LIMITED";
|
||||||
|
_endTime = diag_tickTime + _reinforceTime;
|
||||||
|
while {(diag_tickTime < _endTime) && {(_unitGroup getVariable ["GroupSize",-1]) > 0} && {(_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce"}} do {
|
||||||
|
if (local _unitGroup) then {
|
||||||
|
_vehiclePos = getPosATL _vehicle;
|
||||||
|
_vehiclePos set [2,0];
|
||||||
|
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],DETECT_RANGE_AIR_REINFORCE];
|
||||||
|
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3} && {(lineIntersectsSurfaces [(aimPos _vehicle),(eyePos _x),_vehicle,_x,true,1]) isEqualTo []}) then {
|
||||||
|
_unitGroup reveal [_x,3];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} forEach _nearUnits;
|
||||||
|
};
|
||||||
|
uiSleep 15;
|
||||||
|
};
|
||||||
|
_unitGroup setSpeedMode "NORMAL";
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 reinforcement timer complete.",_unitGroup];};
|
||||||
|
} else {
|
||||||
|
_paraDrop = [_unitGroup,_vehicle,objNull] spawn A3EAI_heliParaDrop;
|
||||||
|
waitUntil {uiSleep 0.1; scriptDone _paraDrop};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (((_unitGroup getVariable ["GroupSize",-1]) < 1) or {!((_unitGroup getVariable ["unitType",""]) isEqualTo "air_reinforce")}) exitWith {
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (type: %2) is no longer reinforcing, reinforce timer exited.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])];};
|
||||||
|
};
|
||||||
|
|
||||||
|
_vehPos = (getPosATL _vehicle);
|
||||||
|
_despawnPos = [_vehPos,AIR_REINFORCE_DESPAWN_DIST,random(360),1] call A3EAI_SHK_pos;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 Vehicle %2 (pos %3) assigned despawn pos %4.",_unitGroup,(typeOf _vehicle),_vehPos,_despawnPos];};
|
||||||
|
|
||||||
|
_waypoint = _unitGroup addWaypoint [_despawnPos,0];
|
||||||
|
_waypoint setWaypointType "MOVE";
|
||||||
|
_waypoint setWaypointBehaviour "CARELESS";
|
||||||
|
if (_vehicleArmed) then {_waypoint setWaypointCombatMode "BLUE";};
|
||||||
|
if (local _unitGroup) then {
|
||||||
|
_unitGroup setCurrentWaypoint _waypoint;
|
||||||
|
} else {
|
||||||
|
A3EAI_setCurrentWaypoint_PVC = _waypoint;
|
||||||
|
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_setCurrentWaypoint_PVC";
|
||||||
|
};
|
||||||
|
|
||||||
|
waitUntil {uiSleep 15; (((getPosATL _vehicle) distance2D _vehPos) > 1200) or {!(alive _vehicle)}};
|
||||||
|
|
||||||
|
_unitGroup call A3EAI_cleanupReinforcementGroup;
|
||||||
|
A3EAI_reinforcedPositions = A3EAI_reinforcedPositions - _reinforcePos;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,47 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_triggerPos", "_targetPlayer", "_nearbyUnits", "_waypoint", "_patrolDist","_targetPos"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_patrolDist = _this select 1;
|
||||||
|
_targetPlayer = _this select 2;
|
||||||
|
_triggerPos = _this select 3;
|
||||||
|
|
||||||
|
_targetPos = getPosATL _targetPlayer;
|
||||||
|
if ((isPlayer _targetPlayer) && {(vehicle _targetPlayer) isKindOf "Land"}) then {
|
||||||
|
if (A3EAI_enableRadioMessages) then {
|
||||||
|
//diag_log "DEBUG: Sending radio static";
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {
|
||||||
|
_nearbyUnits = _targetPlayer nearEntities [["LandVehicle",PLAYER_UNITS],TRANSMIT_RANGE_RADIO_HUNTER];
|
||||||
|
if ((count _nearbyUnits) > 10) then {_nearbyUnits resize 10;};
|
||||||
|
{
|
||||||
|
if (isPlayer _x) then {
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[0,[]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} count _nearbyUnits;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_unitGroup setSpeedMode "FULL";
|
||||||
|
|
||||||
|
_waypoint = [_unitGroup,0]; //Group will move to waypoint index 0 (first waypoint).
|
||||||
|
_waypoint setWaypointType "MOVE";
|
||||||
|
_waypoint setWaypointCompletionRadius 50;
|
||||||
|
_waypoint setWaypointTimeout [3, 3, 3];
|
||||||
|
_waypoint setWPPos _targetPos;
|
||||||
|
_waypoint setWaypointStatements ["true","if !(local this) exitWith {}; (group this) spawn A3EAI_hunterLocate;"];
|
||||||
|
|
||||||
|
_unitGroup setCurrentWaypoint _waypoint;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["targetplayer",_targetPlayer];
|
||||||
|
if (A3EAI_enableHC && {"dynamic" in A3EAI_HCAllowedTypes}) then {
|
||||||
|
_unitGroup setVariable ["HC_Ready",true];
|
||||||
|
_unitGroup setVariable ["MiscData",_targetPlayer];
|
||||||
|
};
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is now hunting player %2.",_unitGroup,_targetPlayer];};
|
||||||
|
} else {
|
||||||
|
0 = [_unitGroup,_triggerPos,_patrolDist] spawn A3EAI_BIN_taskPatrol;
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Dynamic group %1 is patrolling area.",_unitGroup];};
|
||||||
|
};
|
@ -0,0 +1,43 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_vehicle","_loadWP","_loadWPCond","_unit","_regroupPos","_waypointCycle"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
if ((count (waypoints _unitGroup)) > 1) exitWith {
|
||||||
|
if (isNull (driver _vehicle)) then {
|
||||||
|
[_unitGroup,1] setWaypointPosition [(getPosATL _vehicle),0];
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,1];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_unit = objNull;
|
||||||
|
{
|
||||||
|
if (isNull (objectParent _x)) exitWith {_unit = _x};
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
if (isNull _unit) exitWith {_unitGroup call A3EAI_setVehicleRegrouped}; //If no units outside of vehicle, consider crew regrouped and exit script
|
||||||
|
|
||||||
|
_regroupPos = if (isNull (driver _vehicle)) then {
|
||||||
|
(getPosATL _vehicle)
|
||||||
|
} else {
|
||||||
|
([_vehicle,_unit,(_unit distance _vehicle)/2] call A3EAI_getPosBetween)
|
||||||
|
};
|
||||||
|
|
||||||
|
_loadWP = _unitGroup addWaypoint [_regroupPos,0];
|
||||||
|
_loadWP setWaypointType "LOAD";
|
||||||
|
_loadWPCond = "_vehicle = (group this) getVariable ['assignedVehicle',objNull]; ({_x isEqualTo (vehicle _x)} count (assignedCargo _vehicle)) isEqualTo 0";
|
||||||
|
_loadWP setWaypointStatements [_loadWPCond,"if !(local this) exitWith {}; (group this) spawn A3EAI_vehCrewRegroupComplete;"];
|
||||||
|
|
||||||
|
_waypointCycle = _unitGroup addWaypoint [_regroupPos, 0];
|
||||||
|
_waypointCycle setWaypointType "CYCLE";
|
||||||
|
_waypointCycle setWaypointStatements ["true","if !(local this) exitWith {}; _unitGroup = (group this); deleteWaypoint [_unitGroup,2]; deleteWaypoint [_unitGroup,1];"];
|
||||||
|
_waypointCycle setWaypointCompletionRadius 150;
|
||||||
|
|
||||||
|
_loadWP setWaypointCompletionRadius 10;
|
||||||
|
_unitGroup setCurrentWaypoint _loadWP;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Regroup order issued for AI group %1 to vehicle %2. Check WP count: %3.",_unitGroup,typeOf _vehicle,(count (waypoints _unitGroup))];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,16 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_vehicle","_vehiclePos"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",objNull];
|
||||||
|
if (isNull _vehicle) exitWith {diag_log format ["A3EAI Error: Group %1 has null vehicle.",_unitGroup];};
|
||||||
|
_vehiclePos = getPosATL _vehicle;
|
||||||
|
[_unitGroup,0] setWaypointPosition [_vehiclePos,0];
|
||||||
|
[_unitGroup,2] setWaypointPosition [_vehiclePos,0];
|
||||||
|
_unitGroup call A3EAI_setVehicleRegrouped;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Regroup completed for vehicle group %1.",_unitGroup];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,23 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_tooClose","_locationSelected"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
_tooClose = true;
|
||||||
|
_locationSelected = [0,0,0];
|
||||||
|
|
||||||
|
while {_tooClose} do {
|
||||||
|
_locationSelected = (A3EAI_locationsLand call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance2D _locationSelected) > 300) then {
|
||||||
|
_tooClose = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_locationSelected = [_locationSelected,random(300),random(360),0,[1,300]] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWPPos _locationSelected;
|
||||||
|
[_unitGroup,0] setWaypointCompletionRadius 150;
|
||||||
|
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,0];
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set %1 waypoint position to %2.",_unitGroup,_locationSelected];};
|
@ -0,0 +1,236 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_unitType", "_unitTypeRef", "_vehicle", "_stuckCheckTime", "_groupLeadMarker", "_groupWPMarker", "_fncArray", "_fnc_execEveryLoop", "_fnc_checkUnits",
|
||||||
|
"_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck", "_currentTime", "_managerStartTime", "_updateServerLoot", "_pullRate", "_markname", "_mark", "_markername", "_unitPos",
|
||||||
|
"_unitMarker", "_lootPool", "_result", "_debugStartTime"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitLevel = _this select 1;
|
||||||
|
|
||||||
|
if (_unitGroup getVariable ["isManaged",false]) exitWith {};
|
||||||
|
_unitGroup setVariable ["isManaged",true];
|
||||||
|
|
||||||
|
_unitType = (_unitGroup getVariable ["unitType",""]);
|
||||||
|
_unitTypeRef = _unitType;
|
||||||
|
_vehicle = if (_unitType in ["air","land","aircustom","landcustom","air_reinforce","uav","ugv"]) then {_unitGroup getVariable ["assignedVehicle",(assignedVehicle (leader _unitGroup))]} else {objNull};
|
||||||
|
|
||||||
|
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||||
|
if (isNil {_unitGroup getVariable "GroupSize"}) then {_unitGroup setVariable ["GroupSize",(count (units _unitGroup))]};
|
||||||
|
_stuckCheckTime = _unitType call A3EAI_getAntistuckTime;
|
||||||
|
|
||||||
|
//set up debug variables
|
||||||
|
_groupLeadMarker = "";
|
||||||
|
_groupWPMarker = "";
|
||||||
|
|
||||||
|
//Set up local functions
|
||||||
|
_fncArray = [_unitGroup,_unitType] call A3EAI_getLocalFunctions;
|
||||||
|
_fnc_execEveryLoop = _fncArray select 0;
|
||||||
|
_fnc_checkUnits = _fncArray select 1;
|
||||||
|
_fnc_generateLoot = _fncArray select 2;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
|
||||||
|
_fnc_antistuck = _fncArray select 4;
|
||||||
|
|
||||||
|
//Set up timer variables
|
||||||
|
_currentTime = diag_tickTime;
|
||||||
|
_managerStartTime = _currentTime;
|
||||||
|
_unitGroup setVariable ["lastRearmTime",_currentTime];
|
||||||
|
_unitGroup setVariable ["antistuckTime",_currentTime];
|
||||||
|
_unitGroup setVariable ["lootGenTime",_currentTime];
|
||||||
|
|
||||||
|
//Setup loot variables
|
||||||
|
_updateServerLoot = (A3EAI_enableHC && {!isDedicated});
|
||||||
|
_pullRate = 30;
|
||||||
|
|
||||||
|
if (isDedicated) then {
|
||||||
|
[_unitGroup,_unitType,_unitLevel] call A3EAI_setLoadoutVariables;
|
||||||
|
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
_groupLeadMarker = format ["%1_Lead",_unitGroup];
|
||||||
|
if (_groupLeadMarker in allMapMarkers) then {deleteMarker _groupLeadMarker; uiSleep 0.5}; //Delete the previous marker if it wasn't deleted for some reason.
|
||||||
|
_groupLeadMarker = createMarker [_groupLeadMarker,getPosATL (leader _unitGroup)];
|
||||||
|
_groupLeadMarker setMarkerType "mil_warning";
|
||||||
|
_groupLeadMarker setMarkerBrush "Solid";
|
||||||
|
|
||||||
|
if (isNull _vehicle) then {
|
||||||
|
_groupLeadMarker setMarkerText format ["%1 (AI L%2)",_unitGroup,_unitLevel];
|
||||||
|
} else {
|
||||||
|
_groupLeadMarker setMarkerText format ["%1 (AI L%2 %3)",_unitGroup,_unitLevel,(typeOf (vehicle (leader _unitGroup)))];
|
||||||
|
};
|
||||||
|
|
||||||
|
_groupWPMarker = (format ["%1_WP",_unitGroup]);
|
||||||
|
if (_groupWPMarker in allMapMarkers) then {deleteMarker _groupWPMarker; uiSleep 0.5;}; //Delete the previous marker if it wasn't deleted for some reason.
|
||||||
|
_groupWPMarker = createMarker [_groupWPMarker,(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||||
|
_groupWPMarker setMarkerText format ["%1 Waypoint",_unitGroup];
|
||||||
|
_groupWPMarker setMarkerType "Waypoint";
|
||||||
|
_groupWPMarker setMarkerColor "ColorBlue";
|
||||||
|
_groupWPMarker setMarkerBrush "Solid";
|
||||||
|
|
||||||
|
[_unitGroup] spawn {
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
{
|
||||||
|
_markname = str(_x);
|
||||||
|
if (_markname in allMapMarkers) then {deleteMarker _markname; uiSleep 0.5};
|
||||||
|
_mark = createMarker [_markname,getPosATL _x];
|
||||||
|
_mark setMarkerShape "ELLIPSE";
|
||||||
|
_mark setMarkerType "Dot";
|
||||||
|
_mark setMarkerColor "ColorRed";
|
||||||
|
_mark setMarkerBrush "SolidBorder";
|
||||||
|
_nul = _x spawn {
|
||||||
|
_markername = str (_this);
|
||||||
|
_unitGroup = group _this;
|
||||||
|
while {alive _this} do {
|
||||||
|
if (local _this) then {
|
||||||
|
_unitPos = getPosATL _this;
|
||||||
|
if ((leader _unitGroup) isEqualTo _this) then {
|
||||||
|
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
|
||||||
|
_color = call {
|
||||||
|
_combatMode = (combatMode _unitGroup);
|
||||||
|
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
|
||||||
|
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
|
||||||
|
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
|
||||||
|
"ColorBlack"
|
||||||
|
};
|
||||||
|
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
|
||||||
|
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
|
||||||
|
};
|
||||||
|
_markername setMarkerPos _unitPos;
|
||||||
|
};
|
||||||
|
uiSleep 10;
|
||||||
|
};
|
||||||
|
deleteMarker _markername;
|
||||||
|
};
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
waitUntil {uiSleep 0.25; (local _unitGroup)};
|
||||||
|
[_unitGroup,_unitType,_unitLevel] call A3EAI_setLoadoutVariables_HC;
|
||||||
|
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
{
|
||||||
|
_nul = _x spawn {
|
||||||
|
waitUntil {sleep 5; ((local _this) or {!(alive _this)})};
|
||||||
|
_unitMarker = str (_this);
|
||||||
|
_unitGroup = group _this;
|
||||||
|
while {alive _this} do {
|
||||||
|
if (local _this) then {
|
||||||
|
_unitPos = getPosATL _this;
|
||||||
|
if ((leader _unitGroup) isEqualTo _this) then {
|
||||||
|
(format ["%1_Lead",_unitGroup]) setMarkerPos _unitPos;
|
||||||
|
_color = call {
|
||||||
|
_combatMode = (combatMode _unitGroup);
|
||||||
|
if (_combatMode isEqualTo "YELLOW") exitWith {"ColorBlack"};
|
||||||
|
if (_combatMode isEqualTo "RED") exitWith {"ColorRed"};
|
||||||
|
if (_combatMode isEqualTo "BLUE") exitWith {"ColorBlue"};
|
||||||
|
"ColorBlack"
|
||||||
|
};
|
||||||
|
(format ["%1_Lead",_unitGroup]) setMarkerColor _color;
|
||||||
|
(format ["%1_WP",_unitGroup]) setMarkerPos (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
|
||||||
|
};
|
||||||
|
_unitMarker setMarkerPos _unitPos;
|
||||||
|
};
|
||||||
|
uiSleep 10;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {
|
||||||
|
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||||
|
//diag_log format ["Debug: Found loot pool for group %1 from server: %2",_unitGroup,_lootPool];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Main loop
|
||||||
|
while {(!isNull _unitGroup) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
|
||||||
|
_unitType = (_unitGroup getVariable ["unitType",""]);
|
||||||
|
if !(_unitType isEqualTo _unitTypeRef) then {
|
||||||
|
_fncArray = [_unitGroup,_unitType] call A3EAI_getLocalFunctions;
|
||||||
|
_fnc_execEveryLoop = _fncArray select 0;
|
||||||
|
_fnc_checkUnits = _fncArray select 1;
|
||||||
|
_fnc_generateLoot = _fncArray select 2;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = _fncArray select 3;
|
||||||
|
_fnc_antistuck = _fncArray select 4;
|
||||||
|
_stuckCheckTime = _unitType call A3EAI_getAntistuckTime;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reassigned group %1 type from %2 to %3.",_unitGroup,_unitTypeRef,_unitType];};
|
||||||
|
|
||||||
|
_unitTypeRef = _unitType;
|
||||||
|
};
|
||||||
|
|
||||||
|
[_unitGroup,_vehicle] call _fnc_execEveryLoop;
|
||||||
|
|
||||||
|
[_unitGroup] call _fnc_checkUnits;
|
||||||
|
|
||||||
|
//Generate loot
|
||||||
|
if ((diag_tickTime - (_unitGroup getVariable ["lootGenTime",diag_tickTime])) > _pullRate) then {
|
||||||
|
[_unitGroup,_unitLevel] call _fnc_generateLoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Vehicle ammo/fuel check
|
||||||
|
if ((alive _vehicle) && {(diag_tickTime - (_unitGroup getVariable ["lastRearmTime",0])) > 180}) then { //If _vehicle is objNull (if no vehicle was assigned to the group) then nothing in this bracket should be executed
|
||||||
|
[_unitGroup,_vehicle] call _fnc_vehicleAmmoFuelCheck;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Antistuck
|
||||||
|
if ((diag_tickTime - (_unitGroup getVariable ["antistuckTime",diag_tickTime])) > _stuckCheckTime) then {
|
||||||
|
[_unitGroup,_vehicle,_stuckCheckTime] call _fnc_antistuck;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_HCIsConnected && {_unitGroup getVariable ["HC_Ready",false]} && {(diag_tickTime - _managerStartTime) > 30}) then {
|
||||||
|
private ["_result"];
|
||||||
|
_result = _unitGroup call A3EAI_transferGroupToHC;
|
||||||
|
if (_result) then {
|
||||||
|
waitUntil {sleep 1.5; (!(local _unitGroup) or {isNull _unitGroup})};
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Transferred ownership of %1 group %2 to HC %3.",_unitType,_unitGroup,A3EAI_HCObjectOwnerID];};
|
||||||
|
waitUntil {sleep 15; ((local _unitGroup) or {isNull _unitGroup})};
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",-1]) > 0) then {
|
||||||
|
_currentTime = diag_tickTime;
|
||||||
|
_unitGroup call A3EAI_initNoAggroStatus;
|
||||||
|
_unitGroup setVariable ["lastRearmTime",_currentTime];
|
||||||
|
_unitGroup setVariable ["antistuckTime",_currentTime];
|
||||||
|
_unitGroup setVariable ["lootGenTime",_currentTime];
|
||||||
|
};
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 ownership was returned to server.",(_unitGroup getVariable ["unitType",_unitType]),_unitGroup];};
|
||||||
|
} else {
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Waiting to transfer %1 group %2 ownership to headless client (ID: %3).",_unitType,_unitGroup,A3EAI_HCObjectOwnerID];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//diag_log format ["DEBUG: Group Manager cycle time for group %1: %2 seconds.",_unitGroup,(diag_tickTime - _debugStartTime)];
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",0]) > 0) then {uiSleep 15};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_enableDebugMarkers) then {
|
||||||
|
deleteMarker _groupLeadMarker;
|
||||||
|
deleteMarker _groupWPMarker;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !(isNull _unitGroup) then {
|
||||||
|
_unitGroup setVariable ["isManaged",false]; //allow group manager to run again on group respawn.
|
||||||
|
|
||||||
|
if !(isDedicated) exitWith {
|
||||||
|
A3EAI_transferGroup_PVS = _unitGroup;
|
||||||
|
publicVariableServer "A3EAI_transferGroup_PVS"; //Return ownership to server.
|
||||||
|
A3EAI_HCGroupsCount = A3EAI_HCGroupsCount - 1;
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Returned ownership of AI %1 group %2 to server.",_unitType,_unitGroup];};
|
||||||
|
};
|
||||||
|
|
||||||
|
while {(_unitGroup getVariable ["GroupSize",-1]) isEqualTo 0} do { //Wait until group is either respawned or marked for deletion. A dummy unit should be created to preserve group.
|
||||||
|
uiSleep 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((_unitGroup getVariable ["GroupSize",-1]) isEqualTo -1) then { //GroupSize value of -1 marks group for deletion
|
||||||
|
if (!isNull _unitGroup) then {
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Deleting %2 group %1.",_unitGroup,(_unitGroup getVariable ["unitType","unknown"])]};
|
||||||
|
_unitGroup call A3EAI_deleteGroup;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
diag_log "A3EAI Error: An A3EAI-managed group was deleted unexpectedly!";
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((local _vehicle) && {isEngineOn _vehicle}) then {
|
||||||
|
_vehicle engineOn false;
|
||||||
|
};
|
@ -0,0 +1,37 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect", "_leader"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
|
||||||
|
_checkPos = (getPosATL _vehicle);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < ANTISTUCK_MIN_TRAVEL_DIST_AIR} && {canMove _vehicle}) then {
|
||||||
|
_tooClose = true;
|
||||||
|
_wpSelect = [];
|
||||||
|
while {_tooClose} do {
|
||||||
|
_wpSelect = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_AIR_MIN_WP_DIST) then {
|
||||||
|
_tooClose = false;
|
||||||
|
} else {
|
||||||
|
uiSleep 0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_wpSelect = [_wpSelect,ANTISTUCK_AIR_WP_DIST_BASE+(random ANTISTUCK_AIR_WP_DIST_VARIANCE),(random 360),1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWPPos _wpSelect;
|
||||||
|
[_unitGroup,1] setWPPos _wpSelect;
|
||||||
|
if ((count (waypoints _unitGroup)) > 2) then {[_unitGroup,2] setWPPos _wpSelect;};
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
_unitGroup setVariable ["antistuckPos",_wpSelect];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI air vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_currentWP", "_allWP", "_nextWP","_leader"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
|
||||||
|
_checkPos = (getWPPos [_unitGroup,(currentWaypoint _unitGroup)]);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((((_leader distance2D (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea}) && {_checkPos isEqualTo (_unitGroup getVariable ["antistuckPos",[0,0,0]])} && {canMove _vehicle}) then {
|
||||||
|
_currentWP = (currentWaypoint _unitGroup);
|
||||||
|
_allWP = (waypoints _unitGroup);
|
||||||
|
_nextWP = _currentWP + 1;
|
||||||
|
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 1}; //Cycle back to first added waypoint if group is currently on last waypoint.
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
|
||||||
|
_unitGroup setVariable ["antistuckPos",(getWPPos [_unitGroup,(currentWaypoint _unitGroup)])];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI air (custom) group %1. Forcing next waypoint.",_unitGroup];};
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_allWP", "_currentWP", "_nextWP","_leader"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
_allWP = (waypoints _unitGroup);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((count _allWP) > 1) then {
|
||||||
|
_checkPos = (getPosATL (leader _unitGroup));
|
||||||
|
if ((((_leader distance (_leader findNearestEnemy _leader)) > NEAREST_ENEMY_INFANTRY) or {[_checkPos,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea}) && ((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_INFANTRY) then {
|
||||||
|
_currentWP = (currentWaypoint _unitGroup);
|
||||||
|
_nextWP = _currentWP + 1;
|
||||||
|
if ((count _allWP) isEqualTo _nextWP) then {_nextWP = 0}; //Cycle back to first waypoint if group is currently on last waypoint.
|
||||||
|
[_unitGroup] call A3EAI_fixStuckGroup;
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,_nextWP];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI %1 group %2. Forcing next waypoint.",(_unitGroup getVariable ["unitType","unknown"]),_unitGroup];};
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,35 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_allWP", "_currentWP", "_nextWP","_leader"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
|
||||||
|
_checkPos = (getPosATL _vehicle);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_LAND) or {[_checkPos,NO_AGGRO_RANGE_LAND] call A3EAI_checkInNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_LAND}) then {
|
||||||
|
if (canMove _vehicle) then {
|
||||||
|
[_unitGroup] call A3EAI_fixStuckGroup;
|
||||||
|
if ((count (waypoints _unitGroup)) isEqualTo 1) then {
|
||||||
|
[_unitGroup,0] setWaypointPosition [_checkPos,0];
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,0];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for AI land vehicle %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
|
||||||
|
};
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
} else {
|
||||||
|
if (!(_vehicle getVariable ["vehicle_disabled",false])) then {
|
||||||
|
[_vehicle] call A3EAI_vehDestroyed;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: AI vehicle %1 (Group: %2) is immobilized. Respawning vehicle patrol group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
|
||||||
|
if (A3EAI_enableDebugMarkers) then {_checkPos call A3EAI_debugMarkerLocation;};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,37 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect","_leader"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
|
||||||
|
_checkPos = (getPosATL _vehicle);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_AIR) or {[_checkPos,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea}) && {_checkPos distance2D (_unitGroup getVariable ["antistuckPos",[0,0,0]]) < ANTISTUCK_MIN_TRAVEL_DIST_AIR} && {canMove _vehicle}) then {
|
||||||
|
_tooClose = true;
|
||||||
|
_wpSelect = [];
|
||||||
|
while {_tooClose} do {
|
||||||
|
_wpSelect = (A3EAI_locationsAir call A3EAI_selectRandom) select 1;
|
||||||
|
if (((waypointPosition [_unitGroup,0]) distance2D _wpSelect) < ANTISTUCK_AIR_MIN_WP_DIST) then {
|
||||||
|
_tooClose = false;
|
||||||
|
} else {
|
||||||
|
uiSleep 0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_wpSelect = [_wpSelect,ANTISTUCK_AIR_WP_DIST_BASE+(random ANTISTUCK_AIR_WP_DIST_VARIANCE),(random 360),1] call A3EAI_SHK_pos;
|
||||||
|
[_unitGroup,0] setWPPos _wpSelect;
|
||||||
|
[_unitGroup,1] setWPPos _wpSelect;
|
||||||
|
if ((count (waypoints _unitGroup)) > 2) then {[_unitGroup,2] setWPPos _wpSelect;};
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
_unitGroup setVariable ["antistuckPos",_wpSelect];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for UAV %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,34 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_stuckCheckTime", "_checkPos", "_tooClose", "_wpSelect"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
_stuckCheckTime = _this select 2;
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
|
||||||
|
_checkPos = (getPosATL _vehicle);
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
if ((((_leader distance (_leader findNearestEnemy _vehicle)) > NEAREST_ENEMY_LAND) or {[_checkPos,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea}) && {((_unitGroup getVariable ["antistuckPos",[0,0,0]]) distance _checkPos) < ANTISTUCK_MIN_TRAVEL_DIST_LAND}) then {
|
||||||
|
if (canMove _vehicle) then {
|
||||||
|
[_unitGroup] call A3EAI_fixStuckGroup;
|
||||||
|
[_unitGroup,0] setWaypointPosition [_checkPos,0];
|
||||||
|
[_unitGroup,1] setWaypointPosition [_checkPos,0];
|
||||||
|
_unitGroup setCurrentWaypoint [_unitGroup,1];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Antistuck triggered for UGV %1 (Group: %2). Forcing next waypoint.",(typeOf _vehicle),_unitGroup];};
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime + (_stuckCheckTime/2)];
|
||||||
|
} else {
|
||||||
|
if (!(_vehicle getVariable ["vehicle_disabled",false])) then {
|
||||||
|
[_vehicle] call A3EAI_UGV_destroyed;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: UGV %1 (Group: %2) is immobilized. Respawning UGV group. Damage: %3. WaterPos: %4.",(typeOf _vehicle),_unitGroup,(damage _vehicle),(surfaceIsWater _checkPos)];};
|
||||||
|
if (A3EAI_enableDebugMarkers) then {_checkPos call A3EAI_debugMarkerLocation;};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_unitGroup setVariable ["antistuckPos",_checkPos];
|
||||||
|
_unitGroup setVariable ["antistuckTime",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,13 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unit", "_loadout", "_currentMagazines", "_magazine"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
_result = _vehicle call A3EAI_reloadVehicleTurrets; //Rearms vehicle weapons/turrets individually
|
||||||
|
if ((A3EAI_debugLevel > 0) && {_result}) then {diag_log format ["A3EAI Debug: Reloaded ammo for group %1 %2.",_unitGroup,(typeOf _vehicle)];};
|
||||||
|
if ((fuel _vehicle) < 0.50) then {_vehicle setFuel 1; if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Refueled group %1 %2.",_unitGroup,(typeOf _vehicle)];};};
|
||||||
|
_unitGroup setVariable ["lastRearmTime",diag_tickTime];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,45 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unit", "_loadout", "_currentMagazines", "_magazine"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
if ((isNull (objectParent _x)) && {_x getVariable ["canCheckUnit",true]} && {local _x}) then {
|
||||||
|
_x setVariable ["canCheckUnit",false];
|
||||||
|
_nul = _x spawn {
|
||||||
|
if (!alive _this) exitWith {};
|
||||||
|
_unit = _this;
|
||||||
|
_loadout = _unit getVariable "loadout";
|
||||||
|
if (!isNil "_loadout") then {
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Unpacked unit manager for unit %1. Loadout found: %2.",_unit,_loadout];};
|
||||||
|
while {(alive _unit) && {isNull (objectParent _unit)} && {local _unit}} do {
|
||||||
|
_currentMagazines = (magazines _unit);
|
||||||
|
_magazine = ((_loadout select 1) select 0);
|
||||||
|
if (((_unit ammo ((_loadout select 0) select 0)) isEqualTo 0) || {!((_magazine in _currentMagazines))}) then {
|
||||||
|
_unit removeMagazines _magazine;
|
||||||
|
[_unit,_magazine] call A3EAI_addItem;
|
||||||
|
if (_unit getVariable ["extraMag",false]) then {
|
||||||
|
[_unit,_magazine] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for "_i" from 1 to ((count (_loadout select 0)) - 1) do {
|
||||||
|
_magazine = ((_loadout select 1) select _i);
|
||||||
|
if (((_unit ammo ((_loadout select 0) select _i)) isEqualTo 0) && {!((_magazine in _currentMagazines))}) then {
|
||||||
|
_unit removeMagazines _magazine;
|
||||||
|
[_unit,_magazine] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (alive _unit) then {uiSleep 15};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (alive _unit) then {
|
||||||
|
_unit setVariable ["canCheckUnit",true];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Repacking unit manager for unit %1.",_unit];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uiSleep 0.1;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle","_inNoAggroArea","_result","_leader", "_assignedTarget"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
_inArea = [_vehicle,NO_AGGRO_RANGE_AIR] call A3EAI_checkInNoAggroArea;
|
||||||
|
|
||||||
|
if !(_inArea) then {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||||
|
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_AIR) then { //900: replace with engagement range
|
||||||
|
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
|
||||||
|
};
|
||||||
|
}; //To test!
|
||||||
|
|
||||||
|
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,34 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_inArea", "_result", "_trigger", "_maxDistance","_leader", "_assignedTarget"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
//_vehicle = _this select 1;
|
||||||
|
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
_inArea = [_leader,NO_AGGRO_RANGE_MAN] call A3EAI_checkInNoAggroArea;
|
||||||
|
|
||||||
|
if !(_inArea) then {
|
||||||
|
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||||
|
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_MAN) then { //900: replace with engagement range
|
||||||
|
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if !(_inArea) then {
|
||||||
|
_trigger = _unitGroup getVariable "trigger";
|
||||||
|
if !(isNil "_trigger") then {
|
||||||
|
_maxDistance = _unitGroup getVariable ["patrolDist",250];
|
||||||
|
if ((_leader distance2D _trigger) > (_maxDistance + PATROL_DISTANCE_BUFFER)) then {
|
||||||
|
_randomWaypoint = _unitGroup call A3EAI_setRandomWaypoint;
|
||||||
|
(units _unitGroup) doMove (waypointPosition _randomWaypoint);
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 moved beyond allowed patrol radius, ordering group towards spawn center.",_unitGroup];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,36 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_lastAggro","_result","_leader", "_assignedTarget"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
if (A3EAI_detectOnlyUAVs) then {
|
||||||
|
_lastAggro = _vehicle getVariable "AggroTime";
|
||||||
|
if (isNil "AggroTime") then {
|
||||||
|
_lastAggro = 0;
|
||||||
|
_vehicle setVariable ["AggroTime",0];
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
|
||||||
|
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea}) then {
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reset Group %1 %2 UAV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
_inArea = [_vehicle,NO_AGGRO_RANGE_UAV] call A3EAI_checkInNoAggroArea;
|
||||||
|
|
||||||
|
if !(_inArea) then {
|
||||||
|
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||||
|
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UAV) then { //900: replace with engagement range
|
||||||
|
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,36 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_hitArray", "_hitName", "_hitPoint", "_lastRepaired","_result","_leader", "_assignedTarget"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
if (A3EAI_detectOnlyUGVs) then {
|
||||||
|
_lastAggro = _vehicle getVariable "AggroTime";
|
||||||
|
if (isNil "AggroTime") then {
|
||||||
|
_lastAggro = 0;
|
||||||
|
_vehicle setVariable ["AggroTime",0];
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((combatMode _unitGroup) isEqualTo "YELLOW") then {
|
||||||
|
if ((_lastAggro > diag_tickTime) or {[_vehicle,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea}) then {
|
||||||
|
[_unitGroup,"IgnoreEnemies"] call A3EAI_forceBehavior;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Reset Group %1 %2 UGV to non-hostile mode.",_unitGroup,(typeOf _vehicle)]};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
_inArea = [_vehicle,NO_AGGRO_RANGE_UGV] call A3EAI_checkInNoAggroArea;
|
||||||
|
|
||||||
|
if !(_inArea) then {
|
||||||
|
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||||
|
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_UGV) then { //900: replace with engagement range
|
||||||
|
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,35 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle", "_lastRegroupCheck","_inNoAggroArea","_inArea","_result","_leader", "_assignedTarget"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
_leader = (leader _unitGroup);
|
||||||
|
_inArea = [_leader,NO_AGGRO_RANGE_LAND] call A3EAI_checkInNoAggroArea;
|
||||||
|
|
||||||
|
if !(_inArea) then {
|
||||||
|
_assignedTarget = (assignedTarget (vehicle _leader));
|
||||||
|
if ((_assignedTarget distance _leader) < NO_AGGRO_RANGE_LAND) then { //900: replace with engagement range
|
||||||
|
_inArea = [_assignedTarget,300] call A3EAI_checkInNoAggroArea;
|
||||||
|
};
|
||||||
|
}; //To test!
|
||||||
|
|
||||||
|
_result = [_unitGroup,_inArea] call A3EAI_noAggroAreaToggle;
|
||||||
|
|
||||||
|
_lastRegroupCheck = _vehicle getVariable "LastRegroupCheck";
|
||||||
|
if (isNil "_lastRegroupCheck") then {
|
||||||
|
_lastRegroupCheck = diag_tickTime;
|
||||||
|
_vehicle setVariable ["LastRegroupCheck",0];
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((diag_tickTime - _lastRegroupCheck) > 30) then {
|
||||||
|
if ((alive _vehicle) && {_unitGroup getVariable ["regrouped",true]} && {({if ((_x distance2D _vehicle) > REGROUP_VEHICLEGROUP_DIST) exitWith {1}} count (assignedCargo _vehicle)) > 0}) then {
|
||||||
|
_unitGroup setVariable ["regrouped",false];
|
||||||
|
[_unitGroup,_vehicle] call A3EAI_vehCrewRegroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
_vehicle setVariable ["LastRegroupCheck",diag_tickTime];
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,29 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_lootPool", "_updateServerLoot", "_pullChance", "_lootUnit", "_lootIndex", "_loot", "_unitLevel"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitLevel = _this select 1;
|
||||||
|
|
||||||
|
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||||
|
_updateServerLoot = (A3EAI_enableHC && {!isDedicated});
|
||||||
|
_pullChance = missionNamespace getVariable [format ["A3EAI_lootPullChance%1",_unitLevel],0.40];
|
||||||
|
if !(_lootPool isEqualTo []) then {
|
||||||
|
if (_pullChance call A3EAI_chance) then {
|
||||||
|
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
|
||||||
|
_lootIndex = floor (random (count _lootPool));
|
||||||
|
_loot = _lootPool select _lootIndex;
|
||||||
|
if (alive _lootUnit) then {
|
||||||
|
if ([_lootUnit,_loot] call A3EAI_addItem) then {
|
||||||
|
_lootPool deleteAt _lootIndex;
|
||||||
|
if (_updateServerLoot) then {
|
||||||
|
[_unitGroup,_lootIndex] call A3EAI_updateServerLoot;
|
||||||
|
};
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Pulled %1 from %2 loot pool (%3 items remain).",_loot,_unitGroup,(count _lootPool)];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
_unitGroup setVariable ["lootGenTime",diag_tickTime];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,178 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unit", "_unitLevel", "_unitLevelInvalid", "_loadout", "_weaponSelected", "_unitLevelString", "_uniforms", "_backpacks", "_vests", "_headgears", "_magazine", "_uniformItem", "_backpackItem", "_vestItem", "_headgearItem",
|
||||||
|
"_useGL", "_weaponMuzzles", "_GLWeapon", "_GLMagazines", "_isRifle", "_opticsList", "_opticsType", "_pointersList", "_pointerType", "_muzzlesList", "_muzzleType", "_underbarrelList", "_underbarrelType", "_gadgetsArray", "_gadget"];
|
||||||
|
|
||||||
|
_unit = _this select 0;
|
||||||
|
_unitLevel = _this select 1;
|
||||||
|
|
||||||
|
if !(isNil {_unit getVariable "loadout"}) exitWith {diag_log format ["A3EAI Error: Unit already has loadout! (%1)",__FILE__];};
|
||||||
|
|
||||||
|
if !(_unitLevel in A3EAI_unitLevelsAll) then {
|
||||||
|
_unitLevelInvalid = _unitLevel;
|
||||||
|
_unitLevel = A3EAI_unitLevels call A3EAI_selectRandom;
|
||||||
|
diag_log format ["A3EAI Error: Invalid unitLevel provided: %1. Generating new unitLevel value: %2. (%3)",_unitLevelInvalid,_unitLevel,__FILE__];
|
||||||
|
};
|
||||||
|
|
||||||
|
_unit call A3EAI_purgeUnitGear; //Clear unwanted gear from unit first.
|
||||||
|
|
||||||
|
_loadout = [[],[]];
|
||||||
|
_weaponSelected = _unitLevel call A3EAI_getWeapon;
|
||||||
|
_unitLevelString = str (_unitLevel);
|
||||||
|
|
||||||
|
_uniformChance = missionNamespace getVariable ["A3EAI_addUniformChance"+_unitLevelString,1.00];
|
||||||
|
_uniformItem = DEFAULT_UNIFORM_ITEM;
|
||||||
|
if (_uniformChance call A3EAI_chance) then {
|
||||||
|
_uniforms = missionNamespace getVariable ["A3EAI_uniformTypes"+_unitLevelString,[]];
|
||||||
|
if !(_uniforms isEqualTo []) then {
|
||||||
|
_uniformItem = _uniforms call A3EAI_selectRandom;
|
||||||
|
_unit forceAddUniform _uniformItem;
|
||||||
|
//diag_log format ["DEBUG: %1",_uniformItem];
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_unit forceAddUniform DEFAULT_UNIFORM_ITEM;
|
||||||
|
//diag_log format ["DEBUG: %1",DEFAULT_UNIFORM_ITEM];
|
||||||
|
};
|
||||||
|
|
||||||
|
_backpackChance = missionNamespace getVariable ["A3EAI_addBackpackChance"+_unitLevelString,1.00];
|
||||||
|
if (_backpackChance call A3EAI_chance) then {
|
||||||
|
_backpacks = missionNamespace getVariable ["A3EAI_backpackTypes"+_unitLevelString,[]];
|
||||||
|
if !(_backpacks isEqualTo []) then {
|
||||||
|
_backpackItem = _backpacks call A3EAI_selectRandom;
|
||||||
|
_unit addBackpack _backpackItem;
|
||||||
|
clearAllItemsFromBackpack _unit;
|
||||||
|
//diag_log format ["DEBUG: %1",_backpackItem];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_vestChance = missionNamespace getVariable ["A3EAI_addVestChance"+_unitLevelString,1.00];
|
||||||
|
if (_vestChance call A3EAI_chance) then {
|
||||||
|
_vests = missionNamespace getVariable ["A3EAI_vestTypes"+_unitLevelString,[]];
|
||||||
|
if !(_vests isEqualTo []) then {
|
||||||
|
_vestItem = _vests call A3EAI_selectRandom;
|
||||||
|
_unit addVest _vestItem;
|
||||||
|
//diag_log format ["DEBUG: %1",_vestItem];
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_uniformClass = configName (configFile >> "CfgWeapons" >> _uniformItem >> "ItemInfo" >> "uniformClass");
|
||||||
|
_isWoman = [configFile >> "CfgVehicles" >> _uniformClass,"woman",0] call BIS_fnc_returnConfigEntry;
|
||||||
|
_vestItem = if (_isWoman isEqualTo 0) then {
|
||||||
|
DEFAULT_VEST_ITEM_MALE
|
||||||
|
} else {
|
||||||
|
DEFAULT_VEST_ITEM_FEMALE
|
||||||
|
};
|
||||||
|
_unit addVest _vestItem;
|
||||||
|
//diag_log format ["DEBUG: %1",_vestItem];
|
||||||
|
};
|
||||||
|
|
||||||
|
_headgearChance = missionNamespace getVariable ["A3EAI_addHeadgearChance"+_unitLevelString,1.00];
|
||||||
|
if (_headgearChance call A3EAI_chance) then {
|
||||||
|
_headgears = missionNamespace getVariable ["A3EAI_headgearTypes"+_unitLevelString,[]];
|
||||||
|
if !(_headgears isEqualTo []) then {
|
||||||
|
_headgearItem = _headgears call A3EAI_selectRandom;
|
||||||
|
_unit addHeadgear _headgearItem;
|
||||||
|
//diag_log format ["DEBUG: %1",_headgearItem];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_magazine = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "magazines") select 0;
|
||||||
|
|
||||||
|
_unit addMagazine _magazine;
|
||||||
|
_unit addWeapon _weaponSelected;
|
||||||
|
_unit selectWeapon _weaponSelected;
|
||||||
|
(_loadout select 0) pushBack _weaponSelected;
|
||||||
|
(_loadout select 1) pushBack _magazine;
|
||||||
|
if ((getNumber (configFile >> "CfgMagazines" >> _magazine >> "count")) < 6) then {
|
||||||
|
_unit setVariable ["extraMag",true];
|
||||||
|
_unit addMagazine _magazine;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Grenades
|
||||||
|
_useGL = if !(A3EAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3EAI_levelRequiredGL} else {false};
|
||||||
|
if (_useGL) then {
|
||||||
|
_weaponMuzzles = getArray(configFile >> "cfgWeapons" >> _weaponSelected >> "muzzles");
|
||||||
|
if ((count _weaponMuzzles) > 1) then {
|
||||||
|
_GLWeapon = _weaponMuzzles select 1;
|
||||||
|
_GLMagazines = (getArray (configFile >> "CfgWeapons" >> _weaponSelected >> _GLWeapon >> "magazines"));
|
||||||
|
if (GRENADE_AMMO_3RND in _GLMagazines) then {
|
||||||
|
_unit addMagazine GRENADE_AMMO_3RND;
|
||||||
|
(_loadout select 0) pushBack _GLWeapon;
|
||||||
|
(_loadout select 1) pushBack GRENADE_AMMO_3RND;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_unit,_loadout];};
|
||||||
|
} else {
|
||||||
|
if (GRENADE_AMMO_1RND in _GLMagazines) then {
|
||||||
|
_unit addMagazine GRENADE_AMMO_1RND;
|
||||||
|
(_loadout select 0) pushBack _GLWeapon;
|
||||||
|
(_loadout select 1) pushBack GRENADE_AMMO_1RND;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_unit,_loadout];};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Select weapon optics
|
||||||
|
_isRifle = ((getNumber (configFile >> "CfgWeapons" >> _weaponSelected >> "type")) isEqualTo 1);
|
||||||
|
if ((missionNamespace getVariable [("A3EAI_opticsChance"+_unitLevelString),3]) call A3EAI_chance) then {
|
||||||
|
_opticsList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "CowsSlot" >> "compatibleItems");
|
||||||
|
if !(_opticsList isEqualTo []) then {
|
||||||
|
_opticsType = A3EAI_weaponOpticsList call A3EAI_selectRandom;
|
||||||
|
if (_opticsType in _opticsList) then {
|
||||||
|
if (_isRifle) then {_unit addPrimaryWeaponItem _opticsType} else {_unit addHandGunItem _opticsType};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Select weapon pointer
|
||||||
|
if ((missionNamespace getVariable [("A3EAI_pointerChance"+_unitLevelString),3]) call A3EAI_chance) then {
|
||||||
|
_pointersList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "PointerSlot" >> "compatibleItems");
|
||||||
|
if !(_pointersList isEqualTo []) then {
|
||||||
|
_pointerType = _pointersList call A3EAI_selectRandom;
|
||||||
|
if (_isRifle) then {_unit addPrimaryWeaponItem _pointerType} else {_unit addHandGunItem _pointerType};
|
||||||
|
//diag_log format ["DEBUG :: Added pointer item %1 to unit %2.",_pointerType,_unit];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Select weapon muzzle
|
||||||
|
if ((missionNamespace getVariable [("A3EAI_muzzleChance"+_unitLevelString),3]) call A3EAI_chance) then {
|
||||||
|
_muzzlesList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "MuzzleSlot" >> "compatibleItems");
|
||||||
|
if !(_muzzlesList isEqualTo []) then {
|
||||||
|
_muzzleType = _muzzlesList call A3EAI_selectRandom;
|
||||||
|
if (_isRifle) then {_unit addPrimaryWeaponItem _muzzleType} else {_unit addHandGunItem _muzzleType};
|
||||||
|
//diag_log format ["DEBUG :: Added muzzle item %1 to unit %2.",_muzzleType,_unit];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Select weapon muzzle
|
||||||
|
if ((missionNamespace getVariable [("A3EAI_underbarrelChance"+_unitLevelString),3]) call A3EAI_chance) then {
|
||||||
|
_underbarrelList = getArray (configFile >> "CfgWeapons" >> _weaponSelected >> "WeaponSlotsInfo" >> "UnderBarrelSlot" >> "compatibleItems");
|
||||||
|
if !(_underbarrelList isEqualTo []) then {
|
||||||
|
_underbarrelType = _underbarrelList call A3EAI_selectRandom;
|
||||||
|
if (_isRifle) then {_unit addPrimaryWeaponItem _underbarrelType} else {_unit addHandGunItem _underbarrelType};
|
||||||
|
//diag_log format ["DEBUG :: Added underbarrel item %1 to unit %2.",_underbarrelType,_unit];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_gadgetsArray = missionNamespace getVariable ["A3EAI_gadgetsList"+_unitLevelString,[]];
|
||||||
|
for "_i" from 0 to ((count _gadgetsArray) - 1) do {
|
||||||
|
if (((_gadgetsArray select _i) select 1) call A3EAI_chance) then {
|
||||||
|
_gadget = ((_gadgetsArray select _i) select 0);
|
||||||
|
_unit addWeapon _gadget;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//If unit was not given NVGs, give the unit temporary NVGs which will be removed at death.
|
||||||
|
if (A3EAI_enableTempNVGs && {sunOrMoon < 1}) then {
|
||||||
|
_unit call A3EAI_addTempNVG;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Give unit temporary first aid kits to allow self-healing (unit level 1+)
|
||||||
|
if (A3EAI_enableHealing) then {
|
||||||
|
for "_i" from 1 to (_unitLevel min 3) do {
|
||||||
|
[_unit,FIRST_AID_ITEM_AI] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_unit setVariable ["loadout",_loadout];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created loadout for unit %1 (unitLevel: %2): %3.",_unit,_unitLevel,_loadout];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,66 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unit", "_unitLevel", "_weaponLoot", "_toolLoot", "_pistol", "_magazine", "_kryptoAmountMax", "_kryptoAmount", "_kryptoPos", "_kryptoDevice", "_toolsArray", "_item" , "_loadout", "_primaryWeapon"];
|
||||||
|
|
||||||
|
_unit = _this select 0;
|
||||||
|
_unitLevel = _this select 1;
|
||||||
|
|
||||||
|
if (_unit getVariable ["LootGenerated",false]) exitWith {};
|
||||||
|
_unit setVariable ["LootGenerated",true];
|
||||||
|
|
||||||
|
if !(local _unit) then {
|
||||||
|
waitUntil {uiSleep 1; local _unit};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format["A3EAI Debug: Generating loot for AI unit with unitLevel %2.",_unit,_unitLevel];};
|
||||||
|
|
||||||
|
_weaponLoot = [];
|
||||||
|
_toolLoot = [];
|
||||||
|
|
||||||
|
_loadout = _unit getVariable ["loadout",[[],[]]];
|
||||||
|
_primaryWeapon = [_loadout select 0,0,""] call A3EAI_param;
|
||||||
|
|
||||||
|
//Generate a pistol if one wasn't assigned with loadout script.
|
||||||
|
if ((getNumber (configFile >> "CfgWeapons" >> _primaryWeapon >> "type")) != 2) then {
|
||||||
|
_pistol = A3EAI_pistolList call A3EAI_selectRandom;
|
||||||
|
_magazine = getArray (configFile >> "CfgWeapons" >> _pistol >> "magazines") select 0;
|
||||||
|
_unit addMagazine _magazine;
|
||||||
|
_unit addWeapon _pistol;
|
||||||
|
if (A3EAI_debugLevel > 1) then {
|
||||||
|
_weaponLoot pushBack _pistol;
|
||||||
|
_weaponLoot pushBack _magazine
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Generate Krypto
|
||||||
|
_kryptoAmountMax = missionNamespace getVariable ["A3EAI_kryptoAmount"+str(_unitLevel),0];
|
||||||
|
_kryptoAmount = floor (random (_kryptoAmountMax + 1));
|
||||||
|
if(_kryptoAmount > 0) then {
|
||||||
|
_kryptoPos = getPosATL _unit;
|
||||||
|
_kryptoDevice = createVehicle ["Land_MPS_EPOCH",_kryptoPos,[],1.5,"CAN_COLLIDE"];
|
||||||
|
_kryptoDevice setVariable ["Crypto",_kryptoAmount,true];
|
||||||
|
_kryptoDevice setVariable ["A3EAI_kryptoGenTime",diag_tickTime];
|
||||||
|
A3EAI_kryptoObjects pushBack _kryptoDevice;
|
||||||
|
_kryptoPosEmpty = _kryptoPos findEmptyPosition [0,0.5,"Land_MPS_EPOCH"];
|
||||||
|
if !(_kryptoPosEmpty isEqualTo []) then {
|
||||||
|
_kryptoDevice setPosATL _kryptoPosEmpty;
|
||||||
|
};
|
||||||
|
_kryptoDevice setVelocity [0,0,0.25];
|
||||||
|
if (A3EAI_kryptoPickupAssist > 0) then {
|
||||||
|
_kryptoPickup = [_kryptoDevice,_kryptoPos] call A3EAI_generateKryptoPickup;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add tool items
|
||||||
|
_toolsArray = missionNamespace getVariable ["A3EAI_toolsList"+str(_unitLevel),[]];
|
||||||
|
{
|
||||||
|
_item = _x select 0;
|
||||||
|
if (((_x select 1) call A3EAI_chance) && {[_item,"weapon"] call A3EAI_checkClassname}) then {
|
||||||
|
_unit addWeapon _item;
|
||||||
|
if (A3EAI_debugLevel > 1) then {
|
||||||
|
_toolLoot pushBack _item;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} forEach _toolsArray;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Generated loot for AI death: %1,%2,%3. Krypto: %4.",_weaponLoot,_toolLoot,_kryptoAmount];};
|
@ -0,0 +1,73 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_lootPool", "_groupSize", "_unitType", "_lootUnit", "_unitGroup", "_lootItem"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||||
|
_groupSize = _unitGroup getVariable ["GroupSize",0];
|
||||||
|
_unitType = _unitGroup getVariable ["unitType",""];
|
||||||
|
|
||||||
|
if (_unitType != "dynamic") then {
|
||||||
|
for "_j" from 1 to _groupSize do {
|
||||||
|
//Add first aid kit to loot list
|
||||||
|
if (A3EAI_firstAidKitChance call A3EAI_chance) then {
|
||||||
|
_lootPool pushBack FIRST_AID_ITEM_PLAYER;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add food to loot list
|
||||||
|
for "_i" from 1 to A3EAI_foodLootCount do {
|
||||||
|
_lootPool pushBack (A3EAI_foodLoot call A3EAI_selectRandom);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add items to loot list
|
||||||
|
for "_i" from 1 to A3EAI_miscLootCount1 do {
|
||||||
|
_lootPool pushBack (A3EAI_MiscLoot1 call A3EAI_selectRandom);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add items to loot list
|
||||||
|
for "_i" from 1 to A3EAI_miscLootCount2 do {
|
||||||
|
_lootPool pushBack (A3EAI_MiscLoot2 call A3EAI_selectRandom);
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep 0.5;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
//Generate loot all at once for dynamic AI
|
||||||
|
for "_i" from 1 to _groupSize do {
|
||||||
|
//Add first aid kit to loot list
|
||||||
|
if (A3EAI_firstAidKitChance call A3EAI_chance) then {
|
||||||
|
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
|
||||||
|
[_lootUnit,FIRST_AID_ITEM_PLAYER] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add food to loot list
|
||||||
|
for "_i" from 1 to A3EAI_foodLootCount do {
|
||||||
|
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
|
||||||
|
_lootItem = (A3EAI_foodLoot call A3EAI_selectRandom);
|
||||||
|
[_lootUnit,_lootItem] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add items to loot list
|
||||||
|
for "_i" from 1 to A3EAI_miscLootCount1 do {
|
||||||
|
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
|
||||||
|
_lootItem = (A3EAI_MiscLoot1 call A3EAI_selectRandom);
|
||||||
|
[_lootUnit,_lootItem] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add items to loot list
|
||||||
|
for "_i" from 1 to A3EAI_miscLootCount2 do {
|
||||||
|
_lootUnit = (units _unitGroup) call A3EAI_selectRandom;
|
||||||
|
_lootItem = (A3EAI_MiscLoot2 call A3EAI_selectRandom);
|
||||||
|
[_lootUnit,_lootItem] call A3EAI_addItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
sleep 0.5;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//Update local group loot pool
|
||||||
|
_unitGroup setVariable ["LootPool",_lootPool];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,12 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitType"];
|
||||||
|
|
||||||
|
_unitType = _this;
|
||||||
|
|
||||||
|
call {
|
||||||
|
if (_unitType in ["static","staticcustom","vehiclecrew","aircustom","landcustom"]) exitWith {ANTISTUCK_CHECK_TIME_INFANTRY};
|
||||||
|
if (_unitType in ["air","uav"]) exitWith {ANTISTUCK_CHECK_TIME_AIR};
|
||||||
|
if (_unitType in ["land","ugv"]) exitWith {ANTISTUCK_CHECK_TIME_LAND};
|
||||||
|
300
|
||||||
|
};
|
@ -0,0 +1,116 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitType", "_fnc_execEveryLoop", "_fnc_checkUnits", "_fnc_generateLoot", "_fnc_vehicleAmmoFuelCheck", "_fnc_antistuck", "_noAggroRange"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitType = _this select 1;
|
||||||
|
|
||||||
|
call {
|
||||||
|
if (_unitType isEqualTo "static") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_MAN;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "random") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_MAN;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "dynamic") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_MAN;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "air") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_air;
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_air;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_AIR;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "land") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_vehicle;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_land;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_LAND;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "uav") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_uav;
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = {};
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_uav;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_UAV;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "ugv") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_ugv;
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = {};
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_ugv;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_UGV;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "air_reinforce") exitWith {
|
||||||
|
_fnc_execEveryLoop = {};
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = {};
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = {};
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_AIR;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "vehiclecrew") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_infantry;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_MAN;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "staticcustom") exitWith {
|
||||||
|
_fnc_execEveryLoop = {};
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_MAN;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "aircustom") exitWith {
|
||||||
|
_fnc_execEveryLoop = {};
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_aircustom;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_AIR;
|
||||||
|
};
|
||||||
|
if (_unitType isEqualTo "landcustom") exitWith {
|
||||||
|
_fnc_execEveryLoop = A3EAI_execEveryLoop_vehicle;
|
||||||
|
_fnc_checkUnits = A3EAI_checkGroupUnits;
|
||||||
|
_fnc_generateLoot = A3EAI_generateGroupLoot;
|
||||||
|
_fnc_vehicleAmmoFuelCheck = A3EAI_checkAmmoFuel;
|
||||||
|
_fnc_antistuck = A3EAI_antistuck_generic;
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_LAND;
|
||||||
|
};
|
||||||
|
|
||||||
|
_fnc_execEveryLoop = {};
|
||||||
|
_fnc_checkUnits = {};
|
||||||
|
_fnc_generateLoot = {};
|
||||||
|
_fnc_vehicleAmmoFuelCheck = {};
|
||||||
|
_fnc_antistuck = {};
|
||||||
|
_noAggroRange = NO_AGGRO_RANGE_DEFAULT;
|
||||||
|
|
||||||
|
diag_log format ["A3EAI Warning: Group functions for unit type %1 not found.",_unitType];
|
||||||
|
};
|
||||||
|
|
||||||
|
[_fnc_execEveryLoop,_fnc_checkUnits,_fnc_generateLoot,_fnc_vehicleAmmoFuelCheck,_fnc_antistuck,_noAggroRange]
|
@ -0,0 +1,47 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo","_launchersAdded"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitType = _this select 1;
|
||||||
|
_unitLevel = _this select 2;
|
||||||
|
|
||||||
|
if !(_unitType in ["uav","ugv"]) then {
|
||||||
|
_useLaunchers = if !(A3EAI_levelRequiredLauncher isEqualTo -1) then {((count A3EAI_launcherTypes) > 0) && {(_unitLevel >= A3EAI_levelRequiredLauncher)}} else {false};
|
||||||
|
_maxLaunchers = if (_useLaunchers) then {A3EAI_launchersPerGroup min _unitLevel} else {0};
|
||||||
|
_launchersAdded = 0;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["LootPool",[]];
|
||||||
|
_unitGroup spawn A3EAI_generateLootPool;
|
||||||
|
|
||||||
|
//Set up individual group units
|
||||||
|
{
|
||||||
|
_loadout = _x getVariable "loadout";
|
||||||
|
if (isNil "_loadout") then {
|
||||||
|
_weapon = primaryWeapon _x;
|
||||||
|
_magazine = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines") select 0;
|
||||||
|
_loadout = [[_weapon],[_magazine]];
|
||||||
|
_x setVariable ["loadout",_loadout];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (_launchersAdded < _maxLaunchers) then {
|
||||||
|
_launchWeapon = A3EAI_launcherTypes call A3EAI_selectRandom;
|
||||||
|
_launchAmmo = getArray (configFile >> "CfgWeapons" >> _launchWeapon >> "magazines") select 0;
|
||||||
|
if (_x canAdd _launchAmmo) then {
|
||||||
|
_x addMagazine _launchAmmo;
|
||||||
|
_x addWeapon _launchWeapon;
|
||||||
|
(_loadout select 1) pushBack _launchAmmo;
|
||||||
|
(_loadout select 0) pushBack _launchWeapon;
|
||||||
|
_launchersAdded = _launchersAdded + 1;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Successfully added weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
|
||||||
|
} else {
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Unable to add weapon %1 and ammo %2 to unit %3.",_launchWeapon,_launchAmmo,_x];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_currentTime", "_monitorReport", "_getUptime", "_currentSec", "_outHour", "_outMin", "_outSec", "_uptime"];
|
||||||
|
|
||||||
|
_currentTime = diag_tickTime;
|
||||||
|
_monitorReport = _currentTime;
|
||||||
|
|
||||||
|
_getUptime = {
|
||||||
|
private ["_currentSec","_outSec","_outMin","_outHour"];
|
||||||
|
_currentSec = diag_tickTime;
|
||||||
|
_outHour = floor (_currentSec/3600);
|
||||||
|
_outMin = floor ((_currentSec - (_outHour*3600))/60);
|
||||||
|
_outSec = floor (_currentSec - (_outHour*3600) - (_outMin*60));
|
||||||
|
|
||||||
|
[_outHour,_outMin,_outSec]
|
||||||
|
};
|
||||||
|
|
||||||
|
while {true} do {
|
||||||
|
_currentTime = diag_tickTime;
|
||||||
|
|
||||||
|
if ((A3EAI_monitorReportRate > 0) && {((_currentTime - _monitorReport) > A3EAI_monitorReportRate)}) then {
|
||||||
|
_uptime = [] call _getUptime;
|
||||||
|
diag_log format ["A3EAI Monitor: Uptime: %1:%2:%3. FPS: %4. HC Groups: %5.",_uptime select 0, _uptime select 1, _uptime select 2,round(diag_fps),A3EAI_HCGroupsCount];
|
||||||
|
_monitorReport = _currentTime;
|
||||||
|
};
|
||||||
|
uiSleep 30;
|
||||||
|
};
|
@ -0,0 +1,10 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_targetPlayer"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_targetPlayer = _this select 1;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["targetPlayer",_targetPlayer];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,65 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_anchor", "_unitType", "_groupSize", "_functionCall", "_check", "_lootPool","_miscData1","_miscData2","_anchorType"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitLevel = _this select 1;
|
||||||
|
_anchor = _this select 2;
|
||||||
|
_unitType = _this select 3;
|
||||||
|
_groupSize = _this select 4;
|
||||||
|
_lootPool = _this select 5;
|
||||||
|
_miscData1 = if ((count _this) > 6) then {_this select 6};
|
||||||
|
_miscData2 = if ((count _this) > 7) then {_this select 7};
|
||||||
|
|
||||||
|
call {
|
||||||
|
_anchorType = (typeName _anchor);
|
||||||
|
if (_anchorType isEqualTo "ARRAY") exitWith {
|
||||||
|
_anchor = createTrigger [TRIGGER_OBJECT,_anchor,false];
|
||||||
|
_unitGroup setVariable ["trigger",_anchor];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created group trigger for %1 group %2.",_unitType,_unitGroup];};
|
||||||
|
};
|
||||||
|
if (_anchorType isEqualTo "OBJECT") exitWith {
|
||||||
|
_unitGroup setVariable ["assignedVehicle",_anchor];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 has assigned vehicle %3 (%4).",_unitType,_unitGroup,_anchor,(typeOf _anchor)];};
|
||||||
|
};
|
||||||
|
_anchor = objNull;
|
||||||
|
};
|
||||||
|
|
||||||
|
_unitGroup setVariable ["unitLevel",_unitLevel];
|
||||||
|
_unitGroup setVariable ["unitType",_unitType];
|
||||||
|
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||||
|
|
||||||
|
_unitGroup call A3EAI_initNoAggroStatus;
|
||||||
|
|
||||||
|
if !(_lootPool isEqualTo []) then {_unitGroup setVariable ["LootPool",_lootPool];};
|
||||||
|
|
||||||
|
if !(isNil "_miscData1") then {
|
||||||
|
call {
|
||||||
|
if (_unitType isEqualTo "dynamic") exitWith {
|
||||||
|
_unitGroup setVariable ["targetplayer",_miscData1];
|
||||||
|
_anchor setVariable ["targetplayer",_miscData1];
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: %1 group %2 has target player %3.",_unitType,_unitGroup,_miscData1];};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isNil "_miscData2") then {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
_functionCall = missionNamespace getVariable ["A3EAI_handle"+_unitType,{false}];
|
||||||
|
_check = _unitGroup call _functionCall;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {
|
||||||
|
if (_check) then {
|
||||||
|
diag_log format ["A3EAI Debug: HC received new group from server: %1. Processing new group with function %2.",_unitGroup,("A3EAI_handle"+_unitType)];
|
||||||
|
} else {
|
||||||
|
diag_log format ["A3EAI Debug: Function %1 not found.","A3EAI_handle"+_unitType]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
0 = [_unitGroup,_unitLevel] spawn A3EAI_addGroupManager;
|
||||||
|
|
||||||
|
A3EAI_HCGroupsCount = A3EAI_HCGroupsCount + 1;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,28 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_unitType", "_groupSize", "_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Waiting for reinforcement group %1 ready state.",_unitGroup];};
|
||||||
|
waitUntil {uiSleep 10; diag_log format ["Debug: Group %1 behavior is %2, combat mode %3.",_unitGroup,(behaviour (leader _unitGroup)),(combatMode _unitGroup)]; !((behaviour (leader _unitGroup)) isEqualTo "CARELESS")};
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 has now entered ready state.",_unitGroup];};
|
||||||
|
|
||||||
|
while {((behaviour (leader _unitGroup)) in ["AWARE","COMBAT"]) && {(_unitGroup getVariable ["GroupSize",-1]) > 0}} do {
|
||||||
|
if (local _unitGroup) then {
|
||||||
|
_vehiclePos = getPosATL _vehicle;
|
||||||
|
_vehiclePos set [2,0];
|
||||||
|
_nearUnits = _vehiclePos nearEntities [[PLAYER_UNITS,"LandVehicle"],250];
|
||||||
|
if ((count _nearUnits) > 5) then {_nearUnits resize 5};
|
||||||
|
{
|
||||||
|
if ((isPlayer _x) && {(_unitGroup knowsAbout _x) < 3}) then {
|
||||||
|
_unitGroup reveal [_x,3];
|
||||||
|
if (({if (RADIO_ITEM in (assignedItems _x)) exitWith {1}} count (units (group _x))) > 0) then {
|
||||||
|
[_x,[31+(floor (random 5)),[name (leader _unitGroup)]]] call A3EAI_radioSend;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} forEach _nearUnits;
|
||||||
|
};
|
||||||
|
uiSleep 15;
|
||||||
|
};
|
@ -0,0 +1,13 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_vehicle = _this select 1;
|
||||||
|
|
||||||
|
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetIn","GetOut","Fired","Local","Hit"];
|
||||||
|
_unitGroup setVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Releasing ownership of reinforcement group %1 to server.",_unitGroup];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,12 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_trigger","_triggerPos"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_triggerPos = _this select 1;
|
||||||
|
|
||||||
|
_trigger = createTrigger [TRIGGER_OBJECT,_triggerPos,false];
|
||||||
|
_unitGroup setVariable ["trigger",_trigger];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Created group trigger object for %1 at %2.",_unitGroup,_triggerPos];};
|
||||||
|
|
||||||
|
_trigger
|
@ -0,0 +1,24 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addVehAirEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,26 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addVehAirEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
[_unitGroup,_vehicle] spawn A3EAI_airReinforcementDetection;
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,24 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addVehAirEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_unitGroup call A3EAI_requestGroupVars;
|
||||||
|
|
||||||
|
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,25 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = assignedVehicle (leader _unitGroup);
|
||||||
|
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addLandVehEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,25 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_patrolParams"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = assignedVehicle (leader _unitGroup);
|
||||||
|
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addLandVehEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_unitGroup call A3EAI_requestGroupVars;
|
||||||
|
|
||||||
|
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_unitGroup call A3EAI_requestGroupVars;
|
||||||
|
|
||||||
|
//diag_log format ["Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_trigger,_unitType,_groupSize];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1 @@
|
|||||||
|
#include "A3EAI_handlestatic.sqf"
|
@ -0,0 +1,24 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUVUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",assignedVehicle (leader _unitGroup)];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addUAVEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5, %6",_unitGroup,_unitLevel,_vehicle,(assignedDriver _vehicle),_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,25 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_vehicle"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
//_unitLevel = _unitGroup getVariable ["unitLevel",1];
|
||||||
|
//_trigger = _unitGroup getVariable ["trigger",objNull];
|
||||||
|
//_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
//_groupSize = _unitGroup getVariable ["GroupSize",-1];
|
||||||
|
|
||||||
|
{
|
||||||
|
_x call A3EAI_addUVUnitEH;
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
|
||||||
|
_vehicle = assignedVehicle (leader _unitGroup);
|
||||||
|
_unitGroup setVariable ["assignedVehicle",_vehicle];
|
||||||
|
(assignedDriver _vehicle) setVariable ["isDriver",true];
|
||||||
|
_vehicle call A3EAI_addUGVEH;
|
||||||
|
_vehicle call A3EAI_secureVehicle;
|
||||||
|
_vehicle setVariable ["unitGroup",_unitGroup];
|
||||||
|
|
||||||
|
//if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Group %1 (Level: %2): %3, %4, %5",_unitGroup,_unitLevel,_vehicle,_unitType,_groupSize];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1 @@
|
|||||||
|
#include "A3EAI_handlestatic.sqf"
|
@ -0,0 +1,3 @@
|
|||||||
|
A3EAI_getGroupTriggerVars_PVS = _this;
|
||||||
|
publicVariableServer "A3EAI_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 "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_arrayData", "_unitGroup", "_trigger"];
|
||||||
|
_arrayData = _this;
|
||||||
|
_unitGroup = _arrayData select 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if !(local _unitGroup) then {
|
||||||
|
diag_log format ["Debug: Server sent group trigger variables for remote group %1.",_unitGroup];
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
_trigger = _unitGroup getVariable "trigger";
|
||||||
|
|
||||||
|
if (isNil "_trigger") exitWith {diag_log format ["A3EAI Error: Group %1 has undefined trigger.",_unitGroup];};
|
||||||
|
|
||||||
|
//Remove array headers (Group reference)
|
||||||
|
_arrayData deleteAt 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
_trigger setVariable [_x,_arrayData select _forEachIndex];
|
||||||
|
//diag_log format ["Debug: Group %1 variable %2 has value %3.",_unitGroup,_x,_arrayData select _forEachIndex];
|
||||||
|
} forEach [
|
||||||
|
"GroupArray",
|
||||||
|
"patrolDist",
|
||||||
|
"unitLevel",
|
||||||
|
"unitLevelEffective",
|
||||||
|
"maxUnits",
|
||||||
|
"spawnChance",
|
||||||
|
"spawnType",
|
||||||
|
"respawn",
|
||||||
|
"permadelete"
|
||||||
|
];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Set group trigger variables for group %1. Success check: %2.",_unitGroup,_trigger isKindOf TRIGGER_OBJECT];};
|
@ -0,0 +1,61 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitType", "_unitGroup", "_loadout", "_weapon", "_magazine", "_useLaunchers", "_maxLaunchers", "_unitLevel", "_launchWeapon", "_launchAmmo", "_useGL"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_unitType = _this select 1;
|
||||||
|
_unitLevel = _this select 2;
|
||||||
|
|
||||||
|
if !(_unitType in ["uav","ugv"]) then {
|
||||||
|
_useGL = if !(A3EAI_levelRequiredGL isEqualTo -1) then {_unitLevel >= A3EAI_levelRequiredGL} else {false};
|
||||||
|
{
|
||||||
|
_x setVariable ["loadout",[[],[]]];
|
||||||
|
_loadout = _x getVariable "loadout";
|
||||||
|
_primaryWeapon = primaryWeapon _x;
|
||||||
|
_secondaryWeapon = secondaryWeapon _x;
|
||||||
|
_handgunWeapon = handgunWeapon _x;
|
||||||
|
|
||||||
|
if !(_primaryWeapon isEqualTo "") then {
|
||||||
|
(_loadout select 0) pushBack _primaryWeapon;
|
||||||
|
_primaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _primaryWeapon >> "magazines") select 0;
|
||||||
|
(_loadout select 1) pushBack _primaryWeaponMagazine;
|
||||||
|
} else {
|
||||||
|
if !(_handgunWeapon isEqualTo "") then {
|
||||||
|
(_loadout select 0) pushBack _handgunWeapon;
|
||||||
|
_handgunWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _handgunWeapon >> "magazines") select 0;
|
||||||
|
(_loadout select 1) pushBack _handgunWeaponMagazine;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if !(_secondaryWeapon isEqualTo "") then {
|
||||||
|
(_loadout select 0) pushBack _secondaryWeapon;
|
||||||
|
_secondaryWeaponMagazine = getArray (configFile >> "CfgWeapons" >> _secondaryWeapon >> "magazines") select 0;
|
||||||
|
(_loadout select 1) pushBack _secondaryWeaponMagazine;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((getNumber (configFile >> "CfgMagazines" >> ((_loadout select 1) select 0) >> "count")) < 6) then {_x setVariable ["extraMag",true]};
|
||||||
|
|
||||||
|
if (_useGL) then {
|
||||||
|
_weaponMuzzles = getArray(configFile >> "cfgWeapons" >> ((_loadout select 0) select 0) >> "muzzles");
|
||||||
|
if ((count _weaponMuzzles) > 1) then {
|
||||||
|
_GLWeapon = _weaponMuzzles select 1;
|
||||||
|
_GLMagazines = (getArray (configFile >> "CfgWeapons" >> ((_loadout select 0) select 0) >> _GLWeapon >> "magazines"));
|
||||||
|
if (GRENADE_AMMO_3RND in _GLMagazines) then {
|
||||||
|
(_loadout select 0) pushBack _GLWeapon;
|
||||||
|
(_loadout select 1) pushBack GRENADE_AMMO_3RND;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
|
||||||
|
} else {
|
||||||
|
if (GRENADE_AMMO_1RND in _GLMagazines) then {
|
||||||
|
(_loadout select 0) pushBack _GLWeapon;
|
||||||
|
(_loadout select 1) pushBack GRENADE_AMMO_1RND;
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Modified unit %1 loadout to %2.",_x,_loadout];};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: %1 Unit %2 loadout: %3. unitLevel %4.",_unitType,_x,_x getVariable ["loadout",[]],_unitLevel];};
|
||||||
|
} forEach (units _unitGroup);
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,9 @@
|
|||||||
|
private ["_unitGroup","_lootPool"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_lootPool = _this select 1;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["LootPool",_lootPool];
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Updated group %1 loot pool to %2.",_unitGroup,_lootPool];};
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,10 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_groupSize"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_groupSize = _this select 1;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,3 @@
|
|||||||
|
A3EAI_updateGroupLoot_PVS = _this;
|
||||||
|
publicVariableServer "A3EAI_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 "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_HCObject","_versionHC","_compatibleVersions","_positionHC","_useRemoteConfigs"];
|
||||||
|
_HCObject = _this select 0;
|
||||||
|
_versionHC = _this select 1;
|
||||||
|
_useRemoteConfigs = _this select 2;
|
||||||
|
|
||||||
|
A3EAI_HC_serverResponse = false;
|
||||||
|
if (((owner A3EAI_HCObject) isEqualTo 0) && {(typeOf _HCObject) isEqualTo "HeadlessClient_F"}) then {
|
||||||
|
_compatibleVersions = [configFile >> "CfgPatches" >> "A3EAI","compatibleHCVersions",[]] call BIS_fnc_returnConfigEntry;
|
||||||
|
if (_versionHC in _compatibleVersions) then {
|
||||||
|
A3EAI_HCObject = _HCObject;
|
||||||
|
A3EAI_HCObject allowDamage false;
|
||||||
|
A3EAI_HCObject enableSimulationGlobal false;
|
||||||
|
A3EAI_HCObject addEventHandler ["Local",{
|
||||||
|
if (_this select 1) then {
|
||||||
|
private["_unit","_unitGroup"];
|
||||||
|
A3EAI_HCIsConnected = false;
|
||||||
|
A3EAI_HCObjectOwnerID = 0;
|
||||||
|
A3EAI_HCObject = objNull;
|
||||||
|
_unit = _this select 0;
|
||||||
|
_unitGroup = (group _unit);
|
||||||
|
_unit removeAllEventHandlers "Local";
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Deleting disconnected headless client unit %1.",typeOf _unit];};
|
||||||
|
deleteVehicle _unit;
|
||||||
|
deleteGroup _unitGroup;
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
A3EAI_HCObjectOwnerID = (owner A3EAI_HCObject);
|
||||||
|
A3EAI_HCIsConnected = true;
|
||||||
|
A3EAI_HC_serverResponse = if (_useRemoteConfigs) then {
|
||||||
|
A3EAI_pushedHCVariables
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
};
|
||||||
|
_positionHC = getPosATL A3EAI_HCObject;
|
||||||
|
if (({if (_positionHC in _x) exitWith {1}} count (nearestLocations [_positionHC,[BLACKLIST_OBJECT_GENERAL],BLACKLIST_AREA_HC_SIZE])) isEqualTo 0) then {
|
||||||
|
[_positionHC,TEMP_BLACKLIST_AREA_HC_SIZE] call A3EAI_createBlackListArea;
|
||||||
|
diag_log format ["[A3EAI] Created 750m radius blacklist area at HC position %1",_positionHC];
|
||||||
|
};
|
||||||
|
diag_log format ["[A3EAI] Headless client %1 (owner: %2) logged in successfully.",A3EAI_HCObject,A3EAI_HCObjectOwnerID];
|
||||||
|
} else {
|
||||||
|
diag_log format ["[A3EAI] Headless client %1 (owner: %2) has wrong A3EAI version %3 (Compatible versions: %4).",_HCObject,owner _HCObject,_versionHC,_compatibleVersions];
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
diag_log format ["[A3EAI] Rejecting connection from HC %1. A headless client is already connected: %2. Client object type: %3.",(_this select 1),!((owner A3EAI_HCObject) isEqualTo 0),typeOf _HCObject];
|
||||||
|
};
|
||||||
|
|
||||||
|
(owner _HCObject) publicVariableClient "A3EAI_HC_serverResponse";
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_trigger", "_triggerVars", "_value"];
|
||||||
|
|
||||||
|
_unitGroup = _this;
|
||||||
|
_trigger = _unitGroup getVariable ["trigger",A3EAI_defaultTrigger];
|
||||||
|
_triggerVars = [_unitGroup];
|
||||||
|
|
||||||
|
{
|
||||||
|
_value = _trigger getVariable [_x select 0,_x select 1];
|
||||||
|
_triggerVars pushBack _value;
|
||||||
|
} forEach [
|
||||||
|
["GroupArray",[]],
|
||||||
|
["patrolDist",100],
|
||||||
|
["unitLevel",1],
|
||||||
|
["unitLevelEffective",1],
|
||||||
|
["maxUnits",[0,0]],
|
||||||
|
["spawnChance",0],
|
||||||
|
["spawnType",""],
|
||||||
|
["respawn",true],
|
||||||
|
["permadelete",false]
|
||||||
|
];
|
||||||
|
|
||||||
|
A3EAI_sendGroupTriggerVars_PVC = _triggerVars;
|
||||||
|
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_sendGroupTriggerVars_PVC";
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 1) then {diag_log format ["A3EAI Debug: Retrieved group %1 trigger variables: %2",_unitGroup,_triggerVars];};
|
@ -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 "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_victim", "_killer", "_unitGroup", "_unitLevel","_groupSize","_newGroupSize"];
|
||||||
|
|
||||||
|
_victim = _this select 0;
|
||||||
|
_killer = _this select 1;
|
||||||
|
_unitGroup = _this select 2;
|
||||||
|
|
||||||
|
_victim setVariable ["A3EAI_deathTime",diag_tickTime];
|
||||||
|
_unitLevel = (_unitGroup getVariable ["unitLevel",0]);
|
||||||
|
|
||||||
|
_groupSize = (_unitGroup getVariable ["GroupSize",0]);
|
||||||
|
if (_groupSize > 0) then {
|
||||||
|
_newGroupSize = (_groupSize - 1);
|
||||||
|
_unitGroup setVariable ["GroupSize",_newGroupSize];
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((_unitGroup getVariable ["ReinforceAvailable",false]) && {isPlayer _killer} && {(missionNamespace getVariable [format ["A3EAI_airReinforcementSpawnChance%1",_unitLevel],0]) call A3EAI_chance}) then {
|
||||||
|
_unitGroup setVariable ["ReinforceAvailable",false];
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 (Level %2) is calling reinforcements.",_unitGroup,_unitLevel];};
|
||||||
|
_nul = [(getPosATL _victim),_killer,_unitLevel] spawn A3EAI_spawn_reinforcement;
|
||||||
|
};
|
@ -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,36 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup", "_unitLevel", "_trigger", "_unitType", "_groupSize","_lootPool","_miscData","_miscData2","_groupData""_result","_vehicle"];
|
||||||
|
_unitGroup = _this;
|
||||||
|
|
||||||
|
if ((diag_tickTime - A3EAI_lastGroupTransfer) < 5) exitWith {false};
|
||||||
|
A3EAI_lastGroupTransfer = diag_tickTime;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (A3EAI_debugLevel > 1) then {
|
||||||
|
diag_log format ["%1 variables: %2",_unitGroup,(allVariables _unitGroup)];
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
_unitLevel = _unitGroup getVariable ["unitLevel",0];
|
||||||
|
_trigger = _unitGroup getVariable ["trigger",nil];
|
||||||
|
_unitType = _unitGroup getVariable ["unitType","unknown"];
|
||||||
|
_groupSize = _unitGroup getVariable ["GroupSize",nil];
|
||||||
|
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||||
|
_miscData = _unitGroup getVariable ["MiscData",nil];
|
||||||
|
_miscData2 = _unitGroup getVariable ["MiscData2",nil];
|
||||||
|
_vehicle = _unitGroup getVariable ["assignedVehicle",nil];
|
||||||
|
|
||||||
|
_groupData = [_unitGroup,_unitLevel,nil,_unitType,_groupSize,_lootPool];
|
||||||
|
|
||||||
|
if (!isNil "_trigger") then {_groupData set [2,(getPosATL _trigger)];};
|
||||||
|
if (!isNil "_vehicle") then {_groupData set [2,_vehicle];};
|
||||||
|
if (!isNil "_miscData") then {_groupData set [6,_miscData];};
|
||||||
|
if (!isNil "_miscData2") then {_groupData set [7,_miscData2];};
|
||||||
|
|
||||||
|
A3EAI_transferGroup_PVC = _groupData;
|
||||||
|
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_transferGroup_PVC";
|
||||||
|
|
||||||
|
_result = _unitGroup setGroupOwner A3EAI_HCObjectOwnerID;
|
||||||
|
|
||||||
|
_result
|
@ -0,0 +1,7 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup"];
|
||||||
|
_unitGroup = _this;
|
||||||
|
_unitGroup setGroupOwner 2;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,11 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_targetPlayer"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_targetPlayer = _this select 1;
|
||||||
|
|
||||||
|
A3EAI_sendHunterGroupHC = [_unitGroup,_targetPlayer];
|
||||||
|
A3EAI_HCObjectOwnerID publicVariableClient "A3EAI_sendHunterGroupHC";
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,10 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_lootPool","_lootIndex"];
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_lootIndex = _this select 1;
|
||||||
|
|
||||||
|
_lootPool = _unitGroup getVariable ["LootPool",[]];
|
||||||
|
_lootPool deleteAt _lootIndex;
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,10 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unitGroup","_groupSize"];
|
||||||
|
|
||||||
|
_unitGroup = _this select 0;
|
||||||
|
_groupSize = _this select 1;
|
||||||
|
|
||||||
|
_unitGroup setVariable ["GroupSize",_groupSize];
|
||||||
|
|
||||||
|
true
|
@ -0,0 +1,21 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_vehicle","_unitGroup","_unitLevel"];
|
||||||
|
|
||||||
|
_vehicle = (_this select 0);
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
|
||||||
|
_vehicle setVariable ["vehicle_disabled",true];
|
||||||
|
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetOut","Fired","Local","Hit"];
|
||||||
|
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
|
||||||
|
_vehicle call A3EAI_respawnAIVehicle;
|
||||||
|
if !(isNil {_unitGroup getVariable "dummyUnit"}) exitWith {};
|
||||||
|
|
||||||
|
_unitGroup setVariable ["GroupSize",-1];
|
||||||
|
if !(isDedicated) then {
|
||||||
|
A3EAI_updateGroupSize_PVS = [_unitGroup,-1];
|
||||||
|
publicVariableServer "A3EAI_updateGroupSize_PVS";
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 %2 destroyed at %3",_unitGroup,(typeOf _vehicle),mapGridPosition _vehicle];};
|
@ -0,0 +1,21 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_vehicle","_unitGroup","_unitsAlive"];
|
||||||
|
|
||||||
|
_vehicle = (_this select 0);
|
||||||
|
|
||||||
|
if (isNull _vehicle) exitWith {};
|
||||||
|
if (_vehicle getVariable ["vehicle_disabled",false]) exitWith {};
|
||||||
|
_vehicle setVariable ["vehicle_disabled",true];
|
||||||
|
{_vehicle removeAllEventHandlers _x} count ["Killed","HandleDamage","GetOut","Fired","Local","Hit"];
|
||||||
|
_unitGroup = _vehicle getVariable ["unitGroup",grpNull];
|
||||||
|
_vehicle call A3EAI_respawnAIVehicle;
|
||||||
|
if !(isNil {_unitGroup getVariable "dummyUnit"}) exitWith {};
|
||||||
|
|
||||||
|
_unitGroup setVariable ["GroupSize",-1];
|
||||||
|
if !(isDedicated) then {
|
||||||
|
A3EAI_updateGroupSize_PVS = [_unitGroup,-1];
|
||||||
|
publicVariableServer "A3EAI_updateGroupSize_PVS";
|
||||||
|
};
|
||||||
|
|
||||||
|
if (A3EAI_debugLevel > 0) then {diag_log format ["A3EAI Debug: Group %1 %2 destroyed at %3",_unitGroup,(typeOf _vehicle),mapGridPosition _vehicle];};
|
@ -0,0 +1,13 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private ["_unit","_unitPos","_parachute"];
|
||||||
|
|
||||||
|
_unit = _this;
|
||||||
|
|
||||||
|
_unitPos = getPosATL _unit;
|
||||||
|
_parachute = createVehicle [PARACHUTE_OBJECT, _unitPos, [], (-10 + (random 10)), "FLY"];
|
||||||
|
unassignVehicle _unit;
|
||||||
|
_unit setPosATL _unitPos;
|
||||||
|
_unit moveInDriver _parachute;
|
||||||
|
|
||||||
|
_parachute
|
@ -0,0 +1,77 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private["_object","_hit","_damage","_source","_ammo","_partdamage","_durability","_unitGroup","_currentDamage","_hitPoint"];
|
||||||
|
|
||||||
|
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
|
||||||
|
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
|
||||||
|
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
|
||||||
|
_source = _this select 3; //The source unit that caused the damage.
|
||||||
|
_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
|
||||||
|
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
|
||||||
|
|
||||||
|
_hitPoint = (_object getHitIndex _hitPartIndex);
|
||||||
|
if (_damage > _hitPoint) then {
|
||||||
|
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
|
||||||
|
if ((group _object) call A3EAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
|
||||||
|
|
||||||
|
_durability = _object getVariable "durability";
|
||||||
|
if (isNil "_durability") then {
|
||||||
|
_object setVariable ["durability",[0,0,0,0]];
|
||||||
|
_durability = _object getVariable "durability";
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((side _source) != AI_GROUP_SIDE) then {
|
||||||
|
_destroyed = false;
|
||||||
|
_disabled = false;
|
||||||
|
call {
|
||||||
|
if (_hit isEqualTo "hull_hit") exitWith {
|
||||||
|
//Structural damage
|
||||||
|
_currentDamage = (_durability select 0);
|
||||||
|
_partdamage = _currentDamage + (_damage - _currentDamage);
|
||||||
|
_durability set [0,_partdamage];
|
||||||
|
if ((_partdamage > 0.9) && {alive _object}) then {
|
||||||
|
_damage = _hitPoint;
|
||||||
|
_destroyed = true;
|
||||||
|
_disabled = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (_hit in ["engine_hit","engine_1_hit","engine_2_hit","engine_3_hit","engine_4_hit"]) exitWith {
|
||||||
|
_currentDamage = (_durability select 1);
|
||||||
|
_partdamage =_currentDamage + (_damage - _currentDamage);
|
||||||
|
_durability set [1,_partdamage];
|
||||||
|
if ((_partdamage > 0.9) && {alive _object}) then {
|
||||||
|
_damage = _hitPoint;
|
||||||
|
_destroyed = true;
|
||||||
|
_disabled = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (_hit in ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"]) exitWith {
|
||||||
|
_currentDamage = (_durability select 2);
|
||||||
|
_partdamage = _currentDamage + (_damage - _currentDamage);
|
||||||
|
_durability set [2,_partdamage];
|
||||||
|
if ((_partdamage > 0.9)&& {alive _object}) then {
|
||||||
|
{
|
||||||
|
_object setHit [_x,1];
|
||||||
|
} forEach ["tail_rotor_hit","main_rotor_hit","main_rotor_1_hit","main_rotor_2_hit"];
|
||||||
|
_destroyed = false;
|
||||||
|
_disabled = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (_hit isEqualTo "fuel_hit") exitWith {_damage = _hitPoint;};
|
||||||
|
};
|
||||||
|
if (_disabled) then {
|
||||||
|
0 = [_object] call A3EAI_heliEvacuated;
|
||||||
|
//{_object removeAllEventHandlers _x} forEach ["HandleDamage","GetOut","Killed","Hit"];
|
||||||
|
if (_destroyed) then {
|
||||||
|
_nul = _object spawn {
|
||||||
|
uiSleep 3;
|
||||||
|
_this setVehicleAmmo 0;
|
||||||
|
_this setFuel 0;
|
||||||
|
_this setDamage 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_damage
|
@ -0,0 +1,22 @@
|
|||||||
|
#include "\A3EAI\globaldefines.hpp"
|
||||||
|
|
||||||
|
private["_object","_hit","_damage","_source","_ammo","_hitPoint"];
|
||||||
|
|
||||||
|
_object = _this select 0; //Object the event handler is assigned to. (the unit taking damage)
|
||||||
|
_hit = _this select 1; //Name of the selection where the unit was damaged. "" for over-all structural damage, "?" for unknown selections.
|
||||||
|
_damage = _this select 2; //Resulting level of damage for the selection. (Received damage)
|
||||||
|
_source = _this select 3; //The source unit that caused the damage.
|
||||||
|
//_ammo = _this select 4; //Classname of the projectile that caused inflicted the damage. ("" for unknown, such as falling damage.)
|
||||||
|
_hitPartIndex = _this select 5; //Hit part index of the hit point, -1 otherwise.
|
||||||
|
|
||||||
|
_hitPoint = (_object getHitIndex _hitPartIndex);
|
||||||
|
if (_damage > _hitPoint) then {
|
||||||
|
call {
|
||||||
|
if (isNull _source) exitWith {_damage = _hitPoint;}; //No physics damage
|
||||||
|
if ((group _object) call A3EAI_getNoAggroStatus) exitWith {_damage = _hitPoint;};
|
||||||
|
if !(isPlayer _source) exitWith {_damage = _hitPoint;};
|
||||||
|
if ((_hit find "wheel") > -1) exitWith {_damage = _hitPoint;};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_damage
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user