Jump to content

Making bots stand still in a region trigger


Recommended Posts

Good evening,

 

I'm trying to manage spawning to avoid bots bottle-necking the single and narrow exit of a spawn...

I had a first try at it in 1944 Nordwind, that I thought working well enough

Now copying and tweaking it in 1944 Huertgen showed bots don't obey MoveTowards their own position, unlike when using Goto in navigational path through or goal

Map download link: https://wolffiles.de/filebase/ET/Maps/1944_huertgen_forest.zip

 

Should I replace the region trigger by a large waypoint covering the spawn hut with a path through, or is MoveTowards wrongly used or not working in some cases?

Should I create a custom high-priority goal (like the one you made for me years ago, goal_stopbots), and give it/remove it from bots through the algo?

 

You'll find below a sample code; I've added a print which shows bots just go further and further away from their target position, to the point they're still managed by the algo even though they're outside the spawn... Breaking the closest bot calculation

The sleep before releasing the mutual exclusion is given a high value to ease the observation (originally 0.75)

Attached in a ZIP gm+way (one named waypoint used to position the spawn exit for distance calculation)

 

global Map =
{
	Debug = 1,		// Please set to zero before distributing your script

	// Avoid spawn exit bottleneck
	// Only care about bots...
	// Class/weapon not taken into account (aka heavy weaps slowing down first movements)
	tank_spawn =
	{
		Name = "tank_spawn",
		TriggerOnClass = CLASS.ANYPLAYER,
		closestBot,
		mutex = false,
		botList = {},
		OnEnter = function( ent )
		{
			bot = Util.IsBot( ent );
			if ( !bot ) { return; }

			Map.tank_spawn.botList[ bot ] = 1;

			// Immediately capture current bot position
			// If we use GetPosition in the loops, the position is modified because the bot moves...
			botPos = bot.GetPosition();

			// Little sleep to let all spawning bots be listed
			sleep ( .1 );

			while ( bot && bot.Health > 0 && Map.tank_spawn.mutex )
			{
				// Don't move until it's your turn to enter the mutex
				bot.MoveTowards( botPos, 8 );
				Map.PrintBotPos( bot, botPos );
				yield();
			}

			Map.tank_spawn.mutex = true;

			// Determine the closest bot from the exit, remove it from the list, make it go, sleep a bit, free the mutex, exit
			// If the current bot isn't the one, free the mutex and loop until it's the case...
			Map.tank_spawn.closestBot = Map.DetermineClosestBot( Map.tank_spawn.botList );
			if ( bot && bot.Health > 0 && bot.Name != Map.tank_spawn.closestBot.Name )
			{
				//Util.MapDebugPrint( "Freeing mutex because not " + bot.Name + Util.DebugColorString + "'s turn", true );
				Map.tank_spawn.mutex = false;
				while ( bot && bot.Health > 0 && bot.Name != Map.tank_spawn.closestBot.Name )
				{
					// Don't move until it's your turn to move out
					bot.MoveTowards( botPos, 8 );
					Map.PrintBotPos( bot, botPos );
					yield();
				}

				// Now the current bot is the closest bot, take back the mutex
				Map.tank_spawn.mutex = true;
			}

			if ( bot ) { Map.tank_spawn.botList[ bot ] = null; }

			// Only look for the next closest bot if the one we just cleared wasn't the last of the list...
			botCount = 0;
			foreach ( dont_overwrite_bot_var_here and val in Map.tank_spawn.botList )
			{
				if ( !dont_overwrite_bot_var_here || dont_overwrite_bot_var_here.Health <= 0 ) { val = 0; continue; }
				if ( val == 1 ) { botCount += 1; }
			}

			if ( botCount > 0 )
			{
				//Util.MapDebugPrint( ToString( botCount ) + " remaining, looking for the next one...", true );
				Map.tank_spawn.closestBot = Map.DetermineClosestBot( Map.tank_spawn.botList );
			}

			Util.MapDebugPrint( "Exiting mutex as it is " + bot.Name + Util.DebugColorString + "'s turn", true );

			// Let the bot move a bit towards the exit before allowing the next one to move
			sleep( 2 );

			Map.tank_spawn.mutex = false;
		},
		OnExit = function( ent )
		{
			// As we don't wait for the bot to surely exit the spawn
			// (we just leave a bit of time between each bot, so they follow each other in single line),
			// no need for OnExit (botList filled and cleared exclusively in OnEnter)
		}
	},

	PrintBotPos = function( bot, targetPos )
	{
		//Util.MapDebugPrint( bot.Name + Util.DebugColorString + "'s position -> " + ToString( bot.GetPosition() ), true );
		Util.MapDebugPrint( bot.Name + Util.DebugColorString + "'s distance to its target position -> " + ToString( DistanceBetween( bot.GetPosition(), targetPos ) ), true );
	},

	DetermineClosestBot = function( list )
	{
		closestBot;
		dist = 500;

		foreach ( bot and val in list )
		{
			if ( !bot || bot.Health <= 0 ) { val = 0; continue; } // Disconnected or dead meanwhile
			if ( val != 1 ) { continue; }

			currentDist = DistanceBetween( bot.GetPosition(), Map.tankSpawnExitPos );
			if ( currentDist < dist )
			{
				closestBot = bot;
				dist = currentDist;
			}
		}

		//Util.MapDebugPrint( "Closest bot: " + closestBot.Name + Util.DebugColorString + " (" + ToString( dist ) + ")", true );

		return closestBot;
	}
};

global OnMapLoad = function()
{
	// Move self in front of the Tank Spawn
	pos = Vec3( 2739, -3910, 260 );
	wtPos = pos /*+ Vec3( 0, 0, 64 )*/;
	// ExecCommand( format( "wt %s %s %s", ToString( wtPos.x ), ToString( wtPos.y ), ToString( wtPos.z ) ) ); // Just realised I only have this signature locally

	// Grab the exit position only once, then reuse it
	wpTable = {};
	w = Wp.GetWaypointByName( "tank_spawn_exit", wpTable );
	Map.tankSpawnExitPos = wpTable.position;

	// Register the trigger
	OnTriggerRegion( AABB( 2607.125, -4437.875, 193.125, 2912.875, -4127.813, 267.125 ), Map.tank_spawn );

	Util.MapDebugPrint( "OnMapLoad", true );
};

 

1944_huertgen_tank_spawn_exit_management_sample.zip

Edited by Mateos
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...