diff --git a/src/g_game.c b/src/g_game.c index e57402683f92c14dd9eec7bf0b713619dbf50495..18b7ea4a81bc70f3d0b05066fb5a944a928f7e37 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4054,6 +4054,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 035b4541e310e6d9ae11b49bef0f29aa1c0293e2..fa7936747b558b4a1815c50722e65f6d22b2c6a9 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -236,6 +236,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 af64d0823e07965505bf68d796c44b8ba7d435fa..c8b237bf6b89dd26111e93afa5ecbb869514db1c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4031,6 +4031,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); @@ -4357,6 +4381,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 358addb1367068b68a6aac6626f847c39f2374cd..7e2ef1bf5bd3e219f10959a2ab337a57fbb9d841 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10495,44 +10495,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) @@ -10547,7 +10509,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;