Reworked garrisoning so that we only try to garrison nearby buildings.

This should prevent the thing where group leaders way in-front of their group.
M ineptifex/behaviordata.h +5 -0
@@ 1,5 1,10 @@ 
+#include "data.h"
+
 #define NEW_BEHAVIOR_STATE   []
 
 #define DEFEND_WP_NAME  "__INEPT_wp_defend"
 #define FLANK_WP_NAME   "__INEPT_wp_flank"
 #define ASSAULT_WP_NAME "__INEPT_wp_assault"
+
+#define NEW_DEFEND_BEHAVIOR_STATE()        [WP_TYPE_UNKNOWN]
+#define DEFEND_BEHAVIOR_STATE_LAST_WP_TYPE 0

          
M ineptifex/fn_behaviorAssaultInstall.sqf +0 -2
@@ 10,6 10,4 @@ LOGENTRY();
 
 VAR(_pawn) = ARGUMENT_0;
 VAR(_grp) = _pawn select PAWN_GROUP;
-LOGVAR(behaviour leader _grp);
 (leader _grp) setBehaviour "AWARE";
-LOGVAR(behaviour leader _grp);

          
M ineptifex/fn_behaviorDefendInstall.sqf +1 -2
@@ 9,7 9,6 @@ 
 LOGENTRY();
 
 VAR(_pawn) = ARGUMENT_0;
+_pawn set [PAWN_BEHAVIOR_STATE, NEW_DEFEND_BEHAVIOR_STATE()];
 VAR(_grp) = _pawn select PAWN_GROUP;
-LOGVAR(behaviour leader _grp);
 (leader _grp) setBehaviour "SAFE";
-LOGVAR(behaviour leader _grp);

          
M ineptifex/fn_behaviorDefendTick.sqf +6 -6
@@ 14,8 14,7 @@ LOGVAR(_pawn);
 VAR(_aoi) = _pawn select PAWN_AOI;
 LOGVAR(_aoi);
 
-//VAR(_state) = _pawn select PAWN_BEHAVIOR_STATE;
-//_state BEHAVIOR_STATE_
+VAR(_state) = _pawn select PAWN_BEHAVIOR_STATE;
 
 VAR(_wp) = [_pawn, DEFEND_WP_NAME] call INEPT_fnc_findWaypointByName;
 LOGVAR(_wp);

          
@@ 69,10 68,8 @@ if (_is_idle) then
     {
     case (
         (random 1 > 0.6)
-        // When we do the garrison thing, we probably fall out of formation,
-        // ideally we would be right at the building before we did, but that's
-        // too hard, so by making sure we're in the AOI we increase the
-        // likihood that our garrison building will be at least somewhat nearby
+        // Don't garrison twice in a row
+        and {!((_state select DEFEND_BEHAVIOR_STATE_LAST_WP_TYPE) isEqualTo WP_TYPE_GARRISON)}
         and {[_aoi, _pawn_pos, WP_SUBDIVISION_RADIUS] call INEPT_fnc_isPosNearAOI}
         and {[_aoi, _pawn, _wp, WP_TYPE_GARRISON] call INEPT_fnc_configurePawnWaypoint}
         ):

          
@@ 81,6 78,7 @@ if (_is_idle) then
         _wp setWaypointName DEFEND_WP_NAME;
         _grp setCurrentWaypoint _wp;
         _is_on_task = true;
+        _state set [DEFEND_BEHAVIOR_STATE_LAST_WP_TYPE, WP_TYPE_GARRISON];
     };
     case ([_aoi, _pawn, _wp, WP_TYPE_OVERWATCH] call INEPT_fnc_configurePawnWaypoint):
     {

          
@@ 88,10 86,12 @@ if (_is_idle) then
         _wp setWaypointName DEFEND_WP_NAME;
         _grp setCurrentWaypoint _wp;
         _is_on_task = true;
+        _state set [DEFEND_BEHAVIOR_STATE_LAST_WP_TYPE, WP_TYPE_OVERWATCH];
     };
     default
     {
         deleteWaypoint _wp;
+        _state set [DEFEND_BEHAVIOR_STATE_LAST_WP_TYPE, WP_TYPE_UNKNOWN];
         LOGMSG("Failed to make a waypoint for this motherfucker");
     };
     };

          
M ineptifex/fn_configurePawnWaypoint.sqf +29 -38
@@ 44,54 44,44 @@ switch (_wp_type) do
 case WP_TYPE_GARRISON:
 {
     // Ensure we have units to garrison
+    if ([units _grp, {
+            (not ((vehicle _x) isEqualTo _x))
+            and {not ((vehicle _x) isKindOf (configFile >> "CfgVehicles" >> "Car"))}
+        }] call INEPT_fnc_any)
+        exitWith {/* Don't garrison if we are in a group with a vehicle that isn't a car */};
     VAR(_garrison_me) = [
         units _grp,
-        // Only garrison those on foot, everybody else should follow the
-        // waypoint
         {vehicle _x == _x}
         ] call BIS_fnc_conditionalSelect;
-    if (_garrison_me isEqualTo []) exitWith {};
-
-    VAR(_area) = NEW_CIRCLE(
-        _aoi select AOI_POS,
-        _aoi select AOI_DISPERSION
-        );
-    // TODO, set the subdivision radius based on the surface area of the _area
-    VAR(_subareas) = [_area, WP_SUBDIVISION_RADIUS] call INEPT_fnc_subdivide;
-    // Only consider areas above sea level
-    [_subareas, {getTerrainHeightASL _x > 0}] call INEPT_fnc_conditionalSelectIP;
-    // Ensure we are not mermaids
-    if (_subareas isEqualTo []) exitWith {};
+    if (_garrison_me isEqualTo [])
+        exitWith {/* Don't garrison if nobody is on foot? */};
 
-    VAR(_buildings) = [];
-    VAR(_idx) = [
-        _subareas,
-        {
-            // Finds buildings in the subdivision
-            _buildings = _x nearObjects ["Building", WP_SUBDIVISION_RADIUS];
-            [
-                _buildings,
-                {
-                    // Building must have at least 5 positions
-                    if ([0, 0, 0] isEqualTo (_x buildingPos 4)) exitWith {false};
-                    VAR(_garrison) = _x getVariable "__INEPT_garrison";
-                    // Building cannot be already occupied
-                    // TODO, this is a bit racey
-                    if (!isNil "_garrison"
-                        && {!((waypointPosition _garrison) isEqualTo [0, 0, 0])}
-                        && {LOGVAR(getPosATL _x); LOGVAR(waypointPosition _garrison); (getPosATL _x) distance (waypointPosition _garrison) < 10}) exitWith {false};
-                    //if ([0, 0, 0] isEqualTo (_x buildingPos 4)) exitWith {false};
-                    true
-                }
-            ] call INEPT_fnc_conditionalSelectIP;
-            !(_buildings isEqualTo [])
-        }
+    private _buildings = (leader _grp) nearObjects ["Building", 75];
+    LOGVAR(_buildings);
+    private _idx =
+        [
+            _buildings,
+            {
+                // Something about the building having a path.
+                if !((nearestBuilding _x) isEqualTo _x) exitWith {false};
+                // Building must have at least 5 positions
+                if ([0, 0, 0] isEqualTo (_x buildingPos 4)) exitWith {false};
+                VAR(_garrison) = _x getVariable "__INEPT_garrison";
+                // Building cannot be already occupied
+                // this is a bit racey ...
+                if (!isNil "_garrison"
+                    && {!((waypointPosition _garrison) isEqualTo [0, 0, 0])}
+                    && {(getPosATL _x) distance (waypointPosition _garrison) < 10}) exitWith {false};
+                //if ([0, 0, 0] isEqualTo (_x buildingPos 4)) exitWith {false};
+                true
+            }
         ] call INEPT_fnc_indexOfFirstAtRandom;
+    LOGVAR(_idx);
 
     // Just give up, life is not worth living
     if (_idx == -1) exitWith { LOGMSG("Couldn't find a nice building to garrison"); };
 
-    VAR(_bld) = _buildings call INEPT_fnc_popRandom;
+    VAR(_bld) = _buildings select _idx;
     VAR(_dest) = getPosATL _bld;
     [_garrison_me, 0.5 + random 0.5] call INEPT_fnc_selectFractionAtRandomIP;
     [_garrison_me, _bld] call INEPT_fnc_garrisonUnits;

          
@@ 104,6 94,7 @@ case WP_TYPE_GARRISON:
     _wp setWaypointCompletionRadius 20;
 
     // TODO, publicVariable it so that other AOs are effected?
+    // TODO, srsly, the above todo is kind of important
     _bld setVariable ["__INEPT_garrison", _wp];
 
     _did_anything = true;

          
M init.sqf +1 -2
@@ 12,8 12,7 @@ 
 LOGENTRY();
 
 //INEPT_fnc_configurePawnWaypoint_is_verbose = true;
-//INEPT_fnc_delegateAOIs_is_verbose = true;
-//INEPT_fnc_processAOOnce_is_verbose = true;
+//INEPT_fnc_behaviorDefendTick_is_verbose = true;
 
 // EnticingEdict specific stuff