]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/bot.qc
Improve end of warmup countdown abort (when player count drops too low)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / bot.qc
index 59ff81df94678b5f744c0da45e617019e56416a7..d7cf429d74e150a8324c0c30bfe0245d683658f1 100644 (file)
@@ -28,6 +28,7 @@
 #include <server/scores_rules.qh>
 #include <server/teamplay.qh>
 #include <server/weapons/accuracy.qh>
+#include <server/weapons/selection.qh>
 #include <server/world.qh>
 
 STATIC_INIT(bot) { bot_calculate_stepheightvec(); }
@@ -63,10 +64,16 @@ void bot_think(entity this)
        if(autocvar_bot_god)
                this.flags |= FL_GODMODE;
 
-       this.bot_nextthink = max(time, this.bot_nextthink) + max(0.01, autocvar_bot_ai_thinkinterval * (0.5 ** this.bot_aiskill) * min(14 / (skill + 14), 1));
+       this.bot_nextthink = max(time, this.bot_nextthink) + max(0.01, autocvar_bot_ai_thinkinterval * min(14 / (skill + this.bot_aiskill + 14), 1));
 
        if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start))
        {
+               if (IS_PLAYER(this))
+               {
+                       .entity weaponentity = weaponentities[0];
+                       if(this.(weaponentity).m_weapon == WEP_Null)
+                               W_NextWeapon(this, 0, weaponentity);
+               }
                CS(this).movement = '0 0 0';
                this.bot_nextthink = time + 0.5;
                return;
@@ -106,9 +113,11 @@ void bot_think(entity this)
 
        if (time < game_starttime)
        {
+               .entity weaponentity = weaponentities[0];
+               if(this.(weaponentity).m_weapon == WEP_Null)
+                       W_NextWeapon(this, 0, weaponentity);
                // block the bot during the countdown to game start
                CS(this).movement = '0 0 0';
-               this.bot_nextthink = game_starttime;
                return;
        }
 
@@ -160,7 +169,7 @@ void bot_setnameandstuff(entity this)
                int smallest_count = -1;
                if (teamplay)
                {
-                       for (int i = 1; i <= AvailableTeams(); ++i)
+                       for (int i = 1; i <= AVAILABLE_TEAMS; ++i)
                        {
                                // NOTE if (autocvar_g_campaign && autocvar_g_campaign_forceteam == i)
                                // TeamBalance_GetNumberOfPlayers(balance, i); returns the number of players + 1
@@ -200,7 +209,7 @@ void bot_setnameandstuff(entity this)
                        });
                        if (!conflict)
                                prio += 1;
-                       if (teamplay && !(autocvar_bot_vs_human && AvailableTeams() == 2))
+                       if (teamplay && !(autocvar_bot_vs_human && AVAILABLE_TEAMS == 2))
                        {
                                int forced_team = stof(argv(5));
                                if (!Team_IsValidIndex(forced_team))
@@ -232,8 +241,12 @@ void bot_setnameandstuff(entity this)
        if(argv(4) != "" && stof(argv(4)) >= 0) bot_pants = argv(4);
        else bot_pants = ftos(floor(random() * 15));
 
-       if (teamplay && !(autocvar_bot_vs_human && AvailableTeams() == 2))
+       if (teamplay && !(autocvar_bot_vs_human && AVAILABLE_TEAMS == 2))
+       {
                this.bot_forced_team = stof(argv(5));
+               if (!Team_IsValidIndex(this.bot_forced_team))
+                       this.bot_forced_team = 0;
+       }
        else
                this.bot_forced_team = 0;
 
@@ -428,7 +441,6 @@ void bot_clientconnect(entity this)
        if (!IS_BOT_CLIENT(this)) return;
        this.bot_preferredcolors = this.clientcolors;
        this.bot_nextthink = time - random();
-       this.lag_func = bot_lagfunc;
        this.isbot = true;
        this.createdtime = this.bot_nextthink;
 
@@ -438,16 +450,6 @@ void bot_clientconnect(entity this)
                bot_setclientfields(this);
        }
 
-       if (teamplay && Team_IsValidIndex(this.bot_forced_team))
-       {
-               SetPlayerTeam(this, this.bot_forced_team, TEAM_CHANGE_MANUAL);
-       }
-       else
-       {
-               this.bot_forced_team = 0;
-               TeamBalance_JoinBestTeam(this);
-       }
-
        havocbot_setupbot(this);
 }
 
@@ -536,11 +538,8 @@ void bot_removenewest()
 
 void autoskill(float factor)
 {
-       float bestbot;
-       float bestplayer;
-
-       bestbot = -1;
-       bestplayer = -1;
+       int bestbot = -1;
+       int bestplayer = -1;
        FOREACH_CLIENT(IS_PLAYER(it), {
                if(IS_REAL_CLIENT(it))
                        bestplayer = max(bestplayer, it.totalfrags - it.totalfrags_lastcheck);
@@ -548,37 +547,37 @@ void autoskill(float factor)
                        bestbot = max(bestbot, it.totalfrags - it.totalfrags_lastcheck);
        });
 
-       LOG_DEBUG("autoskill: best player got ", ftos(bestplayer), ", ");
-       LOG_DEBUG("best bot got ", ftos(bestbot), "; ");
+       string msg = strcat("autoskill: best player got ", ftos(bestplayer), ", ""best bot got ", ftos(bestbot), "; ");
        if(bestbot < 0 || bestplayer < 0)
        {
-               LOG_DEBUG("not doing anything");
+               msg = strcat(msg, "not doing anything");
                // don't return, let it reset all counters below
        }
        else if(bestbot <= bestplayer * factor - 2)
        {
                if(autocvar_skill < 17)
                {
-                       LOG_DEBUG("2 frags difference, increasing skill");
+                       msg = strcat(msg, "2 frags difference, increasing skill");
                        cvar_set("skill", ftos(autocvar_skill + 1));
-                       bprint("^2SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
+                       bprint("^2BOT SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
                }
        }
        else if(bestbot >= bestplayer * factor + 2)
        {
                if(autocvar_skill > 0)
                {
-                       LOG_DEBUG("2 frags difference, decreasing skill");
+                       msg = strcat(msg, "2 frags difference, decreasing skill");
                        cvar_set("skill", ftos(autocvar_skill - 1));
-                       bprint("^1SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
+                       bprint("^1BOT SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
                }
        }
        else
        {
-               LOG_DEBUG("not doing anything");
+               msg = strcat(msg, "not doing anything");
                return;
                // don't reset counters, wait for them to accumulate
        }
+       LOG_DEBUG(msg);
 
        FOREACH_CLIENT(IS_PLAYER(it), { it.totalfrags_lastcheck = it.totalfrags; });
 }
@@ -591,7 +590,7 @@ void bot_calculate_stepheightvec()
        jumpheight_time = autocvar_sv_jumpvelocity / autocvar_sv_gravity;
 }
 
-bool bot_fixcount()
+bool bot_fixcount(bool multiple_per_frame)
 {
        int activerealplayers = 0;
        int realplayers = 0;
@@ -610,13 +609,13 @@ bool bot_fixcount()
        // But don't remove bots immediately on level change, as the real players
        // usually haven't rejoined yet
        bots_would_leave = false;
-       if (teamplay && autocvar_bot_vs_human && AvailableTeams() == 2)
+       if (autocvar_bot_vs_human && AVAILABLE_TEAMS == 2)
                bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
        else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
        {
                int minplayers = max(0, floor(autocvar_minplayers));
                if (teamplay)
-                       minplayers = max(0, floor(autocvar_minplayers_per_team) * AvailableTeams());
+                       minplayers = max(0, floor(autocvar_minplayers_per_team) * AVAILABLE_TEAMS);
                int minbots = max(0, floor(autocvar_bot_number));
 
                // add bots to reach minplayers if needed
@@ -639,13 +638,17 @@ bool bot_fixcount()
        // only add one bot per frame to avoid utter chaos
        if(time > botframe_nextthink)
        {
-               if (currentbots < bots)
+               while (currentbots < bots)
                {
                        if (bot_spawn() == NULL)
                        {
                                bprint("Can not add bot, server full.\n");
                                return false;
                        }
+                       if (!multiple_per_frame)
+                       {
+                               break;
+                       }
                }
                while (currentbots > bots && bots >= 0)
                        bot_removenewest();
@@ -676,6 +679,7 @@ void bot_serverframe()
        // spectators in the scoreboard and never go away. This issue happens at time 2 if map is changed
        // with the gotomap command, minplayers is > 1 and human clients join as players very soon
        // either intentionally or automatically (sv_spectate 0)
+       // A working workaround for this bug was implemented in commit fbd145044, see entcs_attach
        if (time < 2.5)
        {
                currentbots = -1;
@@ -716,7 +720,7 @@ void bot_serverframe()
 
        if(time > botframe_nextthink)
        {
-               if(!bot_fixcount())
+               if(!bot_fixcount(false))
                        botframe_nextthink = time + 10;
        }