X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fbot.qc;h=3911d596dc51859afd8058272ec394bf402014a7;hp=667fb2b3d577514ac80daf232ec468032516dbec;hb=797bf448a96c0c13d783c7c919bb2caf6fa16707;hpb=b9d5c8d9237626af62c8dd05005af562e5aa33be diff --git a/qcsrc/server/bot/default/bot.qc b/qcsrc/server/bot/default/bot.qc index 667fb2b3d5..3911d596dc 100644 --- a/qcsrc/server/bot/default/bot.qc +++ b/qcsrc/server/bot/default/bot.qc @@ -21,7 +21,7 @@ #include "../../race.qh" #include -#include "../../mutators/_mod.qh" +#include #include "../../weapons/accuracy.qh" @@ -41,6 +41,8 @@ #include #include +STATIC_INIT(bot) { bot_calculate_stepheightvec(); } + // TODO: remove this function! its only purpose is to update these fields since bot_setnameandstuff is called before ClientState void bot_setclientfields(entity this) { @@ -74,12 +76,6 @@ void bot_think(entity this) 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)); - //if (this.bot_painintensity > 0) - // this.bot_painintensity = this.bot_painintensity - (skill + 1) * 40 * frametime; - - //this.bot_painintensity = this.bot_painintensity + this.bot_oldhealth - this.health; - //this.bot_painintensity = bound(0, this.bot_painintensity, 100); - if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start)) { CS(this).movement = '0 0 0'; @@ -129,6 +125,9 @@ void bot_think(entity this) // if dead, just wait until we can respawn if (IS_DEAD(this)) { + if (bot_waypoint_queue_owner == this) + bot_waypoint_queue_owner = NULL; + this.aistatus = 0; CS(this).movement = '0 0 0'; if (this.deadflag == DEAD_DEAD) { @@ -216,13 +215,13 @@ void bot_setnameandstuff(entity this) 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 @@ -244,7 +243,7 @@ void bot_setnameandstuff(entity this) this.bot_config_loaded = true; - // this is really only a default, JoinBestTeam is called later + // 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; @@ -255,16 +254,23 @@ void bot_setnameandstuff(entity this) name = bot_name; // number bots with identical names - int j = 0; - FOREACH_CLIENT(IS_BOT_CLIENT(it), { - if(it.cleanname == name) - ++j; - }); - if (j) - this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix)); - else + if (name == "") + { + name = ftos(etof(this)); this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix)); - + } + else + { + int j = 0; + FOREACH_CLIENT(IS_BOT_CLIENT(it), { + if(it.cleanname == name) + ++j; + }); + if (j) + this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix)); + else + this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix)); + } this.cleanname = strzone(name); // pick the model and skin @@ -396,18 +402,10 @@ void bot_clientdisconnect(entity this) if (!IS_BOT_CLIENT(this)) return; bot_clearqueue(this); - if(this.cleanname) - strunzone(this.cleanname); - if(this.netname_freeme) - strunzone(this.netname_freeme); - if(this.playermodel_freeme) - strunzone(this.playermodel_freeme); - if(this.playerskin_freeme) - strunzone(this.playerskin_freeme); - this.cleanname = string_null; - this.netname_freeme = string_null; - this.playermodel_freeme = string_null; - this.playerskin_freeme = string_null; + strfree(this.cleanname); + strfree(this.netname_freeme); + strfree(this.playermodel_freeme); + strfree(this.playerskin_freeme); if(this.bot_cmd_current) delete(this.bot_cmd_current); if(bot_waypoint_queue_owner == this) @@ -438,7 +436,7 @@ void bot_clientconnect(entity this) else if(this.bot_forced_team==4) this.team = NUM_TEAM_4; else - TeamBalance_JoinBestTeam(this, true); + TeamBalance_JoinBestTeam(this); havocbot_setupbot(this); } @@ -582,7 +580,7 @@ void bot_calculate_stepheightvec() jumpstepheightvec = stepheightvec + jumpheight_vec * 0.85; // reduce it a bit to make the jumps easy } -float bot_fixcount() +bool bot_fixcount() { int activerealplayers = 0; int realplayers = 0; @@ -598,8 +596,6 @@ float bot_fixcount() } int bots; - // add/remove bots if needed to make sure there are at least - // minplayers+bot_number, or remove all bots if no one is playing // But don't remove bots immediately on level change, as the real players // usually haven't rejoined yet bots_would_leave = false; @@ -607,15 +603,19 @@ float bot_fixcount() bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers); else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5))) { - float realminplayers, minplayers; - realminplayers = autocvar_minplayers; - minplayers = max(0, floor(realminplayers)); + 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)); - float realminbots, minbots; - realminbots = autocvar_bot_number; - minbots = max(0, floor(realminbots)); + // add bots to reach minplayers if needed + bots = max(minbots, minplayers - activerealplayers); + // cap bots to the max players allowed by the server + int player_limit = GetPlayerLimit(); + if(player_limit) + bots = min(bots, max(player_limit - activerealplayers, 0)); + bots = min(bots, maxclients - realplayers); - bots = min(max(minbots, minplayers - activerealplayers), maxclients - realplayers); if(bots > minbots) bots_would_leave = true; } @@ -636,7 +636,7 @@ float bot_fixcount() return false; } } - while (currentbots > bots) + while (currentbots > bots && bots >= 0) bot_removenewest(); }