From fe8c444eb9b849b98b91a1bed015f9f43e19597e Mon Sep 17 00:00:00 2001 From: "Jonathan M. Lane" Date: Wed, 31 Oct 2018 00:37:01 -0300 Subject: [PATCH 1/4] Formation deployment script as CfgORBAT property `deployment` property is a string value containing a script to be compiled and called by that formation in the parsed ORBAT. --- fn_Formation.sqf | 9 ++++++++- fn_deployForce.sqf | 45 +++++++++----------------------------------- fn_findValidPos.sqf | 10 +++++----- fn_parseCfgOrbat.sqf | 4 ++-- 4 files changed, 24 insertions(+), 44 deletions(-) diff --git a/fn_Formation.sqf b/fn_Formation.sqf index e9f69a3..11fad93 100644 --- a/fn_Formation.sqf +++ b/fn_Formation.sqf @@ -1,6 +1,7 @@ params [ ["_size", "", [""]], ["_position", [], [[0]]], + ["_deployment", "", [""]], ["_subordinates", [], [[]]] ]; @@ -8,6 +9,7 @@ private _fnc_typeCheck = { params [ ["_size", "", [""]], ["_position", [], [[0]]], + ["_deployment", "", [""]], ["_subordinates", [], [[]]] ]; @@ -22,6 +24,11 @@ private _fnc_typeCheck = { false }; + if ("_deployment" == "") exitWith { + ["'%1' is not a valid deployment value, at %2", _this select 2, _this] call BIS_fnc_error; + false + }; + if ((_subordinates apply {_x call _fnc_typeCheck}) findIf {!_x} > 1) exitWith { false }; @@ -31,4 +38,4 @@ private _fnc_typeCheck = { if (!(_this call _fnc_typeCheck)) exitWith { nil }; -[_size, _position, _subordinates] +[_size, _position, _deployment, _subordinates] diff --git a/fn_deployForce.sqf b/fn_deployForce.sqf index 4f84698..4b076b0 100644 --- a/fn_deployForce.sqf +++ b/fn_deployForce.sqf @@ -11,39 +11,16 @@ private _queue = []; params [ "_echelon", "_pos", + "_deployment", ["_children", []], ["_parent", []] ]; - private _element = [_echelon, _pos, _parent]; + private _element = [_echelon, _pos, _deployment, _parent]; _queue pushBack _element; - - { - // Set index 3 explicitly for leaf (childless) nodes - _x set [3, _element]; - } forEach _children; - - _children; + _children apply {_x set [4, _element]; _x} }] call SimTools_ForceDeployment_fnc_breadthFirstTraversal; -prepareAndPlace = { - params [ - "_echelon", - "_composition", - "_pos", - "_name", - "_killzoneRadius" - ]; - - // TODO: Figure out if MVP compositions are doing this in their inits/triggers - { _x hideObjectGlobal true } foreach nearestTerrainObjects [_pos, [], _killzoneRadius]; - - // LARs_fnc_spawnComp expects 3D ATL pos, everything else can handle 2D. - if (count _pos == 2) then { _pos pushBack 0; }; - - [_composition, _pos] call LARs_fnc_spawnComp; -}; - switchOnEchelon = { params [ "_echelon", @@ -73,7 +50,8 @@ private _pbBacklist = []; private _next = [ _x select 0, _x select 1, - _x select 2 + _x select 2, + _x select 3 ]; if (_x select 0 == "Platoon") then { _next pushBack _pbBacklist; @@ -82,12 +60,12 @@ private _pbBacklist = []; params [ "_echelon", ["_pos", [], [[0]], [0,2,3]], - ["_parent", [], [[]], [0,3]], + ["_deployment", "", [""]], + ["_parent", [], [[]]], ["_blacklist", [], [[]]] ]; private [ - "_composition", "_killzoneRadius", "_blacklistRadius", "_siblings" @@ -95,19 +73,16 @@ private _pbBacklist = []; [ _echelon, { - _composition = "FOB"; _killzoneRadius = 50; _blacklistRadius = 8000; _siblings = _fobs; }, { - _composition = "COP"; _killzoneRadius = 40; _blacklistRadius = 2000; _siblings = _cops; }, { - _composition = "PB"; _killzoneRadius = 15; _blacklistRadius = 600; _siblings = _pbs; @@ -122,7 +97,7 @@ private _pbBacklist = []; _blacklist pushBack [_x, _blacklistRadius]; } forEach _siblings; - private _newPos = [_composition, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; + private _newPos = [_echelon, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; _pos set [0, _newPos select 0]; _pos set [1, _newPos select 1]; if (count _newPos < 3) then { _pos pushBack 0; }; @@ -145,9 +120,7 @@ private _pbBacklist = []; { _pbs } ] call switchOnEchelon pushBack _pos; - // TODO: Add naming scheme - private _name = str _forEachIndex; - [_echelon, _composition, _pos, _name, _killzoneRadius] call prepareAndPlace; + [_pos, _killzoneRadius] call compileFinal _deployment; _x set [1, _pos]; _pos diff --git a/fn_findValidPos.sqf b/fn_findValidPos.sqf index 7166613..66aa8c4 100644 --- a/fn_findValidPos.sqf +++ b/fn_findValidPos.sqf @@ -1,5 +1,5 @@ params [ - "_composition", + "_echelon", ["_parent", []], ["_blacklist", []] ]; @@ -11,8 +11,8 @@ private [ ]; try { - switch (toUpper _composition) do { - case "FOB": { + switch (_echelon) do { + case "Battalion": { // Place a FOB randomly // Add 8km buffer around FOB for siblings _parent_min_radius = 0; @@ -20,7 +20,7 @@ try { _sibling_buffer_radius = 8000; _object_dist = 10; }; - case "COP": { + case "Company": { // Place a COP between 1-3km from FOB // Add 2km buffer around COP for siblings _parent_min_radius = 1000; @@ -28,7 +28,7 @@ try { _sibling_buffer_radius = 2000; _object_dist = 10; }; - case "PB": { + case "Platoon": { // Place a PB between 500-2km from COP // Add 600m buffer around PB for siblings _parent_min_radius = 500; diff --git a/fn_parseCfgOrbat.sqf b/fn_parseCfgOrbat.sqf index ab88a83..25d6247 100644 --- a/fn_parseCfgOrbat.sqf +++ b/fn_parseCfgOrbat.sqf @@ -11,11 +11,11 @@ private _fnc_traverseSubclasses = { private _subordinates = getArray (_class >> "subordinates"); if (count _subordinates < 1 && {_subordinates = _class call BIS_fnc_returnChildren; count _subordinates < 1}) exitWith { - [getText (_class >> "size"), getArray (_class >> "position")] call SimTools_ForceDeployment_fnc_Formation + [getText (_class >> "size"), getArray (_class >> "position"), getText (_class >> "deployment")] call SimTools_ForceDeployment_fnc_Formation }; _subordinates = _subordinates apply {[_x] call _fnc_traverseSubclasses}; - [getText (_class >> "size"), getArray (_class >> "position"), _subordinates] call SimTools_ForceDeployment_fnc_Formation + [getText (_class >> "size"), getArray (_class >> "position"), getText (_class >> "deployment"), _subordinates] call SimTools_ForceDeployment_fnc_Formation }; _orbats apply {[_x] call _fnc_traverseSubclasses} From 6d7f41d2828b4c2a49f9bc6c96235aa730f50033 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Lane" Date: Wed, 31 Oct 2018 00:38:27 -0300 Subject: [PATCH 2/4] Minor: fn_deployForce script clean-up --- fn_deployForce.sqf | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fn_deployForce.sqf b/fn_deployForce.sqf index 4b076b0..bc2e6d3 100644 --- a/fn_deployForce.sqf +++ b/fn_deployForce.sqf @@ -2,9 +2,8 @@ params [ ["_orbat", []] ]; -if (count _orbat < 1) exitWith { "Orbat is empty" call BIS_fnc_error; }; +if (count _orbat < 1) exitWith {["Orbat is empty"] call BIS_fnc_error}; -// [[echelon, pos, parentArrayRef], ...] private _queue = []; [_orbat, { @@ -21,7 +20,7 @@ private _queue = []; _children apply {_x set [4, _element]; _x} }] call SimTools_ForceDeployment_fnc_breadthFirstTraversal; -switchOnEchelon = { +_fnc_switchOnEchelon = { params [ "_echelon", "_BNCode", @@ -87,7 +86,7 @@ private _pbBacklist = []; _blacklistRadius = 600; _siblings = _pbs; } - ] call switchOnEchelon; + ] call _fnc_switchOnEchelon; if (count _pos < 2) then { private _parentPos = []; @@ -100,7 +99,7 @@ private _pbBacklist = []; private _newPos = [_echelon, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; _pos set [0, _newPos select 0]; _pos set [1, _newPos select 1]; - if (count _newPos < 3) then { _pos pushBack 0; }; + if (count _newPos < 3) then {_pos pushBack 0}; if (_echelon == "Company") then { private _vector = (_pos vectorFromTo _parentPos); @@ -118,7 +117,7 @@ private _pbBacklist = []; { _fobs }, { _cops }, { _pbs } - ] call switchOnEchelon pushBack _pos; + ] call _fnc_switchOnEchelon pushBack _pos; [_pos, _killzoneRadius] call compileFinal _deployment; _x set [1, _pos]; From f611ca2f84190a92ef2e344ad90921a8c551f53c Mon Sep 17 00:00:00 2001 From: "Jonathan M. Lane" Date: Wed, 31 Oct 2018 15:10:24 -0300 Subject: [PATCH 3/4] Eliminate unnecessary secondary loop over queue For some reason it didn't occur to me to just do all the main work in the first tree traversal function. This is much easier to read and saves a second pass over the queue for no reason. --- fn_deployForce.sqf | 160 ++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 90 deletions(-) diff --git a/fn_deployForce.sqf b/fn_deployForce.sqf index bc2e6d3..4f105fd 100644 --- a/fn_deployForce.sqf +++ b/fn_deployForce.sqf @@ -4,22 +4,6 @@ params [ if (count _orbat < 1) exitWith {["Orbat is empty"] call BIS_fnc_error}; -private _queue = []; - -[_orbat, { - params [ - "_echelon", - "_pos", - "_deployment", - ["_children", []], - ["_parent", []] - ]; - - private _element = [_echelon, _pos, _deployment, _parent]; - _queue pushBack _element; - _children apply {_x set [4, _element]; _x} -}] call SimTools_ForceDeployment_fnc_breadthFirstTraversal; - _fnc_switchOnEchelon = { params [ "_echelon", @@ -45,85 +29,81 @@ private _fobs = []; private _cops = []; private _pbs = []; private _pbBacklist = []; -{ - private _next = [ - _x select 0, - _x select 1, - _x select 2, - _x select 3 + +[_orbat, { + params [ + "_echelon", + ["_pos", [], [[0]], [0,2,3]], + ["_deployment", "", [""]], + ["_children", []], + ["_parent", [], [[]]], + ["_blacklist", [], [[]]] ]; - if (_x select 0 == "Platoon") then { - _next pushBack _pbBacklist; + + private _element = [_echelon, _pos, _deployment, _parent]; + + if (_echelon == "Platoon") then { + _element pushBack _pbBacklist; }; - _next call { - params [ - "_echelon", - ["_pos", [], [[0]], [0,2,3]], - ["_deployment", "", [""]], - ["_parent", [], [[]]], - ["_blacklist", [], [[]]] - ]; - - private [ - "_killzoneRadius", - "_blacklistRadius", - "_siblings" - ]; - [ - _echelon, - { - _killzoneRadius = 50; - _blacklistRadius = 8000; - _siblings = _fobs; - }, - { - _killzoneRadius = 40; - _blacklistRadius = 2000; - _siblings = _cops; - }, - { - _killzoneRadius = 15; - _blacklistRadius = 600; - _siblings = _pbs; - } - ] call _fnc_switchOnEchelon; - - if (count _pos < 2) then { - private _parentPos = []; - if (count _parent > 2) then {_parentPos = _parent select 1}; - - { - _blacklist pushBack [_x, _blacklistRadius]; - } forEach _siblings; - - private _newPos = [_echelon, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; - _pos set [0, _newPos select 0]; - _pos set [1, _newPos select 1]; - if (count _newPos < 3) then {_pos pushBack 0}; - - if (_echelon == "Company") then { - private _vector = (_pos vectorFromTo _parentPos); - _vector = _vector vectorMultiply 1000; - private _dir = (_vector select 0) atan2 (_vector select 1); - if (_dir < 0) then {_dir = 360 + _dir}; - private _blacklistCenter = _pos vectorAdd _vector; - - _pbBacklist pushBack ([_blacklistCenter, [2000, 1000, _dir, true]]); - }; + + private [ + "_killzoneRadius", + "_blacklistRadius", + "_siblings" + ]; + [ + _echelon, + { + _killzoneRadius = 50; + _blacklistRadius = 8000; + _siblings = _fobs; + }, + { + _killzoneRadius = 40; + _blacklistRadius = 2000; + _siblings = _cops; + }, + { + _killzoneRadius = 15; + _blacklistRadius = 600; + _siblings = _pbs; + } + ] call _fnc_switchOnEchelon; + + if (count _pos < 2) then { + private _parentPos = []; + if (count _parent > 2) then {_parentPos = _parent select 1}; + + { + _blacklist pushBack [_x, _blacklistRadius]; + } forEach _siblings; + + private _newPos = [_echelon, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; + _pos set [0, _newPos select 0]; + _pos set [1, _newPos select 1]; + if (count _newPos < 3) then {_pos pushBack 0}; + + if (_echelon == "Company") then { + private _vector = (_pos vectorFromTo _parentPos); + _vector = _vector vectorMultiply 1000; + private _dir = (_vector select 0) atan2 (_vector select 1); + if (_dir < 0) then {_dir = 360 + _dir}; + private _blacklistCenter = _pos vectorAdd _vector; + + _pbBacklist pushBack ([_blacklistCenter, [2000, 1000, _dir, true]]); }; + }; - [ - _echelon, - { _fobs }, - { _cops }, - { _pbs } - ] call _fnc_switchOnEchelon pushBack _pos; + [ + _echelon, + { _fobs }, + { _cops }, + { _pbs } + ] call _fnc_switchOnEchelon pushBack _pos; - [_pos, _killzoneRadius] call compileFinal _deployment; - _x set [1, _pos]; + [_pos, _killzoneRadius] call compileFinal _deployment; - _pos - }; -} forEach _queue; + _children apply {_x set [4, _element]; _x} +}] call SimTools_ForceDeployment_fnc_breadthFirstTraversal; _orbat From 3c8b9acefe7060ea5d4d3562c207cfb6ad6e52f9 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Lane" Date: Wed, 31 Oct 2018 23:11:07 -0300 Subject: [PATCH 4/4] Fixed company rear blacklist and debug markers --- Debug/fn_createMarkers.sqf | 5 +++-- fn_deployForce.sqf | 13 ++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Debug/fn_createMarkers.sqf b/Debug/fn_createMarkers.sqf index d5301bd..5fa8507 100644 --- a/Debug/fn_createMarkers.sqf +++ b/Debug/fn_createMarkers.sqf @@ -11,8 +11,9 @@ SIMTOOLS_FORCEDEPLOYMENT_DEBUG_MARKERS = []; [_orbat, { params [ "_echelon", - "_pos", - "_children" + ["_pos", [], [[0]], [0,2,3]], + ["_deployment", "", [""]], + ["_children", []] ]; private _name = format ["%1-%2-%3", player, _echelon, _pos]; diff --git a/fn_deployForce.sqf b/fn_deployForce.sqf index 4f105fd..5d19d4d 100644 --- a/fn_deployForce.sqf +++ b/fn_deployForce.sqf @@ -40,10 +40,8 @@ private _pbBacklist = []; ["_blacklist", [], [[]]] ]; - private _element = [_echelon, _pos, _deployment, _parent]; - if (_echelon == "Platoon") then { - _element pushBack _pbBacklist; + _blacklist = _blacklist + _pbBacklist; }; private [ @@ -71,12 +69,9 @@ private _pbBacklist = []; ] call _fnc_switchOnEchelon; if (count _pos < 2) then { - private _parentPos = []; - if (count _parent > 2) then {_parentPos = _parent select 1}; + private _parentPos = if (count _parent >= 2) then {_parent select 1} else {[]}; - { - _blacklist pushBack [_x, _blacklistRadius]; - } forEach _siblings; + _siblings apply {_blacklist pushBack [_x, _blacklistRadius]}; private _newPos = [_echelon, _parentPos, _blacklist] call SimTools_ForceDeployment_fnc_findValidPos; _pos set [0, _newPos select 0]; @@ -103,7 +98,7 @@ private _pbBacklist = []; [_pos, _killzoneRadius] call compileFinal _deployment; - _children apply {_x set [4, _element]; _x} + _children apply {_x set [4, [_echelon, _pos]]; _x} }] call SimTools_ForceDeployment_fnc_breadthFirstTraversal; _orbat