Skip to content

Commit

Permalink
AA turrets
Browse files Browse the repository at this point in the history
  • Loading branch information
Apricot-ale committed Mar 2, 2023
1 parent 6e174fa commit 7f572ed
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
1 change: 1 addition & 0 deletions Missionframework/CfgFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class KPLIB {
class getOpforCap {};
class getOpforFactor {};
class getOpforSpawnPoint {};
class getOpforSpawnPointAA {};
class getPlayerCount {};
class getResistanceTier {};
class getSaveableParam {};
Expand Down
96 changes: 96 additions & 0 deletions Missionframework/functions/fn_getOpforSpawnPointAA.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
File: fn_getOpforSpawnPointAA.sqf
Author: KP Liberation Dev Team
Date: 2020-09-29
Last Update: 2023-03-02
License: MIT License - http://www.opensource.org/licenses/MIT
Description:
Gets a random opfor spawn point marker name respecting following conditions:
* Wasn't used already in the current session (server restart to server restart)
* Distance to blufor FOBs and sectors is more than given min distance
* Distance to blufor FOBs and sectors is less than given max distance
* Distance to an opfor sector is less than 2000m (to avoid strange spawn in blufor territory)
* If nearest is set to true, the valid spawn point which is nearest to any blufor sector/FOB is returned
* If a position is given, the closest valid spawn point to that position is returned
Parameter(s):
_min - Minimum distance to any blufor sector or FOB [NUMBER, defaults to 1500]
_max - Maximum distance to any blufor sector or FOB [NUMBER, defaults to 100000]
_nearest - Provide the nearest spawn point of valid points [BOOL, defaults to false]
_pos - Position if the nearest spawn point to this should be selected [POSITION, defaults to [0, 0, 0]]
Returns:
Opfor spawn point for AA turret[STRING]
*/

params [
["_min", 1500, [0]],
["_max", 100000, [0]],
["_nearest", false, [false]],
["_pos", [0, 0, 0], [[]], [2, 3]]
];

private _possibleSpawns = [];

// Only check for opfor spawn points which aren't used already in the current session
private _sectorsToCheck = KPLIB_sectors_spawn;
if (!isNil "KPLIB_usedPositionsAA") then {
_sectorsToCheck = KPLIB_sectors_spawn - KPLIB_usedPositionsAA;
};

private ["_valid", "_current", "_distances"];
{
_valid = true;
_current = _x;

// Fetch distances to FOBs
_distances = (KPLIB_sectors_fob apply {(markerPos _current) distance2d _x}) select {_x < _max};

// Fetch distances to blufor sectors
_distances append ((KPLIB_sectors_player apply {(markerPos _current) distance2d (markerPos _x)}) select {_x < _max});

// Invalid, if all sectors and FOBs are further away than given max distance
if (_distances isEqualTo []) then {
_valid = false;
} else {
// Invalid, if one sector or FOB is closer than min distance
_distances sort true;
if ((_distances select 0) < _min) then {
_valid = false;
};
};

// Make sure that there is an opfor sector in sensible range to spawn
if (_valid) then {
if ((KPLIB_sectors_all - KPLIB_sectors_player) findIf {((markerPos _current) distance2D (markerPos _x)) < 2000} < 0) then {
_valid = false;
};
};

// Make sure that there is no blufor unit inside min dist to spawn
if (_valid) then {
if (([markerpos _current, _min, KPLIB_side_player] call KPLIB_fnc_getUnitsCount) > 0) then {
_valid = false;
};
};

// Add distance and marker name to possible spawn, if still valid
if (_valid) then {
_possibleSpawns pushBack [_distances select 0, _current];
};
} forEach _sectorsToCheck;

// Return empty string, if no possible spawn point was found
if (_possibleSpawns isEqualTo []) exitWith {["No opfor AA spawn point found", "WARNING"] call KPLIB_fnc_log; ""};

// Return nearest spawn point to a blufor sector/FOB, if selected via parameter
if (_nearest) exitWith {
_possibleSpawns sort true;
(_possibleSpawns select 0) select 1
};

// Return nearest spawn point to given position, if provided
if !(_pos isEqualTo [0, 0, 0]) exitWith {
([_possibleSpawns apply {_x select 1}, [_pos] , {_input0 distance (markerPos _x)} , "ASCEND"] call BIS_fnc_sortBy) select 0
};

// Return random spawn point
(selectRandom _possibleSpawns) select 1;
7 changes: 7 additions & 0 deletions Missionframework/presets/enemies/apex.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,10 @@ KPLIB_o_planes = [
"O_Plane_CAS_02_dynamicLoadout_F", // To-199 Neophron (CAS)
"O_Plane_Fighter_02_F" // To-201 Shikra
];

// Enemy AA turrets that will be spawned in the back country
KPLIB_o_turretsAA = [
["B_SAM_System_01_F"],
["B_SAM_System_02_F"],
["O_SAM_System_04_F", "O_Radar_System_02_F"]
];
7 changes: 7 additions & 0 deletions Missionframework/presets/enemies/custom.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,10 @@ KPLIB_o_planes = [
"O_Plane_CAS_02_dynamicLoadout_F", // To-199 Neophron (CAS)
"O_Plane_Fighter_02_F" // To-201 Shikra
];

// Enemy AA turrets that will be spawned in the back country
KPLIB_o_turretsAA = [
["B_SAM_System_01_F"],
["B_SAM_System_02_F"],
["O_SAM_System_04_F", "O_Radar_System_02_F"]
];
103 changes: 103 additions & 0 deletions Missionframework/scripts/server/ai/AA_turret_manager.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
File: AA_turret_manager.sqf
Author: Nicoman
Date: 2020-09-29
Last Update: 2023-03-02
License: MIT License - http://www.opensource.org/licenses/MIT
Description:
Spawns and manages AA turrets in the back country. Max number and spawn rate of AA turrets is influenced by various factors:
* KPLIB_param_difficulty (game difficulty, ranges from 0.5 to 10)
* KPLIB_enemyReadiness (enemy combat readiness, ranges from 0 to 200)
* KPLIB_param_aggressivity (enemy aggressivity, ranges from 0.25 to 4)
* Player count, if "adapt to player count" mission param is enabled.
Parameter(s):
NONE
Returns:
Nothing
*/

waitUntil {!isNil "KPLIB_saveLoaded"};
waitUntil {!isNil "KPLIB_sectors_player"}; // we wait with our mighty AA units until those pesky players dare to conquer one of OUR nice sectors
waitUntil {KPLIB_saveLoaded};

if (isNil "KPLIB_o_turretsAA") exitWith {}; // leave, if there are no AA turrets defined in currently played preset
if (KPLIB_param_difficulty < 0.75) exitWith {}; // no AA turrets on easiest difficulty level (as of v0.96.8, KPLIB_param_difficulty values range from 0.5 to 10)
if (isNil "KPLIB_usedPositionsAA") then {KPLIB_usedPositionsAA = []}; // define array containing all currently used positions
if (isNil "KPLIB_backCountryTurretsAA") then {KPLIB_backCountryTurretsAA = []}; // define array containing all turrets corresponding to a used position

private ["_crew", "_group", "_i", "_killedTurretsAA", "_maxAAnumber", "_randomTurret", "_sleepTime", "_spawnMarker", "_turret", "_turretGroup"];
_killedTurretsAA = 0; // counter of killed AA turrets

while {KPLIB_endgame == 0} do {
_sleepTime = (1800 + (random 1800)) / (([] call KPLIB_fnc_getOpforFactor) * KPLIB_param_aggressivity); // sleep time is 30 to 60 minutes
if (KPLIB_enemyReadiness >= 80) then {_sleepTime = _sleepTime * 0.75}; // when enemy readiness gets above 80, reduce sleep time to 0.75
if (KPLIB_enemyReadiness >= 90) then {_sleepTime = _sleepTime * 0.75}; // when enemy readiness gets above 90, reduce sleep time to 0.5625 (0.75 * 0.75)
if (KPLIB_enemyReadiness >= 100) then {_sleepTime = _sleepTime * 0.75}; // when enemy readiness gets above 1000, reduce sleep time to 0.42 (0.75 * 0.75 * 0.75)
sleep _sleepTime;

// Check and clear turret array for any destroyed or unmanned units
{
_turret = _x select 0; // in case turret is an array, choose first element of array as turret
if (!alive _turret || !alive gunner _turret || side _turret != KPLIB_side_enemy) then {
{
if (side _x == KPLIB_side_player) exitWith {};
if (alive _x) then {_x setDamage 1};
} forEach _x;
KPLIB_backCountryTurretsAA deleteAt _forEachIndex; // delete any destroyed or unmanned AA turret from turret array
KPLIB_usedPositionsAA deleteAt _forEachIndex; // delete corresponding position from used positions array
_killedTurretsAA = _killedTurretsAA + 1; // raise kill counter
};
} forEach KPLIB_backCountryTurretsAA;

// If AA turrets were destroyed, add a 'punishment' time for the enemy. This extra time is meant to be a dampening of the production of AA turrets
if (_killedTurretsAA > 0) then {
sleep (_sleepTime * _killedTurretsAA); // killing AA turrets 'damps' placement of further turrets
_killedTurretsAA = 0; // reset kill counter after performing 'damp' sleep
};

// Calculate maximum amount of AA turrets
_maxAAnumber = round (KPLIB_param_difficulty * 2);
if (_maxAAnumber > 12) then {_maxAAnumber = 12};
if (KPLIB_enemyReadiness > 0 && _maxAAnumber > 0) then {
_maxAAnumber = _maxAAnumber + round (KPLIB_enemyReadiness / 30);
if (_maxAAnumber > 20) then {_maxAAnumber = 20};
if (_maxAAnumber > (count KPLIB_sectors_all - count KPLIB_sectors_player)) then {_maxAAnumber = count KPLIB_sectors_all - count KPLIB_sectors_player}; // maximum amount of AA turrets should not exceed number of opfor sectors
};

// If maximum amount of AA turrets has not been reached yet, add one to the map
if (count KPLIB_backCountryTurretsAA < _maxAAnumber) then {
_spawnMarker = [] call KPLIB_fnc_getOpforSpawnPointAA; // get a sector for spawning an AA turret
if (_spawnMarker isEqualTo "") exitWith {}; // do not spawn, if no spawn marker was found
_randomTurret = selectRandom KPLIB_o_turretsAA; // choose an OpFor turret to be spawned
KPLIB_usedPositionsAA pushBack _spawnMarker; // update AA used positions array with current sector

// The lower the difficulty level is, the less it is likely to have 'heavy' AA defenses
if (KPLIB_param_difficulty < 4 && count _randomTurret > 1) then {
_i = 4 - (floor KPLIB_param_difficulty);
while {count _randomTurret > 1 && _i > 0} do {
_randomTurret = selectRandom KPLIB_o_turretsAA;
_i = _i - 1;
};
};

// spawn and memory turret / turrets
_turretGroup = []; // create save array for currently spawned turret group
{
_turret = [markerpos _spawnMarker, _x] call KPLIB_fnc_spawnVehicle;
_turretGroup pushBack _turret; // append spawned turret to save array
} forEach _randomTurret; // spawn turret / turrets
KPLIB_backCountryTurretsAA pushBack _turretGroup; // update AA turrets array with current turret

// if turret group has more than one unit, that means there is a radar vehicle involved; so link all units in turret group to that radar
if (count _turretGroup > 1) then {
_group = createGroup [KPLIB_side_enemy, true];
{
_crew = units (_x);
_crew joinSilent _group;
_x setVehicleRadar 1; // fucking turn on radar
} forEach _turretGroup;
};
};
};
2 changes: 2 additions & 0 deletions Missionframework/scripts/server/init_server.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ execVM "scripts\server\offloading\show_fps.sqf";
execVM "scripts\server\patrols\civilian_patrols.sqf";
execVM "scripts\server\patrols\manage_patrols.sqf";
execVM "scripts\server\patrols\reinforcements_resetter.sqf";
// AA turret manager
execVM "scripts\server\ai\AA_turret_manager.sqf";
if (KPLIB_param_logistic) then {execVM "scripts\server\resources\manage_logistics.sqf";};
execVM "scripts\server\resources\manage_resources.sqf";
execVM "scripts\server\resources\recalculate_resources.sqf";
Expand Down

0 comments on commit 7f572ed

Please sign in to comment.