Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions addons/danger/functions/fnc_tacticsAssess.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ _plan = selectRandom _plan;
switch (_plan) do {
case TACTICS_FLANK: {
// flank
[{_this call FUNC(tacticsFlank)}, [_group, _pos, _units], 22 + random 8] call CBA_fnc_waitAndExecute;
[{_this call FUNC(tacticsFlank)}, [_group, _pos], 22 + random 8] call CBA_fnc_waitAndExecute;
};
case TACTICS_GARRISON: {
// garrison ~ nb units not carried here - nkenny
Expand All @@ -262,11 +262,11 @@ switch (_plan) do {
};
case TACTICS_SUPPRESS: {
// suppress
[{_this call FUNC(tacticsSuppress)}, [_group, _pos, _units], 4 + random 4] call CBA_fnc_waitAndExecute;
[{_this call FUNC(tacticsSuppress)}, [_group, _pos], 2 + random 2] call CBA_fnc_waitAndExecute;
};
case TACTICS_ATTACK: {
// group attacks as one
[{_this call FUNC(tacticsAttack)}, [_group, _pos, _units], 1 + random 1] call CBA_fnc_waitAndExecute;
[{_this call FUNC(tacticsAttack)}, [_group, _pos], 1 + random 1] call CBA_fnc_waitAndExecute;
};
default {
// hide from armor
Expand Down
35 changes: 22 additions & 13 deletions addons/danger/functions/fnc_tacticsFlank.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
* 0: group executing tactics <GROUP> or group leader <UNIT>
* 1: group target <OBJECT> or position <ARRAY>
* 2: units in group, default all <ARRAY>
* 3: how many assault cycles <NUMBER>
* 4: default overwatch destination <ARRAY>
* 3: default overwatch destination <ARRAY>
* 4: delay until unit is ready again <NUMBER>
*
* Return Value:
Expand All @@ -19,7 +18,7 @@
*
* Public: No
*/
params ["_group", "_target", ["_units", []], ["_cycle", 5], ["_overwatch", []], ["_delay", 120]];
params ["_group", "_target", ["_units", []], ["_overwatch", []], ["_delay", 120]];

// group is missing
if (isNull _group) exitWith {false};
Expand All @@ -42,37 +41,47 @@ if (_unit distance2D _target < GVAR(cqbRange)) exitWith {
};

// reset tactics
_group setVariable [QGVAR(isExecutingTactic), true];
[
{
params [["_group", grpNull], ["_speedMode", "NORMAL"], ["_formation", "WEDGE"]];
params [["_group", grpNull], ["_delay", 0]];
time > _delay || {isNull _group} || { !(_group getVariable [QGVAR(isExecutingTactic), false]) }
},
{
params [["_group", grpNull], "", ["_speedMode", "NORMAL"], ["_formation", "WEDGE"]];
if (!isNull _group) then {
_group setVariable [QGVAR(isExecutingTactic), nil];
_group setVariable [QEGVAR(main,currentTactic), nil];
_group setSpeedMode _speedMode;
_group setFormation _formation;
{
_x setVariable [QEGVAR(main,currentTask), nil, EGVAR(main,debug_functions)];
_x setVariable [QGVAR(forceMove), nil];
_x setUnitPos "AUTO";
[_x] allowGetIn true;
_x doFollow (leader _x);
} forEach (units _group);
};
},
[_group, speedMode _unit, formation _unit],
_delay
] call CBA_fnc_waitAndExecute;
[_group, time + _delay, speedMode _unit, formation _unit]
] call CBA_fnc_waitUntilAndExecute;

// find units
if (_units isEqualTo []) then {
_units = _unit call EFUNC(main,findReadyUnits);
};

// add loaded units
_units append ((units _unit) select {((assignedVehicleRole _x) select 0) isEqualTo "cargo"});
if (_units isEqualTo []) exitWith {false};

// find vehicles
private _vehicles = [_unit] call EFUNC(main,findReadyVehicles);

// sort building locations
private _pos = [_target, 12, true, false] call EFUNC(main,findBuildings);
_pos pushBack _target;
private _posList = [_target, 12, true, false] call EFUNC(main,findBuildings);
_posList append ((nearestTerrainObjects [ _target, ["HIDE", "TREE", "BUSH", "SMALL TREE"], 8, false, true]) apply { (getPosATL _x) vectorAdd [0, 0, random 2] });
_posList pushBack _target;

// find overwatch position
if (_overwatch isEqualTo []) then {
Expand All @@ -94,7 +103,7 @@ _group setVariable [QEGVAR(main,currentTactic), "Flanking", EGVAR(main,debug_fun

// gesture
[_unit, ["gestureGo"]] call EFUNC(main,doGesture);
[_units select (count _units - 1), "gestureGoB"] call EFUNC(main,doGesture);
[_units select -1, "gestureGoB"] call EFUNC(main,doGesture);

// leader callout
[_unit, "combat", "flank", 125] call EFUNC(main,doCallout);
Expand All @@ -103,7 +112,7 @@ _group setVariable [QEGVAR(main,currentTactic), "Flanking", EGVAR(main,debug_fun
_unit setSpeedMode "FULL";

// prevent units from being mounted!
((units _unit) select {((assignedVehicleRole _x) select 0) isEqualTo "cargo"}) allowGetIn false;
_units allowGetIn false;

// ready group
_group setFormDir (_unit getDir _target);
Expand All @@ -117,11 +126,11 @@ _group setFormation "FILE";
if (!GVAR(disableAutonomousSmokeGrenades)) then {[_unit, _overwatch] call EFUNC(main,doSmoke);};

// function
[{_this call EFUNC(main,doGroupFlank)}, [_cycle, _units, _vehicles, _pos, _overwatch], 2 + random 8] call CBA_fnc_waitAndExecute;
[{_this call EFUNC(main,doGroupFlank)}, [_group, _units, _vehicles, _posList, _overwatch], 2 + random 8] call CBA_fnc_waitAndExecute;

// debug
if (EGVAR(main,debug_functions)) then {
["%1 TACTICS FLANK (%2 with %3 units and %6 vehicles @ %4m with %5 positions)", side _unit, name _unit, count _units, round (_unit distance2D _overwatch), count _pos, count _vehicles] call EFUNC(main,debugLog);
["%1 TACTICS FLANK (%2 with %3 units and %6 vehicles @ %4m with %5 positions)", side _unit, name _unit, count _units, round (_unit distance2D _overwatch), count _posList, count _vehicles] call EFUNC(main,debugLog);
private _m = [_unit, "tactics flank", _unit call EFUNC(main,debugMarkerColor), "hd_arrow"] call EFUNC(main,dotMarker);
private _mt = [_overwatch, "", _unit call EFUNC(main,debugMarkerColor), "hd_objective"] call EFUNC(main,dotMarker);
{_x setMarkerSizeLocal [0.6, 0.6];} forEach [_m, _mt];
Expand Down
39 changes: 23 additions & 16 deletions addons/danger/functions/fnc_tacticsSuppress.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* Public: No
*/
params ["_group", "_target", ["_units", []], ["_delay", 17]];
params ["_group", "_target", ["_units", []], ["_delay", 45]];

// group is missing
if (isNull _group) exitWith {false};
Expand All @@ -38,22 +38,28 @@ if !([_unit, (ATLToASL _target) vectorAdd [0, 0, 5]] call EFUNC(main,shouldSuppr
[_group, _target] call FUNC(tacticsFlank);
};

// sort cycles
private _cycle = selectRandom [2, 3, 3, 4];

// reset tactics
_group setVariable [QGVAR(isExecutingTactic), true];
[
{
params ["_group", "_enableAttack"];
params [["_group", grpNull], ["_delay", 0]];
time > _delay || {isNull _group} || { !(_group getVariable [QGVAR(isExecutingTactic), false]) }
},
{
params ["_group", "", ["_enableAttack", false], ["_formation", "WEDGE"]];
if (!isNull _group) then {
_group setVariable [QGVAR(isExecutingTactic), nil];
_group enableAttack _enableAttack;
_group setVariable [QEGVAR(main,currentTactic), nil];
_group enableAttack _enableAttack;
_group setFormation _formation;
{
_x setVariable [QEGVAR(main,currentTask), nil, EGVAR(main,debug_functions)];
_x doFollow (leader _x);
} forEach (units _group);
};
},
[group _unit, attackEnabled _unit],
_delay * _cycle
] call CBA_fnc_waitAndExecute;
[group _unit, time + _delay, attackEnabled _unit, formation _group]
] call CBA_fnc_waitUntilAndExecute;

// alive unit
if !(_unit call EFUNC(main,isAlive)) exitWith {false};
Expand All @@ -64,13 +70,13 @@ if (_units isEqualTo []) then {
};
if (_units isEqualTo []) exitWith {false};

// find vehicles
private _vehicles = [_unit] call EFUNC(main,findReadyVehicles);
// find vehicles with weapons
private _vehicles = ([_unit] call EFUNC(main,findReadyVehicles)) select {someAmmo _x};

// sort building locations
private _pos = [_target, 20, true, false] call EFUNC(main,findBuildings);
_pos append ((nearestTerrainObjects [ _target, ["HIDE", "TREE", "BUSH", "SMALL TREE"], 8, false, true]) apply { (getPosATL _x) vectorAdd [0, 0, random 2] });
_pos pushBack _target;
private _postList = [_target, 20, true, false] call EFUNC(main,findBuildings);
_postList append ((nearestTerrainObjects [ _target, ["HIDE", "TREE", "BUSH", "SMALL TREE"], 8, false, true]) apply { (getPosATL _x) vectorAdd [0, 0, random 2] });
_postList pushBack _target;

// set tasks
_unit setVariable [QEGVAR(main,currentTarget), _target, EGVAR(main,debug_functions)];
Expand All @@ -79,6 +85,7 @@ _unit setVariable [QEGVAR(main,currentTask), "Leader Suppress", EGVAR(main,debug
// set group task
_group = group _unit;
_group enableAttack false;
_group setFormation "LINE";
_group setVariable [QEGVAR(main,currentTactic), "Suppressing", EGVAR(main,debug_functions)];

// gesture
Expand All @@ -91,11 +98,11 @@ _group setVariable [QEGVAR(main,currentTactic), "Suppressing", EGVAR(main,debug_
_group setFormDir (_unit getDir _target);

// execute recursive cycle
[_cycle, _units, _vehicles, _pos] call EFUNC(main,doGroupSuppress);
[{_this call EFUNC(main,doGroupSuppress)}, [_group, _units, _vehicles, _postList], 1 + random 1] call CBA_fnc_waitAndExecute;

// debug
if (EGVAR(main,debug_functions)) then {
["%1 TACTICS SUPPRESS (%2 with %3 units and %6 vehicles @ %4m with %5 positions for %7 cycles)", side _unit, name _unit, count _units, round (_unit distance2D _target), count _pos, count _vehicles, _cycle] call EFUNC(main,debugLog);
["%1 TACTICS SUPPRESS (%2 with %3 units and %6 vehicles @ %4m with %5 positions)", side _unit, name _unit, count _units, round (_unit distance2D _target), count _postList, count _vehicles] call EFUNC(main,debugLog);
private _m = [_unit, "tactics suppress", _unit call EFUNC(main,debugMarkerColor), "hd_arrow"] call EFUNC(main,dotMarker);
private _mt = [_target, "", _unit call EFUNC(main,debugMarkerColor), "hd_destroy"] call EFUNC(main,dotMarker);
{_x setMarkerSizeLocal [0.6, 0.6];} forEach [_m, _mt];
Expand Down
1 change: 1 addition & 0 deletions addons/main/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ PREP(doShareInformation);
PREP(getLauncherUnits);
PREP(getShareInformationParams);
PREP(shouldSuppressPosition);
PREP(checkVisibilityList);

PREP(eventCallback);
PREP(findBuildings);
Expand Down
92 changes: 67 additions & 25 deletions addons/main/functions/GroupAction/fnc_doGroupFlank.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Actualises flanking cycle
*
* Arguments:
* 0: cycles <NUMBER>
* 0: group conducting the flanking <GROUP>
* 1: units list <ARRAY>
* 2: list of group vehicles <ARRAY>
* 3: list of building/enemy positions <ARRAY>
Expand All @@ -18,54 +18,96 @@
*
* Public: No
*/
params ["_cycle", "_units", "_vehicles", "_pos", "_overwatch", ["_teamAlpha", 0]];
params [["_group", grpNull], ["_units", []], ["_vehicles", []], ["_posList", []], ["_overwatch", [0, 0, 0]], ["_teamAlpha", 0]];

// exit!
if !(_group getVariable [QEGVAR(danger,isExecutingTactic), false]) exitWith {false};

// update
_units = _units select { _x call FUNC(isAlive) && { !isPlayer _x } && {_x distance2D _overwatch > 5}};
_units = _units select { !( _x getVariable [QEGVAR(danger,disableAI), false] ) && { _x call FUNC(isAlive) } && { !isPlayer _x } };
_vehicles = _vehicles select { canFire _x };

// group has reached destination
private _leader = leader _group;
if ( _leader distance2D _overwatch < 4 ) exitWith {
_group setVariable [QEGVAR(danger,isExecutingTactic), false];
_group setVariable [QGVAR(groupMemory), _posList, false];
};

// leader has no friendlies within 45 meters
private _leaderAlone = ( ( _units - crew _leader) findIf { _x distanceSqr _leader < 2025 } ) isEqualTo -1;

{
private _unit = _x;
private _suppressed = (getSuppression _x) > 0.5;
_x setUnitPos (["MIDDLE", "DOWN"] select _suppressed);
_unit setUnitPos (["MIDDLE", "DOWN"] select (_suppressed || {_unit isEqualTo _leader && _leaderAlone}));
_unit setVariable [QEGVAR(danger,forceMove), !_suppressed];

// move
_x doMove (_overwatch vectorAdd [-2 + random 4, -2 + random 4, 0]);
_x setDestination [_overwatch, "LEADER PLANNED", true];
_x setVariable [QEGVAR(danger,forceMove), !_suppressed];
_unit doMove _overwatch;
_unit setDestination [_overwatch, "LEADER PLANNED", false];
_unit setVariable [QGVAR(currentTask), "Group Flank", GVAR(debug_functions)];

// suppress
private _posASL = AGLToASL (selectRandom _pos);
private _posASL = AGLToASL (selectRandom _posList);
private _eyePos = eyePos _unit;
_posASL = _eyePos vectorAdd ((_posASL vectorDiff _eyePos) vectorMultiply 0.6);

if (
(_forEachIndex % 2) isEqualTo _teamAlpha
&& {!(terrainIntersectASL [eyePos _x, _posASL vectorAdd [0, 0, 3]])}
&& {!(_leaderAlone && {isNull (objectParent (effectiveCommander _leader))})}
&& {(currentCommand _unit) isNotEqualTo "Suppress"}
&& {_unit isNotEqualTo (leader _unit)}
&& {[_unit, "VIEW", objNull] checkVisibility [_eyePos, _posASL] isEqualTo 1}
) then {
[{_this call FUNC(doSuppress)}, [_x, _posASL vectorAdd [0, 0, random 1], true], 1 + random 3] call CBA_fnc_waitAndExecute;

// shoot
[{_this call FUNC(doSuppress)}, [_unit, _posASL vectorAdd [0, 0, random 1], false], random 2] call CBA_fnc_waitAndExecute;

};

} forEach _units;

// reset alpha status
_teamAlpha = parseNumber (_teamAlpha isEqualTo 0);

// vehicles
if ((_cycle % 2) isEqualTo 0) then {
{
private _posAGL = selectRandom _pos;
_x doWatch _posAGL;
[_x, _posAGL] call FUNC(doVehicleSuppress);
} forEach _vehicles;
} else {
// check for roads
private _roads = _overwatch nearRoads 50;
if (_roads isNotEqualTo []) exitWith {_vehicles doMove (ASLToAGL (getPosASL (selectRandom _roads)));};
_vehicles doMove _overwatch;
};
_vehicles doWatch (selectRandom _posList);
[_posList, true] call CBA_fnc_shuffle;
{

// loaded vehicles move quickly
if (count (crew _x) > 3 || {_leaderAlone} || { _x isNotEqualTo _leader && { _leader distance2D _overwatch < 35 } } ) exitWith {_vehicles doMove _overwatch;};

// sort out vehicles
private _index = [_x, _posList] call FUNC(checkVisibilityList);

if (
_index isEqualTo -1
) then {

// move up behind leader
private _leaderPos = _leader getPos [35 min (_leader distance2D _x), _overwatch getDir _leader];
if ((vehicle _leader) isEqualTo _x) then {_leaderPos = _x getPos [35, _x getDir _overwatch]};

// check for roads
private _roads = _leaderPos nearRoads 50;
if (_roads isNotEqualTo []) exitWith {_x doMove (ASLToAGL (getPosASL (selectRandom _roads)));};
_x doMove _leaderPos;

} else {

// do suppressive fire
[_x, _posList select _index] call FUNC(doVehicleSuppress);
};
} forEach _vehicles;

// recursive cyclic
if !(_cycle <= 1 || {_units isEqualTo []}) then {
if (_units isNotEqualTo [] && { _group getVariable [QEGVAR(danger,isExecutingTactic), false] }) then {
[
{_this call FUNC(doGroupFlank)},
[_cycle - 1, _units, _vehicles, _pos, _overwatch, _teamAlpha],
10 + random 8
[_group, _units, _vehicles, _posList, _overwatch, _teamAlpha],
11 + random 8
] call CBA_fnc_waitAndExecute;
};

Expand Down
Loading
Loading