]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/bot.qc
Clean up / compact bot_setnameandstuff code
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / bot.qc
index 9ebcffae3c8383657da46d4b571e24dfcdd92b2a..4d0d4cdff2ad2a03c954fb7e56ec3e30434f94ba 100644 (file)
@@ -145,21 +145,7 @@ void bot_think(entity this)
 void bot_setnameandstuff(entity this)
 {
        string readfile, s;
-       float file, tokens, prio;
-
-       string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
-       string name, prefix, suffix;
-
-       if(autocvar_g_campaign)
-       {
-               prefix = "";
-               suffix = "";
-       }
-       else
-       {
-               prefix = autocvar_bot_prefix;
-               suffix = autocvar_bot_suffix;
-       }
+       int file, tokens, prio;
 
        file = fopen(autocvar_bot_config_file, FILE_READ);
 
@@ -170,6 +156,26 @@ void bot_setnameandstuff(entity this)
        }
        else
        {
+               entity balance = TeamBalance_CheckAllowedTeams(NULL);
+               TeamBalance_GetTeamCounts(balance, NULL);
+               int smallest_team = -1;
+               int smallest_count = -1;
+               if (teamplay)
+               {
+                       for (int i = 1; i <= AvailableTeams(); ++i)
+                       {
+                               // NOTE if (autocvar_g_campaign && autocvar_g_campaign_forceteam == i)
+                               // TeamBalance_GetNumberOfPlayers(balance, i); returns the number of players + 1
+                               // since it keeps a spot for the real player in the desired team
+                               int count = TeamBalance_GetNumberOfPlayers(balance, i);
+                               if (smallest_count < 0 || count < smallest_count)
+                               {
+                                       smallest_team = i;
+                                       smallest_count = count;
+                               }
+                       }
+               }
+               TeamBalance_Destroy(balance);
                RandomSelection_Init();
                while((readfile = fgets(file)))
                {
@@ -177,24 +183,41 @@ void bot_setnameandstuff(entity this)
                                continue;
                        if(substring(readfile, 0, 1) == "#")
                                continue;
+                       // NOTE if the line is empty tokenizebyseparator(readfile, "\t")
+                       // will create 1 empty token because there's no separator (bug?)
+                       if (readfile == "")
+                               continue;
                        tokens = tokenizebyseparator(readfile, "\t");
                        if(tokens == 0)
                                continue;
                        s = argv(0);
-                       prio = 1;
+                       prio = 0;
+                       bool conflict = false;
                        FOREACH_CLIENT(IS_BOT_CLIENT(it), {
-                               if(s == it.cleanname)
+                               if (s == it.cleanname)
                                {
-                                       prio = 0;
+                                       conflict = true;
                                        break;
                                }
                        });
+                       if (!conflict)
+                               prio += 1;
+                       if (teamplay && !(autocvar_bot_vs_human && AvailableTeams() == 2))
+                       {
+                               int forced_team = stof(argv(5));
+                               if (!Team_IsValidIndex(forced_team))
+                                       forced_team = 0;
+                               if (!forced_team || forced_team == smallest_team)
+                                       prio += 2;
+                       }
                        RandomSelection_AddString(readfile, 1, prio);
                }
                readfile = RandomSelection_chosen_string;
                fclose(file);
        }
 
+       string bot_name, bot_model, bot_skin, bot_shirt, bot_pants;
+
        tokens = tokenizebyseparator(readfile, "\t");
        if(argv(0) != "") bot_name = argv(0);
        else bot_name = "Bot";
@@ -211,17 +234,20 @@ void bot_setnameandstuff(entity this)
        if(argv(4) != "" && stof(argv(4)) >= 0) bot_pants = argv(4);
        else bot_pants = ftos(floor(random() * 15));
 
-       this.bot_forced_team = stof(argv(5));
+       if (teamplay && !(autocvar_bot_vs_human && AvailableTeams() == 2))
+               this.bot_forced_team = stof(argv(5));
+       else
+               this.bot_forced_team = 0;
 
        prio = 6;
 
-       #define READSKILL(f, w, r) MACRO_BEGIN \
+       #define READSKILL(f, w, r) MACRO_BEGIN \
                if(argv(prio) != "") \
                        this.f = stof(argv(prio)) * w; \
                else \
                        this.f = (!autocvar_g_campaign) * (2 * random() - 1) * r * w; \
                prio++; \
-       MACRO_END
+       MACRO_END
        //print(bot_name, ": ping=", argv(9), "\n");
 
        READSKILL(havocbot_keyboardskill, 0.5, 0.5); // keyboard skill
@@ -241,19 +267,19 @@ void bot_setnameandstuff(entity this)
        READSKILL(bot_thinkskill, 1, 0.5); // think skill
        READSKILL(bot_aiskill, 2, 0); // "ai" skill
 
+       if (file >= 0 && argv(prio) != "")
+               LOG_INFOF("^1Warning^7: too many parameters for bot %s, please check format of %s", bot_name, autocvar_bot_config_file);
+
        this.bot_config_loaded = true;
 
        // this is really only a default, TeamBalance_JoinBestTeam is called later
        setcolor(this, stof(bot_shirt) * 16 + stof(bot_pants));
        this.bot_preferredcolors = this.clientcolors;
 
-       // pick the name
-       if (autocvar_bot_usemodelnames)
-               name = bot_model;
-       else
-               name = bot_name;
+       string prefix = (autocvar_g_campaign ? "" : autocvar_bot_prefix);
+       string suffix = (autocvar_g_campaign ? "" : autocvar_bot_suffix);
+       string name = (autocvar_bot_usemodelnames ? bot_model : bot_name);
 
-       // number bots with identical names
        if (name == "")
        {
                name = ftos(etof(this));
@@ -261,6 +287,7 @@ void bot_setnameandstuff(entity this)
        }
        else
        {
+               // number bots with identical names
                int j = 0;
                FOREACH_CLIENT(IS_BOT_CLIENT(it), {
                        if(it.cleanname == name)
@@ -427,16 +454,15 @@ void bot_clientconnect(entity this)
                bot_setclientfields(this);
        }
 
-       if(this.bot_forced_team==1)
-               this.team = NUM_TEAM_1;
-       else if(this.bot_forced_team==2)
-               this.team = NUM_TEAM_2;
-       else if(this.bot_forced_team==3)
-               this.team = NUM_TEAM_3;
-       else if(this.bot_forced_team==4)
-               this.team = NUM_TEAM_4;
+       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);
 }
@@ -578,6 +604,7 @@ void bot_calculate_stepheightvec()
        stepheightvec = autocvar_sv_stepheight * '0 0 1';
        jumpheight_vec = (autocvar_sv_jumpvelocity ** 2) / (2 * autocvar_sv_gravity) * '0 0 1';
        jumpstepheightvec = stepheightvec + jumpheight_vec * 0.85; // reduce it a bit to make the jumps easy
+       jumpheight_time = autocvar_sv_jumpvelocity / autocvar_sv_gravity;
 }
 
 bool bot_fixcount()
@@ -604,6 +631,8 @@ bool bot_fixcount()
        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());
                int minbots = max(0, floor(autocvar_bot_number));
 
                // add bots to reach minplayers if needed
@@ -611,7 +640,7 @@ bool bot_fixcount()
                // cap bots to the max players allowed by the server
                int player_limit = GetPlayerLimit();
                if(player_limit)
-                       bots = min(bots, player_limit - activerealplayers);
+                       bots = min(bots, max(player_limit - activerealplayers, 0));
                bots = min(bots, maxclients - realplayers);
 
                if(bots > minbots)
@@ -634,7 +663,7 @@ bool bot_fixcount()
                                return false;
                        }
                }
-               while (currentbots > bots)
+               while (currentbots > bots && bots >= 0)
                        bot_removenewest();
        }
 
@@ -752,7 +781,7 @@ void bot_serverframe()
                if(botframe_cachedwaypointlinks)
                {
                        if(!botframe_loadedforcedlinks)
-                               waypoint_load_links_hardwired();
+                               waypoint_load_hardwiredlinks();
                }
                else
                {