diff --git a/src/g_game.c b/src/g_game.c index 5f070711128ce8c770d19ceaf1148086e692b7d2..e45afbd3444642dad4482b22439d128fe4cc4dbc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4048,6 +4048,134 @@ void G_FreeTeamData(UINT8 team) team_ptr->flag_name = NULL; } +static boolean G_AreTeamScoresTied(void) +{ + for (UINT8 i = 1; i < teamsingame - 1; i++) + { + if (teamscores[G_GetTeam(i)] != teamscores[G_GetTeam(i + 1)]) + return false; + } + + return true; +} + +static boolean G_AreTeamPlayerCountsTied(void) +{ + INT32 numplayers[MAXTEAMS]; + + for (INT32 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + numplayers[players[i].ctfteam]++; + } + + for (UINT8 i = 1; i < teamsingame - 1; i++) + { + if (numplayers[G_GetTeam(i)] != numplayers[G_GetTeam(i + 1)]) + return false; + } + + return true; +} + +UINT8 G_GetBestPerformingTeam(void) +{ + if (teamsingame < 2 || G_AreTeamScoresTied()) + return TEAM_NONE; + + UINT8 mostscore = TEAM_NONE; + + for (UINT8 i = 1; i < teamsingame; i++) + { + UINT8 team = G_GetTeam(i); + if (mostscore == TEAM_NONE || teamscores[team] > teamscores[mostscore]) + mostscore = team; + } + + return mostscore; +} + +UINT8 G_GetWorstPerformingTeam(void) +{ + if (teamsingame < 2 || G_AreTeamScoresTied()) + return TEAM_NONE; + + UINT8 leastscore = TEAM_NONE; + + for (UINT8 i = 1; i < teamsingame; i++) + { + UINT8 team = G_GetTeam(i); + if (leastscore == TEAM_NONE || teamscores[team] < teamscores[leastscore]) + leastscore = team; + } + + return leastscore; +} + +UINT8 G_GetMostAdvantagedTeam(void) +{ + if (teamsingame < 2) + return TEAM_NONE; + + INT32 numplayers[MAXTEAMS]; + UINT8 mostscore = TEAM_NONE; + UINT8 mostplayers = TEAM_NONE; + + for (INT32 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + numplayers[players[i].ctfteam]++; + } + + for (UINT8 i = 1; i < teamsingame; i++) + { + UINT8 team = G_GetTeam(i); + if (mostscore == TEAM_NONE || teamscores[team] > teamscores[mostscore]) + mostscore = team; + if (mostplayers == TEAM_NONE || numplayers[team] > numplayers[mostplayers]) + mostplayers = team; + } + + if (mostplayers != TEAM_NONE && !G_AreTeamPlayerCountsTied()) + return mostplayers; + else if (mostscore != TEAM_NONE && !G_AreTeamScoresTied()) + return mostscore; + + return TEAM_NONE; +} + +UINT8 G_GetMostDisadvantagedTeam(void) +{ + if (teamsingame < 2) + return TEAM_NONE; + + INT32 numplayers[MAXTEAMS]; + UINT8 leastscore = TEAM_NONE; + UINT8 leastplayers = TEAM_NONE; + + for (INT32 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + numplayers[players[i].ctfteam]++; + } + + for (UINT8 i = 1; i < teamsingame; i++) + { + UINT8 team = G_GetTeam(i); + if (leastscore == TEAM_NONE || teamscores[team] < teamscores[leastscore]) + leastscore = team; + if (leastplayers == TEAM_NONE || numplayers[team] < numplayers[leastplayers]) + leastplayers = team; + } + + if (leastplayers != TEAM_NONE && !G_AreTeamPlayerCountsTied()) + return leastplayers; + else if (leastscore != TEAM_NONE && !G_AreTeamScoresTied()) + return leastscore; + + return TEAM_NONE; +} + /** Select a random map with the given typeoflevel flags. * If no map has those flags, this arbitrarily gives you map 1. * \param tolflags The typeoflevel flags to insist on. Other bits may diff --git a/src/g_game.h b/src/g_game.h index cb97de6ff753ff3e4abc582f39549004d1f40ba9..1d6ba0cb4724bf688703ee416a192027d194b935 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -237,6 +237,11 @@ boolean G_HasTeamIcon(UINT8 team, UINT8 icon_type); void G_SetTeamIcon(UINT8 team, UINT8 icon_type, const char *icon); void G_FreeTeamData(UINT8 team); +UINT8 G_GetBestPerformingTeam(void); +UINT8 G_GetWorstPerformingTeam(void); +UINT8 G_GetMostAdvantagedTeam(void); +UINT8 G_GetMostDisadvantagedTeam(void); + void G_Ticker(boolean run); boolean G_Responder(event_t *ev); boolean G_LuaResponder(event_t *ev); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 4ec5ed8b3685fe985cee08e343aa885637ecd1aa..05d77d9cee08bae1468cb91f3dc1294f40e9805c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4174,6 +4174,30 @@ static int lib_gCompetitionGametype(lua_State *L) return 1; } +static int lib_gGetBestPerformingTeam(lua_State *L) +{ + lua_pushinteger(L, G_GetBestPerformingTeam()); + return 1; +} + +static int lib_gGetWorstPerformingTeam(lua_State *L) +{ + lua_pushinteger(L, G_GetWorstPerformingTeam()); + return 1; +} + +static int lib_gGetMostAdvantagedTeam(lua_State *L) +{ + lua_pushinteger(L, G_GetMostAdvantagedTeam()); + return 1; +} + +static int lib_gGetMostDisadvantagedTeam(lua_State *L) +{ + lua_pushinteger(L, G_GetMostDisadvantagedTeam()); + return 1; +} + static int lib_gTicsToHours(lua_State *L) { tic_t rtic = luaL_checkinteger(L, 1); @@ -4510,6 +4534,10 @@ static luaL_Reg lib[] = { {"G_CoopGametype",lib_gCoopGametype}, {"G_TagGametype",lib_gTagGametype}, {"G_CompetitionGametype",lib_gCompetitionGametype}, + {"G_GetBestPerformingTeam",lib_gGetBestPerformingTeam}, + {"G_GetWorstPerformingTeam",lib_gGetWorstPerformingTeam}, + {"G_GetMostAdvantagedTeam",lib_gGetMostAdvantagedTeam}, + {"G_GetMostDisadvantagedTeam",lib_gGetMostDisadvantagedTeam}, {"G_TicsToHours",lib_gTicsToHours}, {"G_TicsToMinutes",lib_gTicsToMinutes}, {"G_TicsToSeconds",lib_gTicsToSeconds}, diff --git a/src/p_user.c b/src/p_user.c index 52c005abdb11c50c39bd8ae1a7dd7a659fc979c9..d4df56f9bb585da149cee5f2162c8f31d52e5ae3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10501,44 +10501,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } -static UINT8 P_GetWorstPerformingTeam(void) -{ - INT32 numplayers[MAXTEAMS]; - INT32 leastscore = TEAM_NONE; - INT32 leastplayers = TEAM_NONE; - - for (INT32 i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - numplayers[players[i].ctfteam]++; - } - - for (INT32 i = 1; i < teamsingame; i++) - { - UINT8 team = G_GetTeam(i); - UINT8 compareto = leastscore == TEAM_NONE ? G_GetTeam(1) : leastscore; - - if (teamscores[team] < teamscores[compareto]) - { - leastscore = i; - } - - compareto = leastplayers == TEAM_NONE ? G_GetTeam(1) : leastplayers; - - if (numplayers[team] < numplayers[compareto]) - { - leastplayers = i; - } - } - - if (leastplayers != TEAM_NONE) - return leastplayers; - else if (leastscore != TEAM_NONE) - return leastscore; - - return G_GetTeam(P_RandomRange(1, teamsingame - 1)); -} - boolean P_SpectatorJoinGame(player_t *player) { if (!G_CoopGametype() && !cv_allowteamchange.value) @@ -10553,7 +10515,9 @@ boolean P_SpectatorJoinGame(player_t *player) // Partial code reproduction from p_tick.c autobalance code. else if (G_GametypeHasTeams()) { - UINT8 changeto = P_GetWorstPerformingTeam(); + UINT8 changeto = G_GetMostDisadvantagedTeam(); + if (changeto == TEAM_NONE) + changeto = G_GetTeam(P_RandomRange(1, teamsingame - 1)); if (!LUA_HookTeamSwitch(player, changeto, true, false, false)) return false;