mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
mermerge from 0.4.3: auto team balancing
This commit is contained in:
parent
4fb71c1bca
commit
6dcea2c4ca
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
int client_id;
|
||||
int team;
|
||||
int score;
|
||||
bool force_balanced;
|
||||
|
||||
//
|
||||
int64 last_chat;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue