diff --git a/addons/common/script_component.hpp b/addons/common/script_component.hpp index 7fa6315f..92bd454b 100644 --- a/addons/common/script_component.hpp +++ b/addons/common/script_component.hpp @@ -2,7 +2,7 @@ #define COMPONENT_BEAUTIFIED Common #include "\u\uksf\addons\main\script_mod.hpp" -// #define DEBUG_MODE_FULL +#define DEBUG_MODE_FULL // #define DISABLE_COMPILE_CACHE // #define CBA_DEBUG_SYNCHRONOUS diff --git a/addons/populate/$PBOPREFIX$ b/addons/populate/$PBOPREFIX$ new file mode 100644 index 00000000..0c2d1a1b --- /dev/null +++ b/addons/populate/$PBOPREFIX$ @@ -0,0 +1 @@ +u\uksf\addons\populate diff --git a/addons/populate/CfgEventHandlers.hpp b/addons/populate/CfgEventHandlers.hpp new file mode 100644 index 00000000..865276cf --- /dev/null +++ b/addons/populate/CfgEventHandlers.hpp @@ -0,0 +1,11 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); + }; +}; + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preInit)); + }; +}; diff --git a/addons/populate/CfgFactionClasses.hpp b/addons/populate/CfgFactionClasses.hpp new file mode 100644 index 00000000..7a1e764f --- /dev/null +++ b/addons/populate/CfgFactionClasses.hpp @@ -0,0 +1,6 @@ +class CfgFactionClasses { + class EGVAR(common,eden); + class ADDON: EGVAR(common,eden){ + displayName = "Auto Populate Area"; + }; +}; diff --git a/addons/populate/CfgVehicles.hpp b/addons/populate/CfgVehicles.hpp new file mode 100644 index 00000000..6c372d20 --- /dev/null +++ b/addons/populate/CfgVehicles.hpp @@ -0,0 +1,102 @@ +class CfgVehicles { + class Module_F; + class GVAR(module) : Module_F { + scope = 1; + is3DEN = 1; + functionPriority = 1; + category = ADDON; + class AttributesBase; + }; + class GVAR(populateAreaModule) : GVAR(module) { + scope = 2; + displayName = "Auto Populate)"; + icon = "A3\ui_f\data\map\markers\nato\o_inf.paa"; + portrait = "A3\ui_f\data\map\markers\nato\o_inf.paa"; + function = QFUNC(modulePopulateArea); + canSetArea = 1; + canSetAreaHeight = 0; + canSetAreaShape = 1; + class AttributeValues { + size3[] = { 200, 200, -1 }; + isRectangle = 1; + }; + class Attributes : AttributesBase { + class GVAR(numberOfUnits) { + property = QGVAR(numberOfUnits); + displayName = "Number of Units"; + tooltip = "The number of units to spawn"; + control = "EditShort"; + validate = "NUMBER"; + defaultValue = 30; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(numberOfUnits),_value,true)]); + }; + class GVAR(patrolRadius) { + property = QGVAR(patrolRadius); + displayName = "Patrol Radius"; + tooltip = "The radius any left over units will patrol around the module location. Used for when positions to occupy isn't 100%"; + control = "EditShort"; + validate = "NUMBER"; + defaultValue = 50; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(patrolRadius),_value,true)]); + }; + class GVAR(patrolSize) { + property = QGVAR(patrolSize); + displayName = "Patrol Size"; + tooltip = "The number of units in each patrol. Patrols occur once all building positions are filled."; + control = "EditShort"; + validate = "NUMBER"; + defaultValue = 6; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(patrolSize),_value,true)]); + }; + class GVAR(unitPoolString) { + property = QGVAR(unitPoolString); + displayName = "Unit Pool"; + tooltip = "Class names of units to spawn for counter-mortar groups. Comma-separated list of class names in single quotes, no spaces"; + control = "Edit"; + defaultValue = "[]"; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(unitPoolString),_value,true)]); + }; + class GVAR(occupyStaticGunsBool) { + property = QGVAR(occupyStaticGunsBool); + displayName = "Occupy Static Weapons"; + tooltip = "Should units man placed static weapons"; + control = "CheckBox"; + typeName = "BOOL"; + defaultValue = "(false)"; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(occupyStaticGunsBool),_value,true)]); + }; + class GVAR(percentageOfPositionsToOccupy) { + property = QGVAR(percentageOfPositionsToOccupy); + displayName = "Percentage of Positions to Occupy"; + tooltip = "What percentage of the total positions will be occupied - low % may result in units being spread out"; + control = "EditShort"; + validate = "NUMBER"; + defaultValue = 30; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(percentageOfPositionsToOccupy),_value,true)]); + }; + class GVAR(side) { + property = QGVAR(side); + displayName = "Side"; + tooltip = "Side of spawned units"; + control = "Combo"; + expression = QUOTE(_this setVariable [ARR_3(QQGVAR(side),_value,true)]); + typeName = "NUMBER"; + defaultValue = 0; + class values { + class East { + name = "OPFOR"; + value = 0; + }; + class Guer { + name = "INDEPENDENT"; + value = 1; + }; + class West { + name = "BLUFOR"; + value = 2; + }; + }; + }; + }; + }; +}; diff --git a/addons/populate/README.md b/addons/populate/README.md new file mode 100644 index 00000000..72dcbe05 --- /dev/null +++ b/addons/populate/README.md @@ -0,0 +1,5 @@ +# Auto Populate + +Takes all building positions and AI Building Positions and populates them with units +If the number of AI to spawn is more than 10, group sizes will be 10 +Runs once at mission start diff --git a/addons/populate/XEH_PREP.hpp b/addons/populate/XEH_PREP.hpp new file mode 100644 index 00000000..f56af87f --- /dev/null +++ b/addons/populate/XEH_PREP.hpp @@ -0,0 +1,7 @@ +PREP(createPatrols); +PREP(getValidPositions); +PREP(getValidStatics); +PREP(modulePopulateArea); +PREP(selectSpawnPosition); +PREP(populateBuildingPositions); +PREP(populateStatics); diff --git a/addons/populate/XEH_preInit.sqf b/addons/populate/XEH_preInit.sqf new file mode 100644 index 00000000..da6f4101 --- /dev/null +++ b/addons/populate/XEH_preInit.sqf @@ -0,0 +1,11 @@ +#include "script_component.hpp" + +ADDON = false; + +#include "XEH_PREP.hpp" + +// #include "initSettings.sqf" + +GVAR(groupSize) = 10; + +ADDON = true; diff --git a/addons/populate/XEH_preStart.sqf b/addons/populate/XEH_preStart.sqf new file mode 100644 index 00000000..02288857 --- /dev/null +++ b/addons/populate/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/populate/config.cpp b/addons/populate/config.cpp new file mode 100644 index 00000000..b05957b1 --- /dev/null +++ b/addons/populate/config.cpp @@ -0,0 +1,24 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = { + QGVAR(populateAreaModule) + }; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { + "uksf_mission" + }; + author = QUOTE(UKSF); + authors[] = { "Bridgford.A" }; + url = URL; + VERSION_CONFIG; + }; +}; + +// #include "Cfg3den.hpp" +#include "CfgEventHandlers.hpp" +#include "CfgFactionClasses.hpp" +#include "CfgVehicles.hpp" diff --git a/addons/populate/functions/fnc_createPatrols.sqf b/addons/populate/functions/fnc_createPatrols.sqf new file mode 100644 index 00000000..99fbaa58 --- /dev/null +++ b/addons/populate/functions/fnc_createPatrols.sqf @@ -0,0 +1,59 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Spawns a unit at the passed position + + Parameters: + 0: _numberOfUnitsToSpawn + 1: _module + 2: _group + + Return value: + Nothing +*/ + +params ["_numberOfUnitsToSpawn", "_side", "_module", "_unitPoolArray"]; + +private _group = grpNull; +private _currenGrouptUnitCount = 0; +private _patrolSize = _module getVariable [QGVAR(patrolSize), 0]; +private _patrolRadius = _module getVariable [QGVAR(patrolRadius), 0]; + +[{ + params ["_args", "_idPFH"]; + _args params ["_numberOfUnitsToSpawn", "_side", "_module", "_unitPoolArray", "_currenGrouptUnitCount", "_patrolRadius", "_group", "_patrolSize"]; + + if (_numberOfUnitsToSpawn <= 0) exitWith { + [_idPFH] call cba_fnc_removePerFrameHandler; + [QEGVAR(virtualisation,include), _group] call CBA_fnc_serverEvent; + }; + + // create a group if the _currenGrouptUnitCount is == 0, set previous group to patrol + if (_currenGrouptUnitCount == 0) then { + _group = createGroup _side; + [QEGVAR(virtualisation,exclude), _group] call CBA_fnc_serverEvent; + }; + + private _unitType = selectRandom _unitPoolArray; + private _unit = _group createUnit [_unitType, [0,0,0], [], 0, "NONE"]; + _unit setPos (getPos _module); + + _currenGrouptUnitCount = _currenGrouptUnitCount + 1; + _numberOfUnitsToSpawn = _numberOfUnitsToSpawn - 1; + if (_currenGrouptUnitCount == _patrolSize) then { + [_group, _group, _patrolRadius, 6] call lambs_wp_fnc_taskPatrol; // infantry only + _currenGrouptUnitCount = 0; + }; + + _args set [0, _numberOfUnitsToSpawn]; + _args set [4, _currenGrouptUnitCount]; + _args set [6, _group]; + +}, 1, [_numberOfUnitsToSpawn, _side, _module, _unitPoolArray, _currenGrouptUnitCount, _patrolRadius, _group, _patrolSize]] call cba_fnc_addPerFrameHandler; + +// TODO: exclude virtualization until the group is spawned, then set to true + + diff --git a/addons/populate/functions/fnc_getValidPositions.sqf b/addons/populate/functions/fnc_getValidPositions.sqf new file mode 100644 index 00000000..37b49e7b --- /dev/null +++ b/addons/populate/functions/fnc_getValidPositions.sqf @@ -0,0 +1,62 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Gets any valid building positions AND AI Building Positions in the area + + Parameters: + 0: _module + + Return value: + Nothing +*/ +params ["_module"]; + +if !(isServer) exitWith {}; + +private _statics = []; + +// get the area +private _areaParams = _module getVariable ["objectarea", []]; +private _area = [getPos _module] + _areaParams; +if (_area isEqualTo []) exitWith {}; + +_area params ["", "_a", "_b"]; + +// get which dimension is largest to use as radius +private _radius = [_b, _a] select (_a > _b); + +// get all buildings in radius then in area +private _allBuildingsInRadius = nearestTerrainObjects [_module, ["BUILDING", "HOUSE", "BUNKER"], _radius, false, true]; +private _allBuildingsInArea = _allBuildingsInRadius select {_x inArea _area}; + +// get the building positions for the buildings +private _buildingPositions = []; +{ + private _building = _x; + private _buildingPositionsArray = _building buildingPos -1; + { + private _buildingPosition = _x; + _buildingPositions pushBack _buildingPosition; + } forEach _buildingPositionsArray; +} forEach _allBuildingsInArea; + +// get all ai buildings in the area +private _aiBuildingPositionsInArea = (_module nearObjects ["CBA_BuildingPos", _radius]) select {_x inArea _area}; + +// get statics in the area +private _occupyStatics = _module getVariable [QGVAR(occupyStaticGunsBool), false]; +if (_occupyStatics) then { + _statics = [_module] call FUNC(getValidStatics); +}; + +// append building positions and ai building positions +private _spawnPositions = _buildingPositions + _aiBuildingPositionsInArea; + +if (_spawnPositions isEqualTo [] && _statics isEqualTo []) exitWith {}; + +// call out to select position function +[_spawnPositions, _statics, _module] call FUNC(selectSpawnPosition); + diff --git a/addons/populate/functions/fnc_getValidStatics.sqf b/addons/populate/functions/fnc_getValidStatics.sqf new file mode 100644 index 00000000..8ff59ca4 --- /dev/null +++ b/addons/populate/functions/fnc_getValidStatics.sqf @@ -0,0 +1,36 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Gets any valid static guns in the area + + Parameters: + 0: _module + + Return value: + _statics +*/ +params ["_module"]; + +if !(isServer) exitWith {}; + +// get the area +private _areaParams = _module getVariable ["objectarea", []]; +private _area = [getPos _module] + _areaParams; +if (_area isEqualTo []) exitWith {}; + +_area params ["", "_a", "_b"]; + +// get which dimension is largest to use as radius +private _radius = [_b, _a] select (_a > _b); + +// get all statics in the area +private _statics = []; +private _staticsInArea = (_module nearEntities [["StaticWeapon"], _radius]) select {_x inArea _area && (_x emptyPositions "" > 0)}; +{ + _statics pushBack _x; +} forEach _staticsInArea; + +_statics diff --git a/addons/populate/functions/fnc_modulePopulateArea.sqf b/addons/populate/functions/fnc_modulePopulateArea.sqf new file mode 100644 index 00000000..185afe9a --- /dev/null +++ b/addons/populate/functions/fnc_modulePopulateArea.sqf @@ -0,0 +1,20 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Sets the settings from the module up as global vars + + Parameters: + 0: The module object + + Return value: + Nothing +*/ + +(_this#1) params ["_module"]; + +if (!isServer) exitWith {}; + +[_module] call FUNC(getValidPositions); diff --git a/addons/populate/functions/fnc_populateBuildingPositions.sqf b/addons/populate/functions/fnc_populateBuildingPositions.sqf new file mode 100644 index 00000000..786e7551 --- /dev/null +++ b/addons/populate/functions/fnc_populateBuildingPositions.sqf @@ -0,0 +1,70 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Sets the settings from the module up as global vars + + Parameters: + 0: The module object + + Return value: + Nothing +*/ + +params ["_spawnPositions", "_numberOfPositionsToOccupy", "_side", "_unitPoolArray", "_numberOfUnitsToSpawn"]; + +private _updatedNumberOfUnitsToSpawn = _numberOfUnitsToSpawn; +private _group = grpNull; +private _currenGrouptUnitCount = 0; + + +[{ + params ["_args", "_idPFH"]; + _args params ["_spawnPositions", "_numberOfPositionsToOccupy", "_side", "_unitPoolArray", "_updatedNumberOfUnitsToSpawn", "_currenGrouptUnitCount", "_group"]; + + if (_numberOfPositionsToOccupy <= 1) exitWith { + [_idPFH] call cba_fnc_removePerFrameHandler; + [QEGVAR(virtualisation,include), _group] call CBA_fnc_serverEvent; + _updatedNumberOfUnitsToSpawn + }; + + // create a group if the _currenGrouptUnitCount is == 0 + if (_currenGrouptUnitCount isEqualTo 0) then { + _group = createGroup _side; + [QEGVAR(virtualisation,exclude), _group] call CBA_fnc_serverEvent; + }; + + private _unitType = selectRandom _unitPoolArray; + private _unit = _group createUnit [_unitType, [0,0,0], [], 0, "NONE"]; + _currenGrouptUnitCount = _currenGrouptUnitCount + 1; + + private _pos = selectRandom _spawnPositions; + if (_pos isEqualType []) then { + _unit setPos _pos; + } else { + _unit setPos (getPos _pos); + }; + + _spawnPositions deleteAt (_spawnPositions find _pos); + + // TRACE_4("", _pos, _dir, typeName _spawnPos, _spawnPos); + + _numberOfPositionsToOccupy = _numberOfPositionsToOccupy - 1; + _updatedNumberOfUnitsToSpawn = _updatedNumberOfUnitsToSpawn - 1; + + _unit disableAI "PATH"; + + if (_currenGrouptUnitCount == 10) then { + _currenGrouptUnitCount = 0; + }; + + _args set [0, _spawnPositions]; + _args set [1, _numberOfPositionsToOccupy]; + _args set [4, _updatedNumberOfUnitsToSpawn]; + _args set [5, _currenGrouptUnitCount]; + _args set [6, _group]; + +}, 1, [_spawnPositions, _numberOfPositionsToOccupy, _side, _unitPoolArray, _updatedNumberOfUnitsToSpawn, _currenGrouptUnitCount, _group]] call cba_fnc_addPerFrameHandler; + diff --git a/addons/populate/functions/fnc_populateStatics.sqf b/addons/populate/functions/fnc_populateStatics.sqf new file mode 100644 index 00000000..29175df6 --- /dev/null +++ b/addons/populate/functions/fnc_populateStatics.sqf @@ -0,0 +1,27 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Sets the settings from the module up as global vars + + Parameters: + 0: The module object + + Return value: + Nothing +*/ + +params ["_statics", "_side", "_unitPoolArray", "_numberOfUnitsToSpawn"]; + +private _group = createGroup _side; +private _updatedNumberOfUnitsToSpawn = _numberOfUnitsToSpawn; + +{ + private _unit = _group createUnit [selectRandom _unitPoolArray, [0, 0, 0], [], 0, "NONE"]; + _unit moveInGunner _x; + _updatedNumberOfUnitsToSpawn - 1; +} forEach _statics; + +_updatedNumberOfUnitsToSpawn diff --git a/addons/populate/functions/fnc_selectSpawnPosition.sqf b/addons/populate/functions/fnc_selectSpawnPosition.sqf new file mode 100644 index 00000000..8b0837e2 --- /dev/null +++ b/addons/populate/functions/fnc_selectSpawnPosition.sqf @@ -0,0 +1,69 @@ +#include "script_component.hpp" +/* + Author: + Bridg + + Description: + Selects a position from the list of the positions passed + calls the spawn unit function for those positions + _currenGrouptUnitCount is checked to create a group every 10 units + _numberOfUnitsToSpawn is checked to make sure the number of units defined is spawned + + + Parameters: + 0: _spawnPositions + 1: _statics + 2: _module + + Return value: + Nothing +*/ + +params ["_spawnPositions", "_statics", "_module"]; + +if (!isServer) exitWith {}; + +private _fnc_getArrayFromModule = { + params ["_module", "_property"]; + + private _value = _module getVariable [_property, []]; + + if (_value isEqualType "") then { + if (_value != "") then { + _value = call compile _value; + } else { + _value = []; + }; + }; + _value +}; + +private _unitPoolArray = [_module, QGVAR(unitPoolString)] call _fnc_getArrayFromModule; +private _spawnPercentage = _module getVariable [QGVAR(percentageOfPositionsToOccupy), 0]; +private _numberOfPositionsToOccupy = round((count _spawnPositions) * (_spawnPercentage / 100)); +private _numberOfUnitsToSpawn = _module getVariable [QGVAR(numberOfUnits), 0]; +private _side = _module getVariable [QGVAR(side), 0]; + + +if (_side isEqualTo 0) then { + _side = east; +}; + +if (_side isEqualTo 1) then { + _side = independent; +}; + +if (_side isEqualTo 2) then { + _side = west; +}; + +// populate statics +_numberOfUnitsToSpawn = [_statics, _side, _unitPoolArray, _numberOfUnitsToSpawn] call FUNC(populateStatics); + +// populate ai building positions and building positions +_numberOfUnitsToSpawn = [_spawnPositions, _numberOfPositionsToOccupy, _side, _unitPoolArray, _numberOfUnitsToSpawn] call FUNC(populateBuildingPositions); + +// handle patrols +// if (_numberOfUnitsToSpawn > 0) then { +// [_numberOfUnitsToSpawn, _side, _module, _unitPoolArray] call FUNC(createPatrols); +// ;} diff --git a/addons/populate/functions/script_component.hpp b/addons/populate/functions/script_component.hpp new file mode 100644 index 00000000..1b703f35 --- /dev/null +++ b/addons/populate/functions/script_component.hpp @@ -0,0 +1 @@ +#include "\u\uksf\addons\populate\script_component.hpp" diff --git a/addons/populate/script_component.hpp b/addons/populate/script_component.hpp new file mode 100644 index 00000000..9cc9d1ed --- /dev/null +++ b/addons/populate/script_component.hpp @@ -0,0 +1,9 @@ +#define COMPONENT populate +#define COMPONENT_BEAUTIFIED Populate +#include "\u\uksf\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define CBA_DEBUG_SYNCHRONOUS + +#include "\u\uksf\addons\main\script_macros.hpp"