Mateos Posted Wednesday at 07:38 PM Share Posted Wednesday at 07:38 PM (edited) 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 Wednesday at 07:39 PM by Mateos Quote Link to comment Share on other sites More sharing options...
Moderators palota Posted Wednesday at 09:21 PM Moderators Share Posted Wednesday at 09:21 PM You have to use paththrough navigation. Then in the navigate function you can stop the bot: this.Goto(this.Bot.GetPosition()); Mateos 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.