Jump to content

Recommended Posts

A simple script for ambient combat generation that you can put in a trigger. You can use any groups, vehicles or units. The default is CUP_RU vs CUP_US vs CUP_I_TK_GUE ambient combat.

 

Changelog:

v 1.4

  • Script now uses vanilla units. Here are CUP units from the previous script in case you need them:
Spoiler


_east_infantry = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_AA"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_AT"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_EMR"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_MG")];

_east_armored = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Mechanized" >> "CUP_O_RU_MechInfSquad_2"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Motorized" >> "CUP_O_RU_MotInfSquad"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Armored" >> "CUP_O_RU_TankPlatoon"), "CUP_O_2S6_RU"];

_east_air = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Air" >> "CUP_O_RU_Mi24PSquadron"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Air" >> "CUP_O_RU_Mi8Squadron"), "CUP_O_SU34_RU"];

_west_infantry = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_HeavyATTeam"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_RifleSquad"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_TeamAT"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_WeaponsSquad")];

_west_armored = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedInfantrySquadICVM2"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedInfantrySquadICVMK19"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedReconSection"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Motorized" >> "CUP_B_US_Army_MotorizedSectionAT"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Motorized" >> "CUP_B_US_Army_MotorizedSection"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Armored" >> "CUP_B_US_Army_M1A1Platoon"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Armored" >> "CUP_B_US_Army_MGSPlatoon"), "CUP_B_HMMWV_Avenger_USA"];

_west_air = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Air" >> "CUP_B_US_Army_AH64DFlight"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Air" >> "CUP_B_US_Army_CH47FFlight"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_USMC" >> "Air" >> "CUP_B_USMC_UH1YSquadron"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_USMC" >> "Air" >> "CUP_B_USMC_MV22Squadron"), "CUP_B_A10_DYN_USA", "B_UAV_02_dynamicLoadout_F"];

_guer_infantry = [(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Infantry" >> "CUP_I_TK_GUE_GroupWeapons"),
(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Infantry" >> "CUP_I_TK_GUE_AATeam"),
(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Infantry" >> "CUP_I_TK_GUE_ATTeam")];

_guer_armored = [(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Armored" >> "CUP_I_TK_GUE_T34Platoon"),
(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Mechanized" >> "CUP_I_TK_GUE_MechanizedGroup"),
(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Motorized" >> "CUP_I_TK_GUE_MotorizedPatrol"), "CUP_I_Ural_ZU23_TK_Gue",
["CUP_I_Datsun_PK_TK", "CUP_I_Datsun_PK_TK"]];

_guer_air = [(configfile >> "CfgGroups" >> "Indep" >> "CUP_I_TK_GUE" >> "Air" >> "CUP_I_TK_GUE_UH1HSquadron"),
["CUP_I_UH1H_armed_TK_GUE", "CUP_I_UH1H_armed_TK_GUE"]];

_west_drones = ["B_UAV_01_F"];
_east_drones = ["O_UAV_01_F"];
_guer_drones = ["I_UAV_06_F"];

_east_mortars = ["O_Mortar_01_F"];
_west_mortars = ["CUP_B_M252_US"];
_guer_mortars = ["CUP_I_2b14_82mm_TK_GUE"];

_unitSides = [[east, [_east_infantry, _east_armored, _east_air, _east_drones, _east_mortars]],
[west, [_west_infantry, _west_armored, _west_air, _west_drones, _west_mortars]],
[resistance, [_guer_infantry, _guer_armored, _guer_air, _guer_drones, _guer_mortars]]];

_unitSideWeights = [_eastWeight, _westWeight, _guerWeight];
_unitTypeWeights = [1, _armoredWeight, _airWeight, _droneWeight, _mortarWeight];


_armedOptions = [["CUP_hgun_Makarov","CUP_8Rnd_9x18_Makarov_M"]];
_armedWeights = [1];
_armedMagazines = 2;

 

  • Script now should correctly despawn empty vehicles. (Not fully tested, if you encounter this bug with the new version of the script, DM me).
  • Tasks module now has some inaccuracy in counting enemy units. Instead of saying "Enemy group has 4 infantry units" it will now say something like "2-6 units", making tasks less predictable. The inaccuracy is customizable in settings (_reconCountInaccuracy parameter).
  • Script now runs every second - which gets rid of some bugs with condition testing.
  • Script now supports arming unarmed units - e.g. for the "armed civilians" scenario.
  • Fixed a bug with mission end in MP - script correctly uses BIS_fnc_endMissionServer now.
  • [Experimental feature] Script now has an option to spawn units only out of sight. Only one player's sight is supported (the one that is returned by the _fnc_center) and it is not 100% guarantee in some cases - if you spawn groups close to the player, due to the sizes of groups some units might still spawn in sight (only group leader's position is expected to be out of sight). This feature is disabled by default.

v 1.3

  • Fully tweakable spawning system. Want to be able to spawn 2 planes, 1 tank and 5 infantry units as one team? No problem - scripts supports custom arrays of units, groups or both.
  • You don't need to specify Config paths to list units: only a class name (string) is enough.
  • Added a default Insurgent faction (CUP_I_TK_GUE).
  • Only sides defined by _zeusableSides will show up in Zeuses. See "Tweaking the Script".
  • Added two functions that will stop or pause spawning if the condition is true. Refer to "Tweaking the Script" for examples.
  • Added an option to guide units behavior by MCC instead of default patrolling logic.

 

v 1.2

 

  • Planes! Planes can be spawned and will have a bigger boundary for despawning.
  • Script is rewritten, bits of code are separated as functions. It became easier to change the center of spawn: change one line, not "search and replace".
  • Comments! Triggers only support "comment" statements and crash when I try to add // or /* type of comments. Nevertheless, the script is a bit more readable now.
  • Made it a bit easier to have several copies of the script.
  • All the relevant info about the script is now at bohemia forums.

 

v 1.1

 

  • Added task generation system.

 

v 1.0

 

  • Script generates random groups and units, despawns them if they are too far, despawns dead bodies.

 

 

 

Spoiler

if NOT(isServer) exitWith {};

_nul = [] spawn 
{

comment "FUNCTION: should return a position or object around which ambient combat will be spawned";
_fnc_center = {
    leader playerGroup;
};

comment "FUNCTION: if true, completely end the script";
_fnc_IfTrueStopScript = {
    false;
};

comment "FUNCTION: if true, do not spawn a new group";
_fnc_IfTrueDontSpawn = {
    false;
};


_maxDistance = 600;
_minDistance = 250;
_despawnDistance = 1000;
_sleepTime = 20;
_limit = 30;
_patrolDistance = 300;
_deadBodyDespawnDistance = 300;
_defaultPlaneHeight = 300;
_defaultPlaneSpeed = 150;
_planeDespawnDistance = 4500;
_zeusableSides = [west];
_forceZeusForget = false;
_notifyOnScriptStop = true;
_isMccEnabled = false;
_sleepBeforeStart = 50;
_spawnOutOfSight = false;
_despawnOutOfSight = false;

_armoredWeight = 0.15;
_airWeight = 0.2;
_droneWeight = 0.06;
_mortarWeight = 0.06;

_eastWeight = 1;
_westWeight = 1;
_guerWeight = 1;



_totalTasks = 0;
_tasksWillMissionEnd = false;
_reconUpdateTime = 60; 
_reconAccuracyPosition = 60;
_reconCountInaccuracy = 3;
_tasksTargetSides = [east, resistance];
_taskReceivingGroup = west;
_taskMinGroups = 3;

comment "If you want to have several copies of this script present, you should make these strings different in each script!";
_scriptControlVariable = "ALP_fnc_RandomlySpawned";
_reconMarkerName = "ReconCircle";
_taskPrefix = "ALPtsk";


_currentTaskName = "";
_isTaskAssigned = false;
_targetGroup = 0;
_taskCircleMarker = 0;
_reconUpdVar = 0;

_scriptUpdVar = 0;


_east_infantry = [(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Infantry" >> "O_InfTeam_AT_Heavy"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Infantry" >> "OIA_InfSquad"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Infantry" >> "OIA_InfSquad_Weapons"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Infantry" >> "OIA_InfTeam_AA"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Infantry" >> "OIA_ReconSquad")];

_east_armored = [(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Armored" >> "OIA_TankPlatoon"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Armored" >> "OIA_TankPlatoon_AA"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Mechanized" >> "OIA_MechInf_AT"),
(configfile >> "CfgGroups" >> "East" >> "OPF_F" >> "Mechanized" >> "OIA_MechInfSquad")];

_east_air = ["O_Heli_Attack_02_dynamicLoadout_F",
"O_Heli_Light_02_dynamicLoadout_F",
"O_Plane_CAS_02_dynamicLoadout_F",
"O_Plane_Fighter_02_F",
"O_Plane_Fighter_02_Stealth_F","O_UAV_02_dynamicLoadout_F"];

_west_infantry = [(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Infantry" >> "BUS_InfTeam_AA"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Infantry" >> "BUS_InfSquad"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Infantry" >> "BUS_InfTeam_AT"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Infantry" >> "BUS_ReconSquad")];

_west_armored = [(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Armored" >> "BUS_TankPlatoon"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Armored" >> "BUS_TankPlatoon_AA"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Mechanized" >> "BUS_MechInfSquad"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Mechanized" >> "BUS_MechInf_AA"),
(configfile >> "CfgGroups" >> "West" >> "BLU_F" >> "Mechanized" >> "BUS_MechInf_AT")];

_west_air = [["B_Heli_Light_01_dynamicLoadout_F", "B_Heli_Light_01_dynamicLoadout_F"],
"B_Heli_Attack_01_dynamicLoadout_F", "B_Plane_CAS_01_dynamicLoadout_F", "B_Plane_Fighter_01_F",
"B_UAV_02_dynamicLoadout_F","B_UAV_05_F"];

_guer_infantry = [(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Infantry" >> "HAF_InfSquad"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Infantry" >> "HAF_InfSquad_Weapons"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Infantry" >> "HAF_InfTeam_AA"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Infantry" >> "HAF_InfTeam_AT")];

_guer_armored = [(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Armored" >> "HAF_TankPlatoon"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Armored" >> "HAF_TankPlatoon_AA"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Mechanized" >> "HAF_MechInf_AT"),
(configfile >> "CfgGroups" >> "Indep" >> "IND_F" >> "Mechanized" >> "HAF_MechInfSquad")];

_guer_air = [["I_Heli_light_03_dynamicLoadout_F","I_Heli_light_03_dynamicLoadout_F"],
"I_Plane_Fighter_03_dynamicLoadout_F",
"I_Plane_Fighter_04_F"];

_west_drones = ["B_UAV_01_F"];
_east_drones = ["O_UAV_01_F"];
_guer_drones = ["I_UAV_01_F"];

_east_mortars = ["O_Mortar_01_F"];
_west_mortars = ["B_Mortar_01_F"];
_guer_mortars = ["I_Mortar_01_F"];

_unitSides = [[east, [_east_infantry, _east_armored, _east_air, _east_drones, _east_mortars]],
[west, [_west_infantry, _west_armored, _west_air, _west_drones, _west_mortars]],
[resistance, [_guer_infantry, _guer_armored, _guer_air, _guer_drones, _guer_mortars]]];

_unitSideWeights = [_eastWeight, _westWeight, _guerWeight];
_unitTypeWeights = [1, _armoredWeight, _airWeight, _droneWeight, _mortarWeight];


_armedOptions = [["hgun_Pistol_heavy_01_F","11Rnd_45ACP_Mag"]];
_armedWeights = [1];
_armedMagazines = 2;


comment "FUNCTION: determine behavior for _grp. If MCC is enabled, give it to GAIA. Otherwise make it patrol";
_fnc_task_grp = {
    params ["_grp"];
    if (_isMccEnabled) then {
        _grp setVariable ["GAIA_ZONE_INTEND",["1","MOVE"],true];
    } else {
        [_grp, position leader _grp, _patrolDistance] call bis_fnc_taskpatrol;
    };
};

comment "FUNCTION: If _veh is a plane, spawn it in the air";
_fnc_fixPlaneSpawn = {
    params ["_veh"];
    if (_veh isKindOf "Plane") then {
        _veh setPos [getPos _veh select 0, getPos _veh select 1, _defaultPlaneHeight];
        _dir = direction _veh;
        _veh setVelocity [(sin _dir * _defaultPlaneSpeed), (cos _dir * _defaultPlaneSpeed), 0];
    };
};

comment "FUNCTION: Counts the amount of [infantry, vehicles] in _targetGroup";
_fnc_countUnits = {
    params ["_targetGroup"];
    _vehArray = [];
    _unitCnt = 0;
    {
        if (vehicle _x != _x) then {
            _vehArray pushBackUnique (vehicle _x);
        } else {
            _unitCnt = _unitCnt + 1;
        }
    } forEach units _targetGroup;
    [_unitCnt, count _vehArray];
};

comment "FUNCTION: Counts the amount of [infantry, vehicles] in _targetGroup with some inaccuracy. Returns string";
_fnc_countUnitsInaccurately = {
    params ["_targetGroup", "_maxError"];
    _unitCntArray = _targetGroup call _fnc_countUnits;
    if (_maxError == 0) then {
        format ["Eliminate the enemy (%1 infantry, %2 vehicles)", _unitCntArray select 0, _unitCntArray select 1];
    } else {
        _unitCnt = _unitCntArray select 0;
        _vehCnt = _unitCntArray select 1;
        _unitString = "???";
        _vehString = "???";
        if (_unitCnt == 0) then {
            _unitString = "0";
        } else {
            _uLower = _unitCnt - round (random _maxError);
            _uLower = _uLower max 0;
            _uUpper = _unitCnt + round (random _maxError);
            _unitString = format ["%1-%2", _uLower, _uUpper];
        };
        if (_vehCnt == 0) then {
            _vehString = "0";
        } else {
            _vLower = _vehCnt - round (random _maxError);
            _vUpper = _vehCnt + round (random _maxError);
            _vLower = _vLower max 0;
            _vehString = format ["%1-%2", _vLower, _vUpper];
        };
        format ["Eliminate the enemy (%1 infantry, %2 vehicles)", _unitString, _vehString];
    };
};
    

comment "FUNCTION: Evaluates the despawn distance for an alive _group.";
_fnc_getDespawnDistance = {
    params ["_group"];
    _groupHasPlane = false;
    {
        if ((vehicle _x) isKindOf "Plane") then {
            _groupHasPlane = true;
        }
    } forEach units _group;
    if (_groupHasPlane) then {_planeDespawnDistance;} else {_despawnDistance;};
};

comment "FUNCTION: parse String/CfgVehicle _str for ##armed";
_fnc_parseStringVehicle = {
    params ["_str"];
    if (["##armed", _str] call BIS_fnc_inString) then {
        [([_str, 0, -7] call BIS_fnc_trimString), true];
    } else {
        [_str, false];
    };
};

comment "FUNCTION: arm a _unit";
_fnc_armCivilian = {
    params ["_unit"];
    _armOption = _armedOptions selectRandomWeighted _armedWeights;
    _weapon = _armOption select 0;
    _mag = _armOption select 1;
    _unit addWeapon _weapon;
    for "_i" from 1 to _armedMagazines do {_unit addItemToUniform _mag;};
};
    

comment "FUNCTION: Given _pos, _side and _unit (either Config/CfgGroups, Config/CfgVehicles, String/CfgVehicles, or array any of them) generate a group";
_fnc_spawnUnitAtPos = {
    params ["_pos", "_side", "_unit"];
    _grp = if (typeName _unit == "STRING") then {
        comment "It's String/CfgVehicles";
        _parsed = _unit call _fnc_parseStringVehicle;
        _unit = _parsed select 0;
        _x = [_pos, random 360, _unit, _side] call bis_fnc_spawnvehicle;
        (_x select 0) call _fnc_fixPlaneSpawn;
        if (_parsed select 1) then {
            (_x select 0) call _fnc_armCivilian;
        };
        _x select 2;
    } else {
        if (typeName _unit == "CONFIG") then {
            if ((configfile >> "CfgGroups") in configHierarchy _unit) then {
                _a = [_pos, _side, _unit] call BIS_fnc_spawnGroup;
                {
                    (vehicle _x) call _fnc_fixPlaneSpawn;
                } forEach units _a;
                _a;
            }
            else {
                if ((configfile >> "CfgVehicles") in configHierarchy _unit) then {
                    _name = configName _unit;
                    _x = [_pos, random 360, _name, _side] call bis_fnc_spawnvehicle;
                    (_x select 0) call _fnc_fixPlaneSpawn;
                    _x select 2;
                };
            };
        } else {
            if (typeName _unit == "ARRAY") then {
                _subgrps = [];
                {
                    _pos2 = [_pos, 0, 50, 3, 0, 20, 0] call BIS_fnc_findSafePos;
                    _subgrp = [_pos2, _side, _x] call _fnc_spawnUnitAtPos;
                    _subgrp deleteGroupWhenEmpty true;
                    _subgrps = _subgrps + [_subgrp];
                } forEach _unit;
                _newgrp = createGroup _side;
                {
                    units _x join _newgrp;
                } forEach _subgrps;
                _newgrp;
            } else {
                systemChat format ["Could not create a unit: %1, wrong specification", _unit];
            };
        };
    };
    _grp;
};

comment "FUNCTION: find position out of sight";
_fnc_posOutOfSight = {
    params ["_centerObject", "_minD", "_maxD", "_fov"];
    
    _posFound = false;
    _pos = 0;
    _posTries = 1000;
    while {(!_posFound) AND (_posTries > 0)} do
    {
        _pos = [_centerObject, _minD, _maxD, 3, 0, 20, 0] call BIS_fnc_findSafePos;
        _inView = [position _centerObject, getdir _centerObject, _fov, _pos] call BIS_fnc_inAngleSector;
        if (!_inView) then {
            _posFound = true;
        };
        _posTries = _posTries - 1;
    };
    if (_posFound) then {
        _pos;
    } else {
        [_centerObject, _minD, _maxD, 3, 0, 20, 0] call BIS_fnc_findSafePos;
    };
};

comment "FUNCTION: find position, out of sight if needed";
_fnc_findSpawnPos = {
    params ["_centerObject", "_minD", "_maxD", "_fov"];
    if (_spawnOutOfSight) then {
        [_centerObject, _minD, _maxD, _fov] call _fnc_posOutOfSight;
    } else {
        [_centerObject, _minD, _maxD, 3, 0, 20, 0] call BIS_fnc_findSafePos;
    };
};

comment "FUNCTION: determine if distance and sight makes it OK to despawn a group";
_fnc_canDespawn = {
    params ["_grp", "_despDistance", "_isGroup", "_fov"];
    _target = objNull;
    if (_isGroup) then {
        _target = leader _grp;
    } else {
        _target = _grp;
    };
    if (_despawnOutOfSight) then {
        _inView = [position (call _fnc_center), getDir (call _fnc_center), _fov, position _target] call BIS_fnc_inAngleSector;
        _inSight = count (lineIntersectsWith [eyePos (call _fnc_center), eyePos _target, (call _fnc_center), _target]) == 0;
        (_target distance (call _fnc_center) > _despDistance) AND !(_inView AND _inSight);
    } else {
        _target distance (call _fnc_center) > _despDistance;
    };
};

sleep _sleepBeforeStart;
systemChat "Ambient combat & tasks routines are starting.";

{
    createCenter (_x select 0);
} forEach _unitSides;

while {!(call _fnc_IfTrueStopScript)} do
    {
    
    
    if (round ((_scriptUpdVar)%_sleepTime) == 0) then {
        comment "===Spawn section===";
        if (((count (allGroups select {(_x getVariable [_scriptControlVariable,false])})) < _limit) AND (!(call _fnc_IfTrueDontSpawn))) then {
            _pos = [call _fnc_center, _minDistance, _maxDistance, 3, 0, 20, 0] call BIS_fnc_findSafePos;
            _unitSide = _unitSides selectRandomWeighted _unitSideWeights;
            _unitType = (_unitSide select 1) selectRandomWeighted _unitTypeWeights;
            _unit = selectRandom _unitType;
            _grp = [_pos, _unitSide select 0, _unit] call _fnc_spawnUnitAtPos;
            if (isNil "_grp") then {
                systemChat "Group is not returned to the script.";
            }
            else {
                _grp setVariable [_scriptControlVariable, true];
                {_x setVariable [_scriptControlVariable, true]} forEach units _grp;
                _grp deleteGroupWhenEmpty true;
                _grp call _fnc_task_grp;
                if ((_unitSide select 0) in _zeusableSides) then {
                    {_x addCuratorEditableObjects [units _grp, true]} forEach allCurators;
                } else {
                    if (_forceZeusForget) then {
                        {_x removeCuratorEditableObjects [units _grp, true]} forEach allCurators;
                    };
                };
            };
        };
        comment "===Alive groups despawn section===";
        {
            _grp = _x;
            if ([_grp, _despawnDistance, true, 130] call _fnc_canDespawn) then {
                {
                    if (vehicle _x != _x) then {
                        deleteVehicle (vehicle _x);
                    };
                    deleteVehicle _x;
                } forEach units _grp;
                deleteGroup _grp;
            };
        } forEach (allGroups select {(_x getVariable [_scriptControlVariable,false])});
        comment "===Dead bodies despawn section===";
        {
            if ([_x, _deadBodyDespawnDistance, false, 130] call _fnc_canDespawn) then {
                deleteVehicle _x;
            };
        } forEach (allDead select {(_x getVariable [_scriptControlVariable,false])});
        comment "===Empty vehicles despawn section===";
        {
            _y = _x;
            if ((({alive _x} count (crew _y)) == 0) AND ([_y, _deadBodyDespawnDistance, false, 130] call _fnc_canDespawn)) then {
                deleteVehicle _y;
            };
        } forEach (vehicles select {(_x getVariable [_scriptControlVariable,false])});
    };
    
    comment "===Task assignment section===";
    if (!_isTaskAssigned AND (_totalTasks > 0) AND ({(_x getVariable [_scriptControlVariable,false]) AND (side _x in _tasksTargetSides)} count allGroups  >= _taskMinGroups)) then {
        _targetGroup = selectRandom (allGroups select {(_x getVariable [_scriptControlVariable,false]) AND side _x in _tasksTargetSides});
        _targetGroup setVariable [_scriptControlVariable, false];
        _reconPos = [[[getPos leader _targetGroup, _reconAccuracyPosition]]] call BIS_fnc_RandomPos;
        _taskString = [_targetGroup, _reconCountInaccuracy] call _fnc_countUnitsInaccurately;
        _currentTaskName = format [_taskPrefix+"%1", _totalTasks];
        
        _taskCircleMarker = createMarker [_reconMarkerName, _reconPos];
        _taskCircleMarker setMarkerShape "ELLIPSE";
        _taskCircleMarker setMarkerSize [_reconAccuracyPosition, _reconAccuracyPosition];
        _taskCircleMarker setMarkerBrush "Border";
        _taskCircleMarker setMarkerColor "ColorRed";
        _taskCircleMarker setMarkerPos _reconPos;
        
        [_taskReceivingGroup, _currentTaskName, ["", _taskString, _reconMarkerName], _reconPos, true, 0, true, "Attack", true] call BIS_fnc_taskCreate;
        _isTaskAssigned = true;
        _reconUpdVar = 0;
    } else {
        if (_isTaskAssigned) then {
            comment "===Assigned task control section===";
            _reconUpdVar = round ((_reconUpdVar+1)%_reconUpdateTime);
            if (_reconUpdVar == _reconUpdateTime-1) then {
                _reconPos = [[[getPos leader _targetGroup, _reconAccuracyPosition]]] call BIS_fnc_RandomPos;
                [_currentTaskName, _reconPos] call BIS_fnc_taskSetDestination;
                _taskCircleMarker setMarkerPos _reconPos;
            };
            if ({alive _x} count (units _targetGroup) == 0) then {
                    [_currentTaskName, "SUCCEEDED"] call BIS_fnc_taskSetState;
                    deleteMarker _reconMarkerName;
                    _isTaskAssigned = false;
                    _targetGroup = 0;
                    _totalTasks = _totalTasks - 1;
                    if (_totalTasks == 0 AND _tasksWillMissionEnd) then {
                        "end1" call BIS_fnc_endMissionServer;
                    };
                };
        };
    };
    
	sleep 1;
    _scriptUpdVar = _scriptUpdVar + 1;
};
    
if (_notifyOnScriptStop) then {
    systemChat "Ambient combat & tasks routines are finished";
};

comment "Cleanup after finishing the script";
if (_isTaskAssigned) then {
    [_currentTaskName, "CANCELED"] call BIS_fnc_taskSetState;
};
    
};	

 

 

Basic usage

 

  1. Put the script in a trigger ("on activation" field).
  2. Set condition to true.
  3. Name the player group's variable name "playerGroup".

 

Tweaking the script
 

Spoiler

Spawn control variables

 

  • _fnc_center: function that returns the object or the position which will be the center of ambient combat. By default it's leader playerGroup. This is convenient for multiplayer.
  • _fnc_IfTrueStopScript: function that will stop the script if true. For example if you need to stop the script when leader of a playerGroup reaches the trigger (named "ambStopTrigger"), change "false;" to "(leader playerGroup) inArea ambStopTrigger;"
  • _fnc_IfTrueDontSpawn: function that will prevent any groups from spawning while it returns true.

 

  • _maxDistance: maximum distance of spawn.
  • _minDistance: minimum distance of spawn.
  • _despawnDistance: alive groups spawned by script will despawn if further, unless a plane is a part of the group.
  • _sleepTime: time between group generation, in seconds.
  • _limit: max number of groups generated by script at any given time.
  • _patrolDistance: size of patrol area for each group.
  • _deadBodyDespawnDistance: all dead units spawned by script will despawn if further.
  • _defaultPlaneHeight: default height for spawning planes.
  • _defaultPlaneSpeed: default speed for planes, in m/s.
  • _planeDespawnDistance: alive groups spawned by script will despawn if further, even if a plane is a part of the group.
  • _zeusableSides: array of sides (can be west, east, resistance, civilian) that will show up in Zeus.
  • _forceZeusForget: for an unknown reason sometimes Zeus shows all sides instead of just _zeusableSides. Change this variable to "true" to force Zeus to ignore un-zeusable units.
  • _notifyOnScriptStop: notify in chat when script stops working.
  • _isMccEnabled: if true, will assign all units to move within MCC Zone #1 instead of assigning a default patrol task. Transferring groups to MCC will enable MCC smart task planning for them. If the zone #1 is not created at the time of group spawn, the group will be spawned with no tasks. You can create an MCC zone in editor by adding the "MCC Zones" module to map and sync it to a trigger that covers the zone of interest.
  • _sleepBeforeStart: sleep before starting the script. Use if your group respawns at the beginning of the mission in order to prevent the tasks being generated around [0,0].
  • _spawnOutOfSight: only spawn the units out of sight of a unit that is returned by _fnc_center function.
  • _despawnOutOfSight: only despawn the units out of sight of a unit that is returned by _fnc_center function.

 

  • _armoredWeight: chance of armored/motorized/mechanized groups spawning, relative to chance of infantry groups spawning. For example, _armoredWeight=0.1 means that armored groups will be spawned 10 times less likely than infantry.
  • _airWeight: relative chance of air groups spawning.
  • _droneWeight: relative chance of drones spawning.
  • _mortarWeight: relative chance of mortars spawning.

 

 

  • _eastWeight, _westWeight, _guerWeight: ratio of sides spawning.

 

Unit control variables

 

The units and groups that will be spawned by the script are described in arrays: _east_infantry, _east_armored, _east_air, _east_drones, _east_mortars, _west_infantry, _west_armored, _west_air, _west_drones, _west_mortars, _guer_infantry, _guer_armored, _guer_air, _guer_drones, _guer_mortars.

 

Each element of these arrays might be:

  • a Config entry of one of the two possible categories: CfgVehicles or CfgGroups.
  • a String representing a CfgVehicles class name.
  • an array that contains any of the above.

 

Task control variables

 

  • _totalTasks: total amount of tasks that will be consecutively generated by the script. 0 (off) by default.
  • _tasksWillMissionEnd: if true, script will end the mission after completing all the tasks.
  • _reconUpdateTime: how often will task position update, in seconds.
  • _reconAccuracyPosition: how accurate is task marker position.
  • _reconCountInaccuracy: how inaccurately the units in the target group will be counted. The number represents how far off minimum and maximum estimated count might be from the true number.
  • _tasksTargetSides: array of sides that will be set up for elimination.
  • _taskReceivingGroup: side/group/object/array that will receive the tasks.
  • _taskMinGroups: how many suitable groups should be present before new task will be assigned. By default 3.

 

Armed civilians

To make the script spawn unit with a custom weapon added, add "##armed" to the end of its class name (it works ONLY with units defined as class name strings, and will NOT work with units or groups defined by config entries!). For example, an armed civilian could be referenced as "C_man_polo_1_F##armed". By default, he will be armed with a pistol and 2 magazines.

The following variables control ##armed logic:

 

  • _armedOptions: an array of elements, each of which is an array of two strings: [GunClassName, MagazineClassName].
  • _armedWeights: an array of numbers representing relative frequency of the choice of arms. Should have number of elements equal to _armedOptions.
  • _armedMagazines: a number that represents how many magazines will be added to the unit's uniform.

 

Adding sides

 

All sides are listed in _unitSides as an array of entries that look like this: [side, [side_infantry, side_armored, ...etc]]. All sides should have the same amount of unit arrays. By default the script expects 5 unit arrays: infantry, armored, air, drones, mortars. So if you want a civillian side, you should either populate 5 arrays with something, or use a different copy of the script with different unit arrays.

Also you have to redefine _unitSideWeights: each entry of this array represent a relative weight for a side. _unitSides and _unitSideWeights must be the same size.

 

Known errors with spawn

 

  • If you see "Could not create a unit: wrong specification" in game chat it means that a group did not spawn. The script will provide what specification was wrong.
  • If you see "Group is not returned to the script." it is an undetermined problem with spawning (a group did not spawn). _fnc_spawnUnitAtPos should return a group, but in this case it returned nothing. Look at your changes to the script carefully.

 

Known errors (features) with tasks

 

  • Active battlefield might eliminate your targets before you have a chance to reach them, especially if you are surrounded and stuck for some time. Consider this a feature.
  • Tasks are randomly placed. They may get you travelling back and forth. That is actually a good thing, since it despawns some forces, making room for new situations.

 

Other stuff about the script

 

  • If you redefine _unitSideWeights each iteration of the loop, you can change the power balance of the ambient combat with time. You can script it with relation to distance to the objects or just increment one side weight constantly, making the enemy stronger as time goes.
  • If you want to have several copies of the script, make sure these copies have different strings for _scriptControlVariable, _reconMarkerName, _taskPrefix.

 

This script is licensed by Arma APL. Feel free to improve it.

Edited by mr555ru
Release 1.4
  • Thanks 1

Share this post


Link to post
Share on other sites

My plan for this script will be to add random elimination tasks, which will make this script into a very simple mission generator. Could anyone help me with this problem: how to elegantly count group composition, ignoring crew but including vehicles (return 2 numbers: group consists of X infantry and Y vehicles)?

Share this post


Link to post
Share on other sites

This version of the script sets random tasks to destroy random spawned groups. By default script generates ambient combat around leader playerGroup. This is convenient for multiplayer with respawns.

 

Spoiler

if NOT(isServer) exitWith {};

[] spawn 
{

_maxDistance = 700;
_minDistance = 250;
_despawnDistance = 1200;
_sleepTime = 20;
_limit = 30;
_patrolDistance = 300;
_deadBodyDespawnDistance = 300;

_armoredWeight = 0.1;
_airWeight = 0.08;
_droneWeight = 0.08;
_mortarWeight = 0.02;

_eastWeight = 1;
_westWeight = 1;


_sleepBeforeStart = 0;
_totalTasks = 5;
_tasksWillMissionEnd = true;
_reconUpdateEvery = 3;
_reconAccuracyPosition = 60;
_tasksTargetSides = [east];
_taskReceivingGroup = west;
_taskMinGroups = 3;


_currentTaskName = "";
_isTaskAssigned = false;
_targetGroup = 0;
_taskCircleMarker = 0;
_reconUpdVar = 0;


_east_infantry = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_AA"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_AT"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_EMR"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Infantry" >> "CUP_O_RU_InfSection_MG")];

_east_armored = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Mechanized" >> "CUP_O_RU_MechInfSquad_2"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Motorized" >> "CUP_O_RU_MotInfSquad"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Armored" >> "CUP_O_RU_TankPlatoon"),
(configfile >> "CfgVehicles" >> "CUP_O_2S6_RU")];

_east_air = [(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Air" >> "CUP_O_RU_Mi24PSquadron"),
(configfile >> "CfgGroups" >> "East" >> "CUP_O_RU" >> "Air" >> "CUP_O_RU_Mi8Squadron")];

_west_infantry = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_HeavyATTeam"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_RifleSquad"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_TeamAT"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Infantry" >> "CUP_B_US_Army_WeaponsSquad")];

_west_armored = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedInfantrySquadICVM2"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedInfantrySquadICVMK19"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Mechanized" >> "CUP_B_US_Army_MechanizedReconSection"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Motorized" >> "CUP_B_US_Army_MotorizedSectionAT"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Motorized" >> "CUP_B_US_Army_MotorizedSection"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Armored" >> "CUP_B_US_Army_M1A1Platoon"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Armored" >> "CUP_B_US_Army_MGSPlatoon"),
(configfile >> "CfgVehicles" >> "CUP_B_HMMWV_Avenger_USA")];

_west_air = [(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Air" >> "CUP_B_US_Army_AH64DFlight"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_US_Army" >> "Air" >> "CUP_B_US_Army_CH47FFlight"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_USMC" >> "Air" >> "CUP_B_USMC_UH1YSquadron"),
(configfile >> "CfgGroups" >> "West" >> "CUP_B_USMC" >> "Air" >> "CUP_B_USMC_MV22Squadron")];

_west_drones = [(configfile >> "CfgVehicles" >> "B_UAV_01_F")];
_east_drones = [(configfile >> "CfgVehicles" >> "O_UAV_01_F")];

_east_mortars = [(configfile >> "CfgVehicles" >> "O_Mortar_01_F")];
_west_mortars = [(configfile >> "CfgVehicles" >> "CUP_B_M252_US")];

_unitSides = [[east, [_east_infantry, _east_armored, _east_air, _east_drones, _east_mortars]],
[west, [_west_infantry, _west_armored, _west_air, _west_drones, _west_mortars]]];

_unitSideWeights = [_eastWeight, _westWeight];
_unitTypeWeights = [1, _armoredWeight, _airWeight, _droneWeight, _mortarWeight];

sleep _sleepBeforeStart;
systemChat "Ambient combat & tasks routines are starting";

while {true} do
    {
    if ((count (allGroups select {(_x getVariable ["ALP_fnc_RandomlySpawned",false])})) < _limit) then {
        _pos = [leader playerGroup, _minDistance, _maxDistance, 3, 0, 20, 0] call BIS_fnc_findSafePos;
        _unitSide = _unitSides selectRandomWeighted _unitSideWeights;
        _unitType = (_unitSide select 1) selectRandomWeighted _unitTypeWeights;
        _unit = selectRandom _unitType;
        _grp = if ((configfile >> "CfgGroups") in configHierarchy _unit) then {
            _a = [_pos, (_unitSide select 0), _unit] call BIS_fnc_spawnGroup;
            _a;
        }
        else {
            if ((configfile >> "CfgVehicles") in configHierarchy _unit) then {
                _name = configName _unit;
                _x = [_pos, random 360, _name, (_unitSide select 0)] call bis_fnc_spawnvehicle;
                _x select 2;
            };
        };
        if (isNil "_grp") then {
            systemChat format ["_grp is nil at %1. This entry should be a part of CfgGroups or CfgVehicles!", _unit];
        }
        else {
            _grp setVariable ["ALP_fnc_RandomlySpawned", true];
            {_x setVariable ["ALP_fnc_RandomlySpawned", true]} forEach units _grp;
            _grp deleteGroupWhenEmpty true;
            [_grp, position leader _grp, _patrolDistance] call bis_fnc_taskpatrol;
            {_x addCuratorEditableObjects [units _grp, true]} forEach allCurators;
        };
    };
    {
        if (((leader _x) distance (leader playerGroup)) > _despawnDistance) then {
            _grp = _x;
            {
                if (vehicle _x != _x) then {
                    deleteVehicle (vehicle _x);
                };
                deleteVehicle _x;
            } forEach units _grp;
            deleteGroup _grp;
        };
    } forEach (allGroups select {(_x getVariable ["ALP_fnc_RandomlySpawned",false])});
    {
        if ((((_x) distance (leader playerGroup)) > _deadBodyDespawnDistance)) then {
            deleteVehicle _x;
        };
    } forEach (allDead select {(_x getVariable ["ALP_fnc_RandomlySpawned",false])});
    
    if (!_isTaskAssigned AND (_totalTasks > 0) AND ({(_x getVariable ["ALP_fnc_RandomlySpawned",false]) AND (side _x in _tasksTargetSides)} count allGroups  >= _taskMinGroups)) then {
        _targetGroup = selectRandom (allGroups select {(_x getVariable ["ALP_fnc_RandomlySpawned",false]) AND side _x in _tasksTargetSides});
        _targetGroup setVariable ["ALP_fnc_RandomlySpawned", false];
        _reconPos = [[[getPos leader _targetGroup, _reconAccuracyPosition]]] call BIS_fnc_RandomPos;
        _vehArray = [];
        _unitCnt = 0;
        {
            if (vehicle _x != _x) then {
                _vehArray pushBackUnique (vehicle _x);
            } else {
                _unitCnt = _unitCnt + 1;
            }
        } forEach units _targetGroup;
        _taskString = format ["Eliminate the enemy (%1 infantry, %2 vehicles)", _unitCnt, count _vehArray];
        _currentTaskName = format ["ALPtsk%1", _totalTasks];
        
        _taskCircleMarker = createMarker ["ReconCircle", _reconPos];
        _taskCircleMarker setMarkerShape "ELLIPSE";
        _taskCircleMarker setMarkerSize [_reconAccuracyPosition, _reconAccuracyPosition];
        _taskCircleMarker setMarkerBrush "Border";
        _taskCircleMarker setMarkerColor "ColorRed";
        _taskCircleMarker setMarkerPos _reconPos;
        
        [_taskReceivingGroup, _currentTaskName, ["", _taskString, "ReconCircle"], _reconPos, true, 0, true, "Attack", true] call BIS_fnc_taskCreate;
        _isTaskAssigned = true;
        _reconUpdVar = 0;
    } else {
        if (_isTaskAssigned) then {
            _reconUpdVar = round ((_reconUpdVar+1)%_reconUpdateEvery);
            if (_reconUpdVar == _reconUpdateEvery-1) then {
                _reconPos = [[[getPos leader _targetGroup, _reconAccuracyPosition]]] call BIS_fnc_RandomPos;
                [_currentTaskName, _reconPos] call BIS_fnc_taskSetDestination;
                _taskCircleMarker setMarkerPos _reconPos;
            };
            if ({alive _x} count (units _targetGroup) == 0) then {
                    [_currentTaskName, "SUCCEEDED"] call BIS_fnc_taskSetState;
                    deleteMarker "ReconCircle";
                    _isTaskAssigned = false;
                    _targetGroup = 0;
                    _totalTasks = _totalTasks - 1;
                    if (_totalTasks == 0 AND _tasksWillMissionEnd) then {
                        "end1" call BIS_fnc_endMission;
                    };
                };
        };
    };
    
	sleep _sleepTime;
	}
    
};	

 

 

 

Edited by mr555ru
All options are now described in the first post

Share this post


Link to post
Share on other sites

Updated the script. Planes work now! All relevant info is now here, not on steam. The script has been made easier to tweak, because I got my hands on learning functions.

Share this post


Link to post
Share on other sites
10 hours ago, baton1990 said:

How can I make this script stop working returning to base for example ?

Inside "while" loop, add a condition check, that, if true, sets variable _limit to 0. It will not spawn any more groups.
If you want to despawn all groups generated by script, you can set variables _despawnDistance, _planeDespawnDistance to 0.

 

Another way to totally stop the script once and for all, is to change condition for the while statement. Right now it's while {true} which means that it's an infinite loop. You can change the condition so the loop can end. In this case, nothing more will be despawned, and any unfinished tasks set by the script would never complete. If you don't use the task system, it will be fine, though.

Share this post


Link to post
Share on other sites

Hello mr555ru,

 

first of all, thanks for your work. Although there are several mods/scripts focused in a similar way, yours is the only one that seems to work fine in multiplayer and with custom factions. I´m terrible with scripting (sometimes I try but as I really don´t understand it, rarely works) so could you please put the complete stop working script? I guess that it would be added in a trigger with an area (applied in an airport base for example)?

 

Also I´d like to know what I have to put to introduce a third faction (independent), to make them fight against west and east sides.

 

Here I leave other suggestions that I think that will make it even more enjoyable:

 

- AI can call air strikes and artillery support (HE rounds, smoke and rockets).

 

- a variation with Zeus limited to the playable faction, so it is no available  the option to pick/move enemy units.

 

Cheers!

Share this post


Link to post
Share on other sites

I left ArmA for a while, but had the almost-working new version of the script on my hands. The main feature - fully customized teams to spawn - is just too good to not share.

I also addressed some suggestions:

On 12/5/2018 at 6:34 PM, AveMetal said:

I´m terrible with scripting (sometimes I try but as I really don´t understand it, rarely works) so could you please put the complete stop working script? I guess that it would be added in a trigger with an area (applied in an airport base for example)?

I tried to make it easier to do that. An example on how to do that is now available in "Tweaking the Script" section.

On 12/5/2018 at 6:34 PM, AveMetal said:

- a variation with Zeus limited to the playable faction, so it is no available  the option to pick/move enemy units.

Made as the default option. It might not work from the box - I don't know the reason for that. But if it doesn't work and you need it, you can try to turn _forceZeusForget on.

 

Be advised that some of the default settings were changed:

  • By default only west units should show up in Zeus.
  • Task module is not active by default.
  • All three sides - east, west, resistance - will spawn, instead of "east vs west" as before.

 

It's not likely that I will continue working on this script in the near future, but I believe its current state covers almost all needs.

  • Thanks 1

Share this post


Link to post
Share on other sites

I decided to improve the script despite warning that I discontinued it. Here, some new stuff:

 

  • Script now uses vanilla units. The CUP units from the previous version are still preserved in the first post, in case you need them.
  • Script now should correctly despawn empty vehicles. (Not fully tested, if you encounter this bug with the new version of the script, DM me).
  • Tasks module now has some inaccuracy in counting enemy units. Instead of saying "Enemy group has 4 infantry units" it will now say something like "2-6 units", making tasks less predictable. The inaccuracy is customizable in settings (_reconCountInaccuracy parameter).
  • Script now runs every second - which gets rid of some bugs with condition testing.
  • Script now supports arming unarmed units - e.g. for the "armed civilians" scenario.
  • Fixed a bug with mission end in MP - script correctly uses BIS_fnc_endMissionServer now.
  • [Experimental feature] Script now has an option to spawn units only out of sight. Only one player's sight is supported (the one that is returned by the _fnc_center) and it is not 100% guarantee in some cases - if you spawn groups close to the player, due to the sizes of groups some units might still spawn in sight (only group leader's position is expected to be out of sight). This feature is disabled by default.

Although I don't currently have a "to do list" for this script, I might look forward to bringing in some more stuff. Also I'm working on a simple "random tasks" script that works in a similar (trigger-placed) way.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×