Jump to content
chernaruski

DMS - Defent's Mission System

Recommended Posts

Hi all! I am trying to setup a position array for a static DMS mission. Here is the current code for the mission; I am not sure what to comment out and how to arrange the _pos code for the dozens of coords I have.

 

Spoiler

/*
    Sample mission
    Created by Defent and eraser1

    Called from DMS_selectMission
*/

private ["_num", "_group", "_pos", "_side", "_OK", "_difficulty", "_AICount", "_type", "_launcher", "_crate1", "_wreck", "_crate_loot_values1", "_missionAIUnits", "_missionObjs", "_msgStart", "_msgWIN", "_msgLOSE", "_missionName", "_markers", "_time", "_added", "_cleanup"];

// For logging purposes
_num = DMS_MissionCount;


// Set mission side
_side = "bandit";

// This part is unnecessary, but exists just as an example to format the parameters for "DMS_fnc_MissionParams" if you want to explicitly define the calling parameters for DMS_fnc_FindSafePos.
// It also allows anybody to modify the default calling parameters easily.
if ((isNil "_this") || {_this isEqualTo [] || {!(_this isEqualType [])}}) then
{
    _this =
    [
        [10,DMS_WaterNearBlacklist,DMS_MinSurfaceNormal,DMS_SpawnZoneNearBlacklist,DMS_TraderZoneNearBlacklist,DMS_MissionNearBlacklist,DMS_PlayerNearBlacklist,DMS_TerritoryNearBlacklist,DMS_ThrottleBlacklists],
        [
            []
        ],
        _this
    ];
};

// Check calling parameters for manually defined mission position.
// This mission doesn't use "_extraParams" in any way currently.
_OK = (_this call DMS_fnc_MissionParams) params
[
    ["_pos",[],[[]],[3]],
    ["_extraParams",[]]
];

if !(_OK) exitWith
{
    diag_log format ["DMS ERROR :: Called MISSION beertransport.sqf with invalid parameters: %1",_this];
};


// Set general mission difficulty
_difficulty = "easy";


// Create AI
_AICount = 3 + (round (random 2));

_group =
[
    _pos,                    // Position of AI
    _AICount,                // Number of AI
    "random",                // "random","hardcore","difficult","moderate", or "easy"
    "random",                 // "random","assault","MG","sniper" or "unarmed" OR [_type,_launcher]
    _side                     // "bandit","hero", etc.
] call DMS_fnc_SpawnAIGroup;

/*
// Create Crates
_crate1 = ["Box_NATO_Wps_F",_pos] call DMS_fnc_SpawnCrate;

_wreck = createVehicle ["Land_Wreck_Van_F",[(_pos select 0) - 10, (_pos select 1),-0.2],[], 0, "CAN_COLLIDE"];

// Set crate loot values
_crate_loot_values1 =
[
    8,        // Weapons
    [10,["Exile_Item_Beer"]],        // Items
    1         // Backpacks
];
*/


// Define mission-spawned AI Units
_missionAIUnits =
[
    _group         // We only spawned the single group for this mission
];

// Define mission-spawned objects and loot values
_missionObjs =
[
    [_wreck],
    [],
    [[_crate1,_crate_loot_values1]]
];

// Define Mission Start message
//_msgStart = ['#FFFF00',"A transport truck carrying beer and guns is being robbed, stop the robbers and steal the loot!"];

// Define Mission Win message
//_msgWIN = ['#0080ff',"Convicts have successfully claimed all of the beer and guns. 'Murica."];

// Define Mission Lose message
//_msgLOSE = ['#FF0000',"The robbers have taken off with all the beer and all the guns! What a travesty!"];

// Define mission name (for map marker and logging)
//_missionName = "Beer N' Guns Truck";

// Create Markers
_markers =
[
    _pos,
    _missionName,
    _difficulty
] call DMS_fnc_CreateMarker;

// Record time here (for logging purposes, otherwise you could just put "diag_tickTime" into the "DMS_AddMissionToMonitor" parameters directly)
_time = diag_tickTime;

// Parse and add mission info to missions monitor
_added =
[
    _pos,
    [
        [
            "kill",
            _group
        ],
        [
            "playerNear",
            [_pos,DMS_playerNearRadius]
        ]
    ],
    [
        _time,
        (DMS_MissionTimeOut select 0) + random((DMS_MissionTimeOut select 1) - (DMS_MissionTimeOut select 0))
    ],
    _missionAIUnits,
    _missionObjs,
    [_missionName,_msgWIN,_msgLOSE],
    _markers,
    _side,
    _difficulty,
    []
] call DMS_fnc_AddMissionToMonitor;

// Check to see if it was added correctly, otherwise delete the stuff
if !(_added) exitWith
{
    diag_log format ["DMS ERROR :: Attempt to set up mission %1 with invalid parameters for DMS_AddMissionToMonitor! Deleting mission objects and resetting DMS_MissionCount.",_missionName];

    // Delete AI units and the crate. I could do it in one line but I just made a little function that should work for every mission (provided you defined everything correctly)
    _cleanup = [];
    {
        _cleanup pushBack _x;
    } forEach _missionAIUnits;

    _cleanup pushBack ((_missionObjs select 0)+(_missionObjs select 1));

    {
        _cleanup pushBack (_x select 0);
    } foreach (_missionObjs select 2);

    _cleanup call DMS_fnc_CleanUp;


    // Delete the markers directly
    {deleteMarker _x;} forEach _markers;


    // Reset the mission count
    DMS_MissionCount = DMS_MissionCount - 1;
};


// Notify players
//[_missionName,_msgStart] call DMS_fnc_BroadcastMissionStatus;

if (DMS_DEBUG) then
{
    (format ["MISSION: (%1) :: Mission #%2 started at %3 with %4 AI units and %5 difficulty at time %6",_missionName,_num,_pos,_AICount,_difficulty,_time]) call DMS_fnc_DebugLog;
};
 

 

As always, any help is appreciated. 

Share this post


Link to post
Share on other sites

Your code shown above is not a static mission. This is a dynamic mission (bandit).

Share this post


Link to post
Share on other sites
57 minutes ago, DEH4NK said:

Your code shown above is not a static mission. This is a dynamic mission (bandit).

 

I hadn't realized that, but you are correct. I feel like I remember there being a way to make it static, though. I thought it was something like:

 

_pos = [ [12345,54321,0] , [2345,5432,0] , [76543,3245,0] ];

 

 

Share this post


Link to post
Share on other sites

True for Statik DMS Mission need the position 

_pos = [

//Ai

[12345,54321,0] ,

[2345,5432,0] ,

[76543,3245,0]

 ];

_pos = [

//hmg

[12345,54321,0] ,

[2345,5432,0] ,

[76543,3245,0],

//high posi hmg on exemple Container tower

//not the position from export you need the high from building not from map self 

[12345,54321,17] ,

[2345,5432,17] ,

[76543,3245,17]

 ];

Then need center position, position for the Box and maybe for the vehicle part from loot

Share this post


Link to post
Share on other sites

Sharing my A3DMS Missions for Arma 3 Exile. These Missions are set up to use reinforcements on both static and bandit missions. Working vehicle, helicopter, and foot soldiers when a defined number of AI in a group are killed the reinforcements will come in. The helicopter will fly around as gun ship it will not drop troops If you enable it may or may not work right has a mind of its own when doing pardrops. Take a look at the bandit mission blackHawkDown.sqf, static missions Saltflats.sqf, StoptheMayor.sqf, and Chelonisipower.sqf to see the randomization these have to offer. I run these on my server and players like the randomization because it never plays out the same and they dont get use to the same exact stuff at the missions. If you use dms you cannot use just the missions out of here it will not work you need the scripts folder and the missions folder due to the changes I had to make to 2 scripts and all bandit missions to get this all to work. Also In the blackHawkDown.sqf is specific cordinates put in each pos case and it runs of choosing a mission location off of chordinates you put in there instead of the normal bandit mission random locations. I did this because the buildings for this mission do not work well on hills. the cordinates that are there are for Altis map so if you use another map you need to get cordinates put in where you want possible spawns to be. https://github.com/Crito-VanaheimServers/Reworked-A3DMS-Missions

  • Like 2

Share this post


Link to post
Share on other sites

Updated on Github I replaced the sqf with the original version because I forgot the one provided is one I use on my server and has a bunch of RHS loot that will probably thorw errors if you are not using RHS.

Share this post


Link to post
Share on other sites

Wondering if anyone would have a static mission  for the  panthera map?  Would like one for on the Jurassic park island. 

Share this post


Link to post
Share on other sites

I'm looking for some good DMS missions, If y'all have any that you would like to share, please do.

Share this post


Link to post
Share on other sites

Hi there,

 

I am running DMS Static Missions on an Arma 3 Exile Chernarus server and my RPT is spamming the following error related to an undefined variable:

 

if !(_onM>
 8:05:26   Error Undefined variable in expression: _groupreinforcementsinfo
 8:05:26 File x\addons\dms\scripts\fn_MissionsMonitor_Static.sqf..., line 301
 8:05:28 "ExileServer - Job with handle 10059 added."
 8:05:39 "ExileZ Mod: Monitored Zombies    |    0    "
 8:05:41 Error in expression <fo deleteAt _forEachIndex;
};
} forEach _groupReinforcementsInfo;
};

 

Below are lines 294 to 302 in addons\dms\scripts\fn_MissionsMonitor_Static.sqf

 

if (DMS_AllowStaticReinforcements) then
        {
            {
                if (_x call DMS_fnc_GroupReinforcementsManager) then
                {
                    _groupReinforcementsInfo deleteAt _forEachIndex;
                };
            } forEach _groupReinforcementsInfo;
        };

 

Does anyone know what I can tweak to stop this error from spamming in my RPT?

 

Thanks!

 

Vladick

Share this post


Link to post
Share on other sites
3 hours ago, BSBS Vladick said:
Spoiler

 

Hi there,

 

I am running DMS Static Missions on an Arma 3 Exile Chernarus server and my RPT is spamming the following error related to an undefined variable:

 

if !(_onM>
 8:05:26   Error Undefined variable in expression: _groupreinforcementsinfo
 8:05:26 File x\addons\dms\scripts\fn_MissionsMonitor_Static.sqf..., line 301
 8:05:28 "ExileServer - Job with handle 10059 added."
 8:05:39 "ExileZ Mod: Monitored Zombies    |    0    "
 8:05:41 Error in expression <fo deleteAt _forEachIndex;
};
} forEach _groupReinforcementsInfo;
};

 

Below are lines 294 to 302 in addons\dms\scripts\fn_MissionsMonitor_Static.sqf

 

if (DMS_AllowStaticReinforcements) then
        {
            {
                if (_x call DMS_fnc_GroupReinforcementsManager) then
                {
                    _groupReinforcementsInfo deleteAt _forEachIndex;
                };
            } forEach _groupReinforcementsInfo;
        };

 

Does anyone know what I can tweak to stop this error from spamming in my RPT?

 

Thanks!

 

Vladick

 

 

can you post (use pastebin link) the full fn_MissionsMonitor_Static.sqf file you are using?

Share this post


Link to post
Share on other sites
23 hours ago, chernaruski said:

can you post (use pastebin link) the full fn_MissionsMonitor_Static.sqf file you are using?

Here you go. I put it in a spoiler. Hope that's what you wanted. Thanks for taking a look!

 

Spoiler

/*
    DMS_fnc_MissionsMonitor_Static

    Created by eraser1
    Mostly identical to "DMS_fnc_MissionsMonitor_Dynamic"


    Each mission has its own index in "DMS_StaticMission_Arr".
    Every index is a subarray with the values:
    [
        _missionPos,
        _completionInfo,                    //<--- More info in "DMS_fnc_MissionSuccessState"
        _groupReinforcementsInfo,            //<--- More info in "DMS_fnc_GroupReinforcementsManager"
        [_timeStarted,_failTime],
        [_AIGroup1,_AIGroup2,...,_AIGroupX],
        [
            [_cleanupObj1,_cleanupObj2,...,_cleanupObjX],
            [_vehicle1,_vehicle2,...,_vehicleX],
            [
                [_crate1,_crate_loot_values1],
                [_crate2,_crate_loot_values2],
                ...
                [_crateX,_crate_loot_valuesX]
            ],
            [_mine1,_mine2,...,_mineX]
        ],
        [_missionName,_msgWIN,_msgLose],
        _markers,
        _missionSide,
        _missionDifficulty,
        _missionEvents,
        [
            _onSuccessScripts,
            _onFailScripts,
            _onMonitorStart,
            _onMonitorEnd
        ],
        _prevAICount
    ]

    A semi-full breakdown can be found in fn_AddStaticMissionToMonitor.sqf
*/

{
    if !(_x params
    [
        "_missionPos",
        "_completionInfo",
        "_groupReinforcementsInfo",
        "_timing",
        "_inputAIUnits",
        "_missionObjs",
        "_msgInfo",
        "_markers",
        "_missionSide",
        "_missionDifficulty",
        "_missionEvents",
        "_missionScripts",
        "_prevAICount"
    ])
    then
    {
        DMS_StaticMission_Arr deleteAt _forEachIndex;
        diag_log format ["DMS ERROR :: Invalid Index (%1) in DMS_StaticMission_Arr: %2",_forEachIndex,_x];
    };


    if !(_timing params
    [
        "_timeStarted",
        "_failTime"
    ])
    exitWith
    {
        DMS_StaticMission_Arr deleteAt _forEachIndex;
        diag_log format ["DMS ERROR :: Invalid _timing (%1) in DMS_StaticMission_Arr: %2",_timing,_x];
    };


    if !(_missionObjs params
    [
        "_buildings",
        "_vehs",
        "_crate_info_array",
        "_mines"
    ])
    exitWith
    {
        DMS_StaticMission_Arr deleteAt _forEachIndex;
        diag_log format ["DMS ERROR :: Invalid _missionObjs (%1) in DMS_StaticMission_Arr: %2",_missionObjs,_x];
    };


    if !(_msgInfo params
    [
        "_missionName",
        "_msgWIN",
        "_msgLose"
    ])
    exitWith
    {
        DMS_StaticMission_Arr deleteAt _forEachIndex;
        diag_log format ["DMS ERROR :: Invalid _msgInfo (%1) in DMS_StaticMission_Arr: %2",_msgInfo,_x];
    };


    if !(_missionScripts params
    [
        "_onSuccessScripts",
        "_onFailScripts",
        "_onMonitorStart",
        "_onMonitorEnd"
    ])
    exitWith
    {
        DMS_StaticMission_Arr deleteAt _forEachIndex;
        diag_log format ["DMS ERROR :: Invalid _missionScripts (%1) in DMS_StaticMission_Arr: %2",_missionScripts,_x];
    };

    try
    {
        /*
        if (DMS_DEBUG) then
        {
            (format ["MissionsMonitor_Static :: Checking Mission Status (index %1): ""%2"" at %3",_forEachIndex,_missionName,_missionPos]) call DMS_fnc_DebugLog;
        };
        */

        if !(_onMonitorStart isEqualTo {}) then
        {
            if (DMS_DEBUG) then
            {
                (format ["MissionsMonitor_Static :: Calling _onMonitorStart (index %1): ""%2"". Code: %3",_forEachIndex,_missionName,_onMonitorStart]) call DMS_fnc_DebugLog;
            };
            _x call _onMonitorStart;
        };


        if (_completionInfo call DMS_fnc_MissionSuccessState) then
        {
            DMS_CleanUpList pushBack [_buildings,diag_tickTime,DMS_CompletedMissionCleanupTime];

            {
                _x allowDamage true;
                _x enableRopeAttach true;
                _x enableSimulationGlobal true;

                if (_x getVariable ["ExileIsPersistent", false]) then
                {
                    _x lock 0;
                    _x setVariable ["ExileIsLocked",0];

                    _x setVariable ["ExileLastLockToggleAt", time];
                    _x setVariable ["ExileAccessDenied", false];
                    _x setVariable ["ExileAccessDeniedExpiresAt", 0];

                    // NOW we save the vehicle in the database, since we know we're not deleting this vehicle.
                    _x call ExileServer_object_vehicle_database_insert;
                    _x call ExileServer_object_vehicle_database_update;
                }
                else
                {
                    _x lock 1;
                };

                _x call ExileServer_system_simulationMonitor_addVehicle;
            } forEach _vehs;

            {
                _x call DMS_fnc_FillCrate;
            } forEach _crate_info_array;

            if (DMS_despawnMines_onCompletion) then
            {
                {
                    deleteVehicle _x;
                } forEach _mines;
            };

            {
                _params = _x select 0;
                _code = _x select 1;
                if (_code isEqualType "") then
                {
                    _code = compile _code;
                };
                _params call _code;
            } forEach _onSuccessScripts;

            [_missionName,_msgWIN] call DMS_fnc_BroadcastMissionStatus;
            [_markers,"win"] call DMS_fnc_RemoveMarkers;

            DMS_StaticMission_Arr deleteAt _forEachIndex;
            DMS_RunningStaticMissions deleteAt _forEachIndex;

            throw format ["Mission (%1) Success at %2 with message %3.",_missionName,_missionPos,_msgWIN];
        };


        private _timeElapsed = diag_tickTime - _timeStarted;

        if (DMS_ResetStaticMissionTimeoutOnKill) then
        {
            private _AICount = count (_inputAIUnits call DMS_fnc_GetAllUnits);

            if (_AICount != _prevAICount) then
            {
                _x set [3,[diag_tickTime,_failTime]];
                _x set [12, _AICount];
                _timeElapsed = 0;

                if (DMS_DEBUG) then
                {
                    format["MissionsMonitor_Static :: Static Mission Timeout Extended to %1 more seconds; AI count changed from %2 to %3. Position: %4, MissionIndex: %5",_failTime, _prevAICount, _AICount,_pos,_forEachIndex] call DMS_fnc_DebugLog;
                };
            };
        };

        switch (true) do
        {
            case (_timeElapsed > DMS_SMissionTimeoutResetFrequency):
            {
                if ([_missionPos,DMS_StaticMissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby) then
                {
                    _x set [3,[diag_tickTime,_failTime]];

                    if (DMS_DEBUG) then
                    {
                        format["MissionsMonitor_Static :: Static Mission Timeout Extended to %1 more seconds; player found within %2 meters. Position: %3, MissionIndex: %4",_failTime,DMS_StaticMissionTimeoutResetRange,_pos,_forEachIndex] call DMS_fnc_DebugLog;
                    };
                };
            };

            case (_timeElapsed > _failTime):
            {
                // Check to see if the timeout should be extended before ending the mission.
                if ((DMS_StaticMissionTimeoutResetRange>0) && {[_missionPos,DMS_StaticMissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby}) then
                {
                    _x set [3,[diag_tickTime,_failTime]];

                    throw format ["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_missionPos];
                };

                //Nobody is nearby so just cleanup objects from here
                _cleanupList = ((_inputAIUnits call DMS_fnc_GetAllUnits)+_buildings+_vehs+_mines);

                {
                    _cleanupList pushBack (_x select 0);
                } forEach _crate_info_array;

                private _prev = DMS_CleanUp_PlayerNearLimit;
                DMS_CleanUp_PlayerNearLimit = 0;            // Temporarily set the limit to 0 since we want to delete all the stuff regardless of player presence.

                _cleanupList call DMS_fnc_CleanUp;

                DMS_CleanUp_PlayerNearLimit = _prev;


                {
                    _params = _x select 0;
                    _code = _x select 1;
                    if (_code isEqualType "") then
                    {
                        _code = compile _code;
                    };
                    _params call _code;
                } forEach _onFailScripts;

                [_missionName,_msgLose] call DMS_fnc_BroadcastMissionStatus;
                [_markers,"lose"] call DMS_fnc_RemoveMarkers;

                DMS_StaticMission_Arr deleteAt _forEachIndex;
                DMS_RunningStaticMissions deleteAt _forEachIndex;

                throw format ["Mission (%1) Fail at %2 with message %3.",_missionName,_missionPos,_msgLose];
            };
        };


        if (DMS_MarkerText_ShowAICount_Static) then
        {
            private _dot = _markers select 0;
            private _text = missionNamespace getVariable [format ["%1_text",_dot],_missionName];

            if (DMS_MarkerText_ShowMissionPrefix) then
            {
                _text = format ["%1 %2",DMS_MarkerText_MissionPrefix,_text];
            };

            _dot setMarkerText (format ["%1 (%2 %3 remaining)",_text,count (_inputAIUnits call DMS_fnc_GetAllUnits),DMS_MarkerText_AIName]);
        };


        if (DMS_AllowStaticReinforcements) then
        {
            {
                if (_x call DMS_fnc_GroupReinforcementsManager) then
                {
                    _groupReinforcementsInfo deleteAt _forEachIndex;
                };
            } forEach _groupReinforcementsInfo;
        };


        if !(_onMonitorEnd isEqualTo {}) then
        {
            if (DMS_DEBUG) then
            {
                (format ["MissionsMonitor_Static :: Calling _onMonitorEnd (index %1): ""%2"". Code: %3",_forEachIndex,_missionName,_onMonitorEnd]) call DMS_fnc_DebugLog;
            };
            _x call _onMonitorEnd;
        };
    }
    catch
    {
        if !(_onMonitorEnd isEqualTo {}) then
        {
            if (DMS_DEBUG) then
            {
                (format ["MissionsMonitor_Static :: Calling _onMonitorEnd (index %1): ""%2"". Code: %3",_forEachIndex,_missionName,_onMonitorEnd]) call DMS_fnc_DebugLog;
            };
            _x call _onMonitorEnd;
        };


        if (DMS_DEBUG) then
        {
            (format ["MissionsMonitor_Static :: %1",_exception]) call DMS_fnc_DebugLog;
        };
    };
} forEach DMS_StaticMission_Arr;
 

 

Share this post


Link to post
Share on other sites

we need to go deeper.
can you do the same for fn_GroupReinforcementsManager ?

Share this post


Link to post
Share on other sites
On 2/27/2022 at 11:29 AM, chernaruski said:

we need to go deeper.
can you do the same for fn_GroupReinforcementsManager ?

Oh man, I just saw that you replied. Sorry for the late reply. Here is the  fn_GroupReinforcementsManager.

Thanks for your help!

 

Spoiler

/*
    DMS_fnc_GroupReinforcementsManager
    Created by eraser1

    Usage:
    [
        _AIGroup,                        // GROUP: The AI group to monitor.
        [
            [
                _maxReinforcementWaves,            // SCALAR: The maximum number of reinforcement waves that this group can receive. Set to -1 for unlimited reinforcement waves.
                _reinforcementWavesGiven        // SCALAR: The number of reinforcement waves given to this group.
            ],
            [
                _maxReinforcementUnits,            // SCALAR: The maximum number of reinforcement units that this group can receive. Set to -1 for unlimited reinforcement units.
                _reinforcementUnitsGiven        // SCALAR: The number of reinforcement units given to this group.
            ]
        ],
        [
            _updateDelay,                    // SCALAR: Delay in seconds until the AI group is reinforced.
            _lastUpdated                    // SCALAR: The time (diag_tickTime) when the group was last reinforced.
        ],
        _spawnLocations,                // ARRAY: Array of positions (ATL) where reinforcement AI can spawn. Passing an empty array will cause the group leader's position to be used. For "armed_vehicle" _monitorType, a random position between 100 and 300 meters from the leader is used.
        _class,                            // STRING: The "class" of AI to spawn as reinforcements. Supported values: "random","assault","MG","sniper" or "unarmed"
        _difficulty,                    // STRING: The difficulty of the AI to be spawned. Supported values: "random","static","hardcore","difficult","moderate", or "easy"
        _side,                            // STRING: The "side" that the AI are on. Currently only "bandit" is supported.
        _monitorType,                    // STRING: How the AI group should be managed. Supported types: "playernear", "maintain", "reinforce", "increasing_resistance", "armed_vehicle"
        _monitorParams,                    // ARRAY: Parameters specific to the _monitorType. See below.
        _customGearSet                    // (OPTIONAL) ARRAY: The custom gear set of the AI. Refer to documentation of fn_SpawnAISoldier.sqf for more info: https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf
    ] call DMS_fnc_GroupReinforcementsManager;

    About "_monitorType" types:

        "playernear":
            _monitorParams =
            [
                _posOrObj,                // ARRAY (position): The position at which the players have to be near.
                _radius,                // SCALAR: The distance (in meters) that a player has to be near in order for reinforcements to spawn
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Set to 0 for no limit. Default value is 0.
            ]

        "maintain":
            _monitorParams =
            [
                _AICount                 // SCALAR: If the AI Group has fewer than "_AICount" living units, then new members will be added to the group until it has "_AICount" living units again.
            ]

        "reinforce":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Set to 0 for no limit. Default value is equivalent to _AICount.
            ]

        "increasing_resistance":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _increment_AICount,        // SCALAR: After reinforcements, "_AICount" is increased by this amount, so subsequent reinforcements will be spawned for even greater amounts of AI (increasing the number of total AI, until "_maxAICount" is reached).
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Default value is equivalent to _AICount. Set to 0 for no limit.
            ]

        "increasing_difficulty":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Default value is equivalent to _AICount. Set to 0 for no limit.
            ]

        "static_gunner":
            _monitorParams =
            [
                _staticGun,                // OBJECT: If this object (static gun) loses its gunner and/or is deleted, then a new static gun and/or gunner will spawn to replace the previous one.
                _gunPos,                // ARRAY (positionATL): The position of the static gun.
                _staticGunClass            // (OPTIONAL) STRING: The classname of the static gun to spawn as reinforcement.
            ]

        "armed_vehicle":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _vehClass                // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
            ]

        "armed_vehicle_replace":
            _monitorParams =
            [
                _vehicle,                // OBJECT: When this vehicle is null or dead, then this group will receive reinforcements. The spawned vehicle will then be the new _vehicle.
                _vehClass                // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
            ]
        NOTE: Every reinforcement vehicle counts as one unit given for monitor type "armed_vehicle" and "armed_vehicle_replace"

        "heli_troopers":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _ejectFFVGunners,               // BOOLEAN: Whether or not to eject Fire-From-Vehicle (FFV) gunners.
                _maxJumpers,                    // SCALAR: Maximum number of AI to eject from the aircraft. Set to a really high # to ignore (like 999).
                _remainAsGunship,               // BOOLEAN: Whether or not to keep the heli flying around as a gunship.
                _dropPoint,                     // OBJECT or ARRAY (OPTIONAL - Position2D or 3D): The location to drop the reinforcements at. The drop point will default to the group leader.
                _heliClass,                     // STRING (OPTIONAL): The classname of the heli to spawn.
                _spawnPos                       // ARRAY (OPTIONAL - Position2D or 3D): The position for the heli to spawn at.
            ]
            This reinforcement type will attempt to drop the AI off at the group leader's position. The heli will spawn in the air 500-5000 meters away from the leader's position and 1000 meters away from a player (default).

    Returns whether or not reinforcement waves or units given exceeds/matches maximum wave or unit reinforcements. If true, then no more reinforcements will be spawned (so the passed info should be deleted from the available reinforcements list).
*/

// Check ALL the variables
if !(params
[
    "_AIGroup",
    "_reinforcementInfo",
    "_updateInfo",
    "_spawnLocations",
    "_class",
    "_difficulty",
    "_side",
    "_monitorType",
    "_monitorParams"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid parameters: %1",_this];
    true
};


if !(_reinforcementInfo params
[
    "_wavesInfo",
    "_unitsInfo"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _reinforcementInfo: %1",_reinforcementInfo];
    true
};


if !(_wavesInfo params
[
    "_maxReinforcementWaves",
    "_reinforcementWavesGiven"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _wavesInfo: %1",_wavesInfo];
    true
};


if !(_unitsInfo params
[
    "_maxReinforcementUnits",
    "_reinforcementUnitsGiven"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _unitsInfo: %1",_unitsInfo];
    true
};


if !(_updateInfo params
[
    "_updateDelay",
    "_lastUpdated"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _updateInfo: %1",_updateInfo];
    true
};

private _customGearSet =
    if ((count _this) > 9) then
    {
        _this select 9
    }
    else
    {
        []
    };

_fnc_isDepleted =
{
    switch (true) do
    {
        // Both "_maxReinforcementWaves" and "_maxReinforcementUnits" are limited, so we check both.
        case ((_maxReinforcementWaves>0) && {_maxReinforcementUnits>0}): {((_reinforcementWavesGiven>=_maxReinforcementWaves) || {_reinforcementUnitsGiven>=_maxReinforcementUnits})};

        // Only "_maxReinforcementWaves" is limited.
        case (_maxReinforcementWaves>0): {(_reinforcementWavesGiven>=_maxReinforcementWaves)};

        // Only "_maxReinforcementUnits" is limited.
        case (_maxReinforcementUnits>0): {(_reinforcementUnitsGiven>=_maxReinforcementUnits)};

        // Neither are limited, so reinforcements will never be depleted.
        default {false};
    };
};

private _reinforcementsDepleted = call _fnc_isDepleted;

if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) then
{
    private "_unitsToSpawn";

    private _remainingUnits =
        if (isNull _AIGroup) then
        {
            // The group (presumably) lost all units and got deleted, so we create a new group using the given side and continue with that.
            _AIGroup = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]);

            _this set [0, _AIGroup];


            if (DMS_DEBUG) then
            {
                (format ["GroupReinforcementsManager :: Group provided was null! Created new group for ""%1"" side: %2",_side, _AIGroup]) call DMS_fnc_DebugLog;
            };

            0
        }
        else
        {
            {alive _x} count (units _AIGroup);
        };


    if (DMS_DEBUG) then
    {
        (format ["GroupReinforcementsManager :: Checking reinforcements for group %1 with %2 surviving units. _this: %3",_AIGroup, _remainingUnits, _this]) call DMS_fnc_DebugLog;
    };

    switch (toLower _monitorType) do
    {
        case "playernear":
        {
            if !(_monitorParams params
            [
                "_posOrObj",
                "_radius",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if ([_posOrObj,_radius] call DMS_fnc_IsPlayerNearby) then
            {
                private _maxAICount = _monitorParams param [3, 0, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "maintain":
        {
            if !(_monitorParams params
            [
                "_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                _unitsToSpawn = _AICount - _remainingUnits;
            };
        };

        case "reinforce":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                private _maxAICount = _monitorParams param [2, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "increasing_resistance":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount",
                "_increment_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                private _maxAICount = _monitorParams param [3, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);

                _monitorParams set [0, _AICount + _increment_AICount];
            };
        };

        case "increasing_difficulty":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                _difficulty =
                    switch (toLower _difficulty) do
                    {
                        case "easy": {"moderate"};
                        case "moderate": {"difficult"};
                        case "difficult";
                        case "hardcore": {"hardcore"};
                    };

                private _maxAICount = _monitorParams param [3, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "armed_vehicle":
        {
            if !(_monitorParams params
            [
                "_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if (_remainingUnits<_AICount) then
            {
                private _vehClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                private _veh =
                [
                    [
                        if (_spawnLocations isEqualTo []) then {_leaderPos getPos [100+(random 200),random 360]} else {selectRandom _spawnLocations},
                        _leaderPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _vehClass
                ] call DMS_fnc_SpawnAIVehicle;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.",_AIGroup, _vehClass, _veh]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "armed_vehicle_replace":
        {
            if !(_monitorParams params
            [
                "_vehicle"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if ((isNull _vehicle) || {!alive _vehicle} || {(count (crew _vehicle)) isEqualTo 0}) then
            {
                deleteVehicle _vehicle;

                private _vehClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                _vehicle =
                [
                    [
                        if (_spawnLocations isEqualTo []) then {[_leaderPos,100+(random 200),random 360] call DMS_fnc_SelectOffsetPos} else {selectRandom _spawnLocations},
                        _leaderPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _vehClass
                ] call DMS_fnc_SpawnAIVehicle;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                _monitorParams set [0, _vehicle];

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.",_AIGroup, _vehClass, _vehicle]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "static_gunner":
        {
            if !(_monitorParams params
            [
                "_staticGun",
                "_gunPos"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if ((isNull _staticGun) || {!alive _staticGun} || {(count (crew _staticGun)) isEqualTo 0}) then
            {
                deleteVehicle _staticGun;

                private _staticGunClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                _staticGun =
                [
                    [
                        _gunPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _staticGunClass
                ] call DMS_fnc_SpawnAIStaticMG;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                _monitorParams set [0, _staticGun];

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" static gun (%3) as reinforcement at %4.",_AIGroup, _staticGunClass, _staticGun, _gunPos]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "heli_troopers":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_ejectFFVGunners",
                "_maxJumpers",
                "_remainAsGunship"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if (_remainingUnits<_AICount) then
            {
                private _dropPoint = _monitorParams param [4, getPosATL (leader _AIGroup), [objNull,[]], [2,3]];
                private _heliClass = _monitorParams param [5, selectRandom DMS_ReinforcementHelis, [""]];

                private _params =
                [
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _dropPoint,
                    _ejectFFVGunners,
                    _maxJumpers,
                    _remainAsGunship,
                    _heliClass
                ];

                if ((count _monitorParams)>6) then
                {
                    _params pushBack (_monitorParams select 6);
                };

                private _heli = _params call DMS_fnc_SpawnHeliReinforcement;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;


                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.", _AIGroup, typeOf _heliClass, _heli]) call DMS_fnc_DebugLog;
                };
            };
        };

        default
        {
            _reinforcementsDepleted = true;
            diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with unsupported _monitorType: %1 | Setting _reinforcementsDepleted to true.",_monitorType];
        };
    };

    if ((!isNil "_unitsToSpawn") && {_unitsToSpawn>0}) then
    {
        private _spawnPos = [];

        if (_maxReinforcementUnits>0) then
        {
            _maxAvailableReinforcements = (_maxReinforcementUnits-_reinforcementUnitsGiven) max 0;
            if (_maxAvailableReinforcements<_unitsToSpawn) then
            {
                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 requested %2 units for backup, but only %3 are available. Providing %3 units and setting _reinforcementsDepleted to true.",_AIGroup, _unitsToSpawn, _maxAvailableReinforcements]) call DMS_fnc_DebugLog;
                };
                _unitsToSpawn = _maxAvailableReinforcements;
                _reinforcementsDepleted = true;
            };
        };

        private _units = [];

        if (_spawnLocations isEqualTo []) then
        {
            // No spawn locations were provided, so we just use the leader of the group as the spawn location.
            _spawnPos = getPosATL (leader _AIGroup);

            for "_i" from 0 to (_unitsToSpawn-1) do
            {
                _units pushBack ([_AIGroup,_spawnPos,_class,_difficulty,_side,"Soldier",_customGearSet] call DMS_fnc_SpawnAISoldier);
            };
        }
        else
        {
            // Shuffle the list.
            private _spawningLocations = _spawnLocations call ExileClient_util_array_shuffle;
            _spawnPos = _spawningLocations select 0;                // Define it for spawning flares
            _spawningLocations_count = count _spawningLocations;

            // Add extra spawning locations if there are not enough.
            for "_i" from 0 to (_unitsToSpawn-_spawningLocations_count-1) do
            {
                _spawningLocations pushBack (selectRandom _spawningLocations);
            };

            // Now to spawn the AI...
            for "_i" from 0 to (_unitsToSpawn-1) do
            {
                _units pushBack ([_AIGroup,_spawningLocations select _i,_class,_difficulty,_side,"Soldier",_customGearSet] call DMS_fnc_SpawnAISoldier);
            };
        };

        _units joinSilent _AIGroup;        // Otherwise they don't like each other...

        // Update the given reinforcements count.
        _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
        _reinforcementUnitsGiven = _reinforcementUnitsGiven + _unitsToSpawn;

        if (DMS_SpawnFlareOnReinforcements) then
        {
            playSound3D ["a3\missions_f_beta\data\sounds\Showcase_Night\flaregun_4.wss", objNull, false, (ATLToASL _spawnPos) vectorAdd [0,0,250],2];
            ("F_20mm_Red" createVehicle (_spawnPos vectorAdd [0,0,250])) setVelocity [0,0,-1];
        };

        if (DMS_DEBUG) then
        {
            (format["GroupReinforcementsManager :: Group %1 received %2 units as backup (wave #%3, %4 units given total). Reinforcements Depleted: %5",_AIGroup, _unitsToSpawn, _reinforcementWavesGiven, _reinforcementUnitsGiven, _reinforcementsDepleted]) call DMS_fnc_DebugLog;
        };
    };

    if (!_reinforcementsDepleted) then
    {
        _reinforcementsDepleted = call _fnc_isDepleted;
    };

    // Update values
    _this set [1, [[_maxReinforcementWaves,_reinforcementWavesGiven],[_maxReinforcementUnits,_reinforcementUnitsGiven]]];
    _this set [2, [_updateDelay,diag_tickTime]];
};

_reinforcementsDepleted
 

 

Share this post


Link to post
Share on other sites
On 3/2/2022 at 4:38 PM, BSBS Vladick said:

Oh man, I just saw that you replied. Sorry for the late reply. Here is the  fn_GroupReinforcementsManager.

Thanks for your help!

 

  Reveal hidden contents

/*
    DMS_fnc_GroupReinforcementsManager
    Created by eraser1

    Usage:
    [
        _AIGroup,                        // GROUP: The AI group to monitor.
        [
            [
                _maxReinforcementWaves,            // SCALAR: The maximum number of reinforcement waves that this group can receive. Set to -1 for unlimited reinforcement waves.
                _reinforcementWavesGiven        // SCALAR: The number of reinforcement waves given to this group.
            ],
            [
                _maxReinforcementUnits,            // SCALAR: The maximum number of reinforcement units that this group can receive. Set to -1 for unlimited reinforcement units.
                _reinforcementUnitsGiven        // SCALAR: The number of reinforcement units given to this group.
            ]
        ],
        [
            _updateDelay,                    // SCALAR: Delay in seconds until the AI group is reinforced.
            _lastUpdated                    // SCALAR: The time (diag_tickTime) when the group was last reinforced.
        ],
        _spawnLocations,                // ARRAY: Array of positions (ATL) where reinforcement AI can spawn. Passing an empty array will cause the group leader's position to be used. For "armed_vehicle" _monitorType, a random position between 100 and 300 meters from the leader is used.
        _class,                            // STRING: The "class" of AI to spawn as reinforcements. Supported values: "random","assault","MG","sniper" or "unarmed"
        _difficulty,                    // STRING: The difficulty of the AI to be spawned. Supported values: "random","static","hardcore","difficult","moderate", or "easy"
        _side,                            // STRING: The "side" that the AI are on. Currently only "bandit" is supported.
        _monitorType,                    // STRING: How the AI group should be managed. Supported types: "playernear", "maintain", "reinforce", "increasing_resistance", "armed_vehicle"
        _monitorParams,                    // ARRAY: Parameters specific to the _monitorType. See below.
        _customGearSet                    // (OPTIONAL) ARRAY: The custom gear set of the AI. Refer to documentation of fn_SpawnAISoldier.sqf for more info: https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf
    ] call DMS_fnc_GroupReinforcementsManager;

    About "_monitorType" types:

        "playernear":
            _monitorParams =
            [
                _posOrObj,                // ARRAY (position): The position at which the players have to be near.
                _radius,                // SCALAR: The distance (in meters) that a player has to be near in order for reinforcements to spawn
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Set to 0 for no limit. Default value is 0.
            ]

        "maintain":
            _monitorParams =
            [
                _AICount                 // SCALAR: If the AI Group has fewer than "_AICount" living units, then new members will be added to the group until it has "_AICount" living units again.
            ]

        "reinforce":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Set to 0 for no limit. Default value is equivalent to _AICount.
            ]

        "increasing_resistance":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _increment_AICount,        // SCALAR: After reinforcements, "_AICount" is increased by this amount, so subsequent reinforcements will be spawned for even greater amounts of AI (increasing the number of total AI, until "_maxAICount" is reached).
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Default value is equivalent to _AICount. Set to 0 for no limit.
            ]

        "increasing_difficulty":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _reinforcementCount,    // SCALAR: The (maximum) number of units to spawn as reinforcements.
                _maxAICount                // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Default value is equivalent to _AICount. Set to 0 for no limit.
            ]

        "static_gunner":
            _monitorParams =
            [
                _staticGun,                // OBJECT: If this object (static gun) loses its gunner and/or is deleted, then a new static gun and/or gunner will spawn to replace the previous one.
                _gunPos,                // ARRAY (positionATL): The position of the static gun.
                _staticGunClass            // (OPTIONAL) STRING: The classname of the static gun to spawn as reinforcement.
            ]

        "armed_vehicle":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _vehClass                // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
            ]

        "armed_vehicle_replace":
            _monitorParams =
            [
                _vehicle,                // OBJECT: When this vehicle is null or dead, then this group will receive reinforcements. The spawned vehicle will then be the new _vehicle.
                _vehClass                // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
            ]
        NOTE: Every reinforcement vehicle counts as one unit given for monitor type "armed_vehicle" and "armed_vehicle_replace"

        "heli_troopers":
            _monitorParams =
            [
                _AICount,                // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
                _ejectFFVGunners,               // BOOLEAN: Whether or not to eject Fire-From-Vehicle (FFV) gunners.
                _maxJumpers,                    // SCALAR: Maximum number of AI to eject from the aircraft. Set to a really high # to ignore (like 999).
                _remainAsGunship,               // BOOLEAN: Whether or not to keep the heli flying around as a gunship.
                _dropPoint,                     // OBJECT or ARRAY (OPTIONAL - Position2D or 3D): The location to drop the reinforcements at. The drop point will default to the group leader.
                _heliClass,                     // STRING (OPTIONAL): The classname of the heli to spawn.
                _spawnPos                       // ARRAY (OPTIONAL - Position2D or 3D): The position for the heli to spawn at.
            ]
            This reinforcement type will attempt to drop the AI off at the group leader's position. The heli will spawn in the air 500-5000 meters away from the leader's position and 1000 meters away from a player (default).

    Returns whether or not reinforcement waves or units given exceeds/matches maximum wave or unit reinforcements. If true, then no more reinforcements will be spawned (so the passed info should be deleted from the available reinforcements list).
*/

// Check ALL the variables
if !(params
[
    "_AIGroup",
    "_reinforcementInfo",
    "_updateInfo",
    "_spawnLocations",
    "_class",
    "_difficulty",
    "_side",
    "_monitorType",
    "_monitorParams"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid parameters: %1",_this];
    true
};


if !(_reinforcementInfo params
[
    "_wavesInfo",
    "_unitsInfo"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _reinforcementInfo: %1",_reinforcementInfo];
    true
};


if !(_wavesInfo params
[
    "_maxReinforcementWaves",
    "_reinforcementWavesGiven"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _wavesInfo: %1",_wavesInfo];
    true
};


if !(_unitsInfo params
[
    "_maxReinforcementUnits",
    "_reinforcementUnitsGiven"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _unitsInfo: %1",_unitsInfo];
    true
};


if !(_updateInfo params
[
    "_updateDelay",
    "_lastUpdated"
])
exitWith
{
    diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _updateInfo: %1",_updateInfo];
    true
};

private _customGearSet =
    if ((count _this) > 9) then
    {
        _this select 9
    }
    else
    {
        []
    };

_fnc_isDepleted =
{
    switch (true) do
    {
        // Both "_maxReinforcementWaves" and "_maxReinforcementUnits" are limited, so we check both.
        case ((_maxReinforcementWaves>0) && {_maxReinforcementUnits>0}): {((_reinforcementWavesGiven>=_maxReinforcementWaves) || {_reinforcementUnitsGiven>=_maxReinforcementUnits})};

        // Only "_maxReinforcementWaves" is limited.
        case (_maxReinforcementWaves>0): {(_reinforcementWavesGiven>=_maxReinforcementWaves)};

        // Only "_maxReinforcementUnits" is limited.
        case (_maxReinforcementUnits>0): {(_reinforcementUnitsGiven>=_maxReinforcementUnits)};

        // Neither are limited, so reinforcements will never be depleted.
        default {false};
    };
};

private _reinforcementsDepleted = call _fnc_isDepleted;

if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) then
{
    private "_unitsToSpawn";

    private _remainingUnits =
        if (isNull _AIGroup) then
        {
            // The group (presumably) lost all units and got deleted, so we create a new group using the given side and continue with that.
            _AIGroup = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]);

            _this set [0, _AIGroup];


            if (DMS_DEBUG) then
            {
                (format ["GroupReinforcementsManager :: Group provided was null! Created new group for ""%1"" side: %2",_side, _AIGroup]) call DMS_fnc_DebugLog;
            };

            0
        }
        else
        {
            {alive _x} count (units _AIGroup);
        };


    if (DMS_DEBUG) then
    {
        (format ["GroupReinforcementsManager :: Checking reinforcements for group %1 with %2 surviving units. _this: %3",_AIGroup, _remainingUnits, _this]) call DMS_fnc_DebugLog;
    };

    switch (toLower _monitorType) do
    {
        case "playernear":
        {
            if !(_monitorParams params
            [
                "_posOrObj",
                "_radius",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if ([_posOrObj,_radius] call DMS_fnc_IsPlayerNearby) then
            {
                private _maxAICount = _monitorParams param [3, 0, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "maintain":
        {
            if !(_monitorParams params
            [
                "_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                _unitsToSpawn = _AICount - _remainingUnits;
            };
        };

        case "reinforce":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                private _maxAICount = _monitorParams param [2, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "increasing_resistance":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount",
                "_increment_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                private _maxAICount = _monitorParams param [3, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);

                _monitorParams set [0, _AICount + _increment_AICount];
            };
        };

        case "increasing_difficulty":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_reinforcementCount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };


            if (_remainingUnits<_AICount) then
            {
                _difficulty =
                    switch (toLower _difficulty) do
                    {
                        case "easy": {"moderate"};
                        case "moderate": {"difficult"};
                        case "difficult";
                        case "hardcore": {"hardcore"};
                    };

                private _maxAICount = _monitorParams param [3, _AICount, [0]];

                _unitsToSpawn = _reinforcementCount min ((_maxAICount-_remainingUnits) max 0);
            };
        };

        case "armed_vehicle":
        {
            if !(_monitorParams params
            [
                "_AICount"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if (_remainingUnits<_AICount) then
            {
                private _vehClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                private _veh =
                [
                    [
                        if (_spawnLocations isEqualTo []) then {_leaderPos getPos [100+(random 200),random 360]} else {selectRandom _spawnLocations},
                        _leaderPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _vehClass
                ] call DMS_fnc_SpawnAIVehicle;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.",_AIGroup, _vehClass, _veh]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "armed_vehicle_replace":
        {
            if !(_monitorParams params
            [
                "_vehicle"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if ((isNull _vehicle) || {!alive _vehicle} || {(count (crew _vehicle)) isEqualTo 0}) then
            {
                deleteVehicle _vehicle;

                private _vehClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                _vehicle =
                [
                    [
                        if (_spawnLocations isEqualTo []) then {[_leaderPos,100+(random 200),random 360] call DMS_fnc_SelectOffsetPos} else {selectRandom _spawnLocations},
                        _leaderPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _vehClass
                ] call DMS_fnc_SpawnAIVehicle;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                _monitorParams set [0, _vehicle];

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.",_AIGroup, _vehClass, _vehicle]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "static_gunner":
        {
            if !(_monitorParams params
            [
                "_staticGun",
                "_gunPos"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if ((isNull _staticGun) || {!alive _staticGun} || {(count (crew _staticGun)) isEqualTo 0}) then
            {
                deleteVehicle _staticGun;

                private _staticGunClass = _monitorParams param [1, "random", [""]];

                private _leaderPos = getPosATL (leader _AIGroup);

                _staticGun =
                [
                    [
                        _gunPos
                    ],
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _staticGunClass
                ] call DMS_fnc_SpawnAIStaticMG;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;

                _monitorParams set [0, _staticGun];

                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" static gun (%3) as reinforcement at %4.",_AIGroup, _staticGunClass, _staticGun, _gunPos]) call DMS_fnc_DebugLog;
                };
            };
        };

        case "heli_troopers":
        {
            if !(_monitorParams params
            [
                "_AICount",
                "_ejectFFVGunners",
                "_maxJumpers",
                "_remainAsGunship"
            ])
            exitWith
            {
                _reinforcementsDepleted = true;
                diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
            };

            if (_remainingUnits<_AICount) then
            {
                private _dropPoint = _monitorParams param [4, getPosATL (leader _AIGroup), [objNull,[]], [2,3]];
                private _heliClass = _monitorParams param [5, selectRandom DMS_ReinforcementHelis, [""]];

                private _params =
                [
                    _AIGroup,
                    _class,
                    _difficulty,
                    _side,
                    _dropPoint,
                    _ejectFFVGunners,
                    _maxJumpers,
                    _remainAsGunship,
                    _heliClass
                ];

                if ((count _monitorParams)>6) then
                {
                    _params pushBack (_monitorParams select 6);
                };

                private _heli = _params call DMS_fnc_SpawnHeliReinforcement;

                // Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
                _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
                _reinforcementUnitsGiven = _reinforcementWavesGiven;


                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.", _AIGroup, typeOf _heliClass, _heli]) call DMS_fnc_DebugLog;
                };
            };
        };

        default
        {
            _reinforcementsDepleted = true;
            diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with unsupported _monitorType: %1 | Setting _reinforcementsDepleted to true.",_monitorType];
        };
    };

    if ((!isNil "_unitsToSpawn") && {_unitsToSpawn>0}) then
    {
        private _spawnPos = [];

        if (_maxReinforcementUnits>0) then
        {
            _maxAvailableReinforcements = (_maxReinforcementUnits-_reinforcementUnitsGiven) max 0;
            if (_maxAvailableReinforcements<_unitsToSpawn) then
            {
                if (DMS_DEBUG) then
                {
                    (format["GroupReinforcementsManager :: Group %1 requested %2 units for backup, but only %3 are available. Providing %3 units and setting _reinforcementsDepleted to true.",_AIGroup, _unitsToSpawn, _maxAvailableReinforcements]) call DMS_fnc_DebugLog;
                };
                _unitsToSpawn = _maxAvailableReinforcements;
                _reinforcementsDepleted = true;
            };
        };

        private _units = [];

        if (_spawnLocations isEqualTo []) then
        {
            // No spawn locations were provided, so we just use the leader of the group as the spawn location.
            _spawnPos = getPosATL (leader _AIGroup);

            for "_i" from 0 to (_unitsToSpawn-1) do
            {
                _units pushBack ([_AIGroup,_spawnPos,_class,_difficulty,_side,"Soldier",_customGearSet] call DMS_fnc_SpawnAISoldier);
            };
        }
        else
        {
            // Shuffle the list.
            private _spawningLocations = _spawnLocations call ExileClient_util_array_shuffle;
            _spawnPos = _spawningLocations select 0;                // Define it for spawning flares
            _spawningLocations_count = count _spawningLocations;

            // Add extra spawning locations if there are not enough.
            for "_i" from 0 to (_unitsToSpawn-_spawningLocations_count-1) do
            {
                _spawningLocations pushBack (selectRandom _spawningLocations);
            };

            // Now to spawn the AI...
            for "_i" from 0 to (_unitsToSpawn-1) do
            {
                _units pushBack ([_AIGroup,_spawningLocations select _i,_class,_difficulty,_side,"Soldier",_customGearSet] call DMS_fnc_SpawnAISoldier);
            };
        };

        _units joinSilent _AIGroup;        // Otherwise they don't like each other...

        // Update the given reinforcements count.
        _reinforcementWavesGiven = _reinforcementWavesGiven + 1;
        _reinforcementUnitsGiven = _reinforcementUnitsGiven + _unitsToSpawn;

        if (DMS_SpawnFlareOnReinforcements) then
        {
            playSound3D ["a3\missions_f_beta\data\sounds\Showcase_Night\flaregun_4.wss", objNull, false, (ATLToASL _spawnPos) vectorAdd [0,0,250],2];
            ("F_20mm_Red" createVehicle (_spawnPos vectorAdd [0,0,250])) setVelocity [0,0,-1];
        };

        if (DMS_DEBUG) then
        {
            (format["GroupReinforcementsManager :: Group %1 received %2 units as backup (wave #%3, %4 units given total). Reinforcements Depleted: %5",_AIGroup, _unitsToSpawn, _reinforcementWavesGiven, _reinforcementUnitsGiven, _reinforcementsDepleted]) call DMS_fnc_DebugLog;
        };
    };

    if (!_reinforcementsDepleted) then
    {
        _reinforcementsDepleted = call _fnc_isDepleted;
    };

    // Update values
    _this set [1, [[_maxReinforcementWaves,_reinforcementWavesGiven],[_maxReinforcementUnits,_reinforcementUnitsGiven]]];
    _this set [2, [_updateDelay,diag_tickTime]];
};

_reinforcementsDepleted
 

 

core files seem fine, what static mission are you trying to use? (maybe zip the whole dms folder so I can dwell on it)

Share this post


Link to post
Share on other sites
On 3/4/2022 at 3:42 AM, chernaruski said:

core files seem fine, what static mission are you trying to use? (maybe zip the whole dms folder so I can dwell on it)

@chernaruski Thank you for your replies. I have created about a dozen static missions that are currently running on my Exile Chernarus server. I have used various templates that I found online to create the mission files for DMS. About half of them are configured to spawn reinforcements and everything seems to be working in game. I was just hoping that I could get rid of those pesky errors spamming in my RPT. I would be happy to zip the DMS folder but I don't know anything about pastebin. How can I DM them to you, Discord? Here is my discord link in case you want to join and DM me.

 

https://discord.gg/rSzfvY9n

 

Thanks for your help!

Share this post


Link to post
Share on other sites

×