mermerge from 0.4.3: auto team balancing

This commit is contained in:
Alfred Eriksson 2008-09-07 08:10:56 +00:00
parent 4fb71c1bca
commit 6dcea2c4ca
6 changed files with 135 additions and 3 deletions

View file

@ -62,6 +62,7 @@ bool CHARACTER::spawn(PLAYER *player, vec2 pos, int team)
game.world.insert_entity(this);
alive = true;
player->force_balanced = false;
game.controller->on_character_spawn(this);
@ -563,6 +564,15 @@ void CHARACTER::tick()
return;
}
* */
if(player->force_balanced)
{
char buf[128];
str_format(buf, sizeof(buf), "You were moved to %s due to team balancing", game.controller->get_team_name(team));
game.send_broadcast(buf, player->client_id);
player->force_balanced = false;
}
//player_core core;
//core.pos = pos;

View file

@ -26,6 +26,8 @@ GAMECONTROLLER::GAMECONTROLLER()
teamscore[0] = 0;
teamscore[1] = 0;
unbalanced_tick = -1;
num_spawn_points[0] = 0;
num_spawn_points[1] = 0;
num_spawn_points[2] = 0;
@ -188,6 +190,7 @@ void GAMECONTROLLER::startround()
game.world.paused = false;
teamscore[0] = 0;
teamscore[1] = 0;
unbalanced_tick = -1;
round_count++;
}
@ -341,6 +344,49 @@ void GAMECONTROLLER::tick()
}
}
if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60)
{
dbg_msg("game", "Balancing teams");
int t[2] = {0,0};
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(game.players[i].client_id != -1 && game.players[i].team != -1)
t[game.players[i].team]++;
}
int m = (t[0] > t[1]) ? 0 : 1;
int num_balance = abs(t[0]-t[1]) / 2;
int scorediff = abs(teamscore[0]-teamscore[1]);
do
{
// move player who is closest to team-scorediff
PLAYER *p = 0;
int pd = teamscore[m];
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(game.players[i].client_id == -1)
continue;
if(game.players[i].team == m && (!p || abs(scorediff - game.players[i].score) < pd))
{
p = &(game.players[i]);
pd = abs(scorediff - game.players[i].score);
}
}
// change in player::set_team needed: player won't lose score on team-change
int score_before = p->score;
p->set_team(m^1);
p->score = score_before;
p->respawn();
p->force_balanced = true;
} while (--num_balance);
unbalanced_tick = -1;
}
// update browse info
int prog = -1;
@ -431,6 +477,66 @@ bool GAMECONTROLLER::can_join_team(int team, int notthisid)
return (numplayers[0] + numplayers[1]) < config.sv_max_clients-config.sv_spectator_slots;
}
bool GAMECONTROLLER::check_team_balance()
{
if(!is_teamplay() || !config.sv_teambalance_time)
return true;
int t[2] = {0, 0};
for(int i = 0; i < MAX_CLIENTS; i++)
{
PLAYER *p = &(game.players[i]);
if(p->client_id != -1 && p->team != -1)
t[p->team]++;
}
if(abs(t[0]-t[1]) >= 2)
{
dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", t[0], t[1]);
if (game.controller->unbalanced_tick == -1)
game.controller->unbalanced_tick = server_tick();
return false;
}
else
{
dbg_msg("game", "Team is balanced (red=%d blue=%d)", t[0], t[1]);
game.controller->unbalanced_tick = -1;
return true;
}
}
bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam)
{
int t[2] = {0, 0};
if (!is_teamplay() || jointeam == -1 || !config.sv_teambalance_time)
return true;
for(int i = 0; i < MAX_CLIENTS; i++)
{
PLAYER *p = &(game.players[i]);
if(p->client_id != -1 && p->team != -1)
t[p->team]++;
}
// simulate what would happen if changed team
t[jointeam]++;
if (pplayer->team != -1)
t[jointeam^1]--;
// there is a player-difference of at least 2
if(abs(t[0]-t[1]) >= 2)
{
// player wants to join team with less players
if ((t[0] < t[1] && jointeam == 0) || (t[0] > t[1] && jointeam == 1))
return true;
else
return false;
}
else
return true;
}
void GAMECONTROLLER::do_player_score_wincheck()
{
if(game_over_tick == -1 && !warmup)

View file

@ -34,7 +34,7 @@ protected:
void cyclemap();
void resetgame();
const char *gametype;
int round_start_tick;
@ -52,6 +52,8 @@ protected:
public:
bool is_teamplay() const;
int unbalanced_tick;
GAMECONTROLLER();
void do_team_score_wincheck();
@ -118,6 +120,8 @@ public:
virtual const char *get_team_name(int team);
virtual int get_auto_team(int notthisid);
virtual bool can_join_team(int team, int notthisid);
bool check_team_balance();
bool can_change_team(PLAYER *pplayer, int jointeam);
int clampteam(int team);
virtual void post_reset();

View file

@ -104,6 +104,8 @@ void mods_connected(int client_id)
game.players[client_id].team = -1;
else
game.players[client_id].team = game.controller->get_auto_team(client_id);
(void) game.controller->check_team_balance();
// send motd
NETMSG_SV_MOTD msg;
@ -115,7 +117,7 @@ void mods_connected(int client_id)
void mods_client_drop(int client_id)
{
game.players[client_id].on_disconnect();
(void) game.controller->check_team_balance();
}
void mods_message(int msgtype, int client_id)
@ -156,7 +158,15 @@ void mods_message(int msgtype, int client_id)
// Switch team on given client and kill/respawn him
if(game.controller->can_join_team(msg->team, client_id))
p->set_team(msg->team);
{
if(game.controller->can_change_team(p, msg->team))
{
p->set_team(msg->team);
(void) game.controller->check_team_balance();
}
else
game.send_broadcast("Teams must be balanced, please join other team", client_id);
}
else
{
char buf[128];

View file

@ -21,6 +21,7 @@ public:
int client_id;
int team;
int score;
bool force_balanced;
//
int64 last_chat;

View file

@ -61,3 +61,4 @@ MACRO_CONFIG_INT(sv_tournament_mode, 0, 0, 1)
MACRO_CONFIG_INT(sv_spamprotection, 1, 0, 1)
MACRO_CONFIG_INT(sv_spectator_slots, 0, 0, 12)
MACRO_CONFIG_INT(sv_teambalance_time, 1, 0, 1000)