Jump to content
Crazy_Man

Ideas for a script to remove AI units when they've been stuck for a while

Recommended Posts

Hi all, I'm interested in a script that would detect AI units that get stuck for a while and are not in combat.

 

If you have good ideas on the subject, don't hesitate to post them.

 

I am creating a mission where, once a city is taken, reinforcements are spawned at random and secure positions and must reach the city.

So I don't want to be bothered by vehicles stuck on the way slowing the reinforcements, I prefer to delete them if they are not in combat.

 

for the moment, I've this:

 

if (!isServer) exitWith {};

timeIdle = 60*10; // 10 minutes
//timeIdle = 30; // TEST !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

mission_fnc_idle = {

	params ["_gr"];

	//{_x disableAI "PATH"} forEach units _gr; // TEST !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	_distToDelete = 5;

	// Get all group's vehicle(s)
	_vehs = [_gr, true] call BIS_fnc_groupVehicles;
	
	// initialize vars
	{if (alive _x) then {_x setVariable ["idlePos", position _x]}} forEach units _gr;
	_timeOut = time + timeIdle;


	// MAIN LOOP
	while {{alive _x} count units _gr > 0} do {

		sleep 5;

		if (isNil "_gr" or {{alive _x} count units _gr < 1}) exitWith {};
      
		// CHECK IDLE UNITS
		if ({alive _x} count units _gr > 0 and _timeOut < time) then {

			_units = [];
			_unitsToDelete = [];
			_vehsToDelete = [];

			// get all units near their idle position
			{if (alive _x and _x distance (_x getVariable "idlePos") < _distToDelete) then {_units pushBackUnique _x}} forEach units _gr;

		
			{

				// if unit in vehicle
				if (vehicle _x != _x) then {

					_veh = vehicle _x;

					if (!((crew _veh) call mission_fnc_isEngaging)) then {

						{_unitsToDelete pushBackUnique _x} forEach crew _veh;
						_vehsToDelete = _vehsToDelete + [_veh];
					};
				};

				// if unit not in vehicle
				if (vehicle _x == _x and !(_x call mission_fnc_isEngaging)) then {

					_unitsToDelete pushBackUnique _x;
				};

			} forEach _units;


			// delete idle units and vehicles
			{deleteVehicle _x} forEach _unitsToDelete + _vehsToDelete; 


			// reset vars
			{if (alive _x) then {_x setVariable ["idlePos", position _x]}} forEach units _gr;
			_timeOut = time + timeIdle;
		};
		
	};

};

                                                            
                                                            
// Thanks to rübe

mission_fnc_isEngaging = {
	/*
	  Author:
	   rübe

	  Description:
	   returns true if anybody of the given unit(s)/group is engaging

	  Parameter(s):
	   _this: unit(s)/group (unit, array of units or group)

	  Returns:
	   boolean
	*/

	private ["_units", "_engaging"];

	_units = [];
	_engaging = false;

	switch (true) do
	{
	  case ((typeName _this) == "ARRAY"):
	  {
	     _units = _this;
	  };
	  case ((typeName _this) == "GROUP"):
	  {
	     _units = units _this;
	  };
	  default
	  {
	     _units = [_this];
	  };
	};

	{
	  if ((currentCommand _x) in ["ATTACK", "ATTACKFIRE", "FIRE"]) exitWith
	  {
	     _engaging = true;
	  };
	} forEach _units;


	// return status
	_engaging

};

 

Share this post


Link to post
Share on other sites

Round 1)

Safe every unit and it's position in an array. 

Round 2) 

Get the positions again and compare array 1 with array 2, if the position are within a small range, delete the unit

  • Confused 1

Share this post


Link to post
Share on other sites

 Hi  @Crazy_Man 

That's a very good topic! I'm on it before releasing a (possible) advanced waypoint for searching in houses (within a radius). Difficult!

That's lead for this comments:

- spawning vehicles or units in safe place is not too difficult. There are BI functions: bis_fnc_findSafePos  BIS_fnc_CPFindEmptyPosition (coming from Combat Patrol) or commands findEmptyPosition  selectBestPlaces  (isFlatEmpty )

 That's for placement..

- moving vehicles or units. Here come the paths and the ability for AIs to find them, follow them. There is a new tool, but not achieved imho, with an EN "calculatedPath" and the command calculatePath In an ideal world, this tool should say at once if a path from A to B is existing (returning something different than an empty array or nothing!).

In real arma world, the tool is bugged (EH runs twice and the returned path is quickly overridden by a useless array - see problem in BIKI). My own workaround:

 

isNil { 
  _agent = calculatePath ["man", "aware", Position1, Position2] addEventHandler ["PathCalculated",
   {
     params ["_agent","_path"];
     if (isNil {_agent getVariable "passed"}) then {
       _agent setVariable ["passed",true];
       pathArray = _path
     }
    }
  ];
};

You just can say: if no calculated path, no move.

 

Spoiler

But a returned path don't guarantee that the vehicle will follow it. It's easy to check that with a calculation for "wheeled_APC" and a true "B_APC_Wheeled_01_cannon_F"  in Stratis - Agia Marina city. There are probably some re-calculation when the vehicle detects an obstacle (like house in curve)

  

So, When a unit/vehicle is stuck?
You can check unit readiness;  unitReady returning TRUE is not "really" stuck. Unit is "probably" ready for a new move. But sometimes a stuck unit becomes ready after a delay (especially when there is no possible path). That depends also on the animation state. For example a unit can be indefinitely stuck trying to climb a ladder without success (Tanoa example: Land_Shop_City_07_f)
 

Spoiler

Imho, There is a lack of command for setting a unit to be ready, something like setUnitReady  which cancel the current move/waypoint if no path/no success for current destination.


The behavior of the unit is also important! If you start to delete all units finding a cover to fire, while there are underway for a destination, you will not keep too much fighting units!
So, your topic is huge.  For me, it's WIP for a while!

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Good topic.  I know mission makers have always struggled with units and vehicles that get stuck.  That boat driver who drives up on the sandbar and doesn't move,

 

The mrap driver who rides up on a rock and can't figure it out.....

 

Ugh

 

Share this post


Link to post
Share on other sites

Ok so I've done some tests with the EH "PathCalculated" but for now it doesn't seems to help.

 

It can detect whether or not the vehicle can reach the desired position (water for a vehicle that is not amphibious for example).

 

But even if the vehicle is on its back and can therefore no longer move, it will still find a path.

 

With the player placed in the desired vehicle and a logic game named "logictest" (for the position to reach) :

  • Water on the way without an amphibious land vehicle : return false
  • No water on the way and same vehicle but on its back : return true
KK_fnc_setPosAGLS = {
	params ["_obj", "_pos", "_offset"];
	_offset = _pos select 2;
	if (isNil "_offset") then {_offset = 0};
	_pos set [2, worldSize];
	_obj setPosASL _pos;
	_pos set [2, vectorMagnitude (_pos vectorDiff getPosVisual _obj) + _offset];
	_obj setPosASL _pos;
};


mission_fnc_calculatedPath = {

	params ["_veh", "_destPos"];

	_agent = createAgent [typeOf (crew _veh select 0), [0,0,10000], [], 100, "CAN_COLLIDE"];
	//_vehAgent = createVehicle [(typeOf _veh), [0,0,10000], [], 100, "CAN_COLLIDE"];
	_vehAgent = createVehicle [(typeOf _veh), position _veh, [], 0, "NONE"];
	_agent moveInDriver _vehAgent;

	//_vehAgent hideObjectGlobal true;

	//sleep 0.5;

	//[_vehAgent, position _veh] call KK_fnc_setPosAGLS;
	_vehAgent setVectorDirAndUp [vectorDir _veh, vectorUp _veh];

	sleep 0.5;
	
	_agent addEventHandler ["PathCalculated",
		{
			params ["_agent","_path"];

			if (isNil {_agent getVariable "passed"}) then {

				_agent setVariable ["passed", true];
				{ 
					_marker = createMarker ["marker" + str _forEachIndex, _x]; 
					_marker setMarkerType "mil_dot"; 
					_marker setMarkerText str _forEachIndex; 
				} 
				forEach _path;
			}
		}
	];
	
	_agent setDestination [_destPos, "LEADER PLANNED", false];

	_timeOut = time + 5; 

	waitUntil {_agent getVariable ["passed", false] or _timeOut <= time};
	
	systemChat str (_agent getVariable ["passed", false]);

	//deleteVehicle _agent;
	//deleteVehicle _vehAgent;

};

[vehicle player, position logictest] spawn mission_fnc_calculatedPath;

 

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

×