diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8f257cb4a..723cc6725 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2338,9 +2338,9 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) static UINT8 GetTeamByName(const char *name) { - for (UINT8 i = TEAM_RED; i < teamsingame; i++) + for (UINT8 i = 1; i < teamsingame; i++) { - if (!stricmp(name, G_GetTeamName(i))) + if (!stricmp(name, G_GetTeamName(G_GetTeam(i)))) return i; } return MAXTEAMS; @@ -2376,7 +2376,11 @@ static void Command_Teamchange_f(void) { UINT8 newteam = MAXTEAMS; if (M_StringOnlyHasDigits(COM_Argv(1))) + { newteam = atoi(COM_Argv(1)); + if (newteam >= teamsingame) + newteam = MAXTEAMS; + } else newteam = GetTeamByName(COM_Argv(1)); if (newteam != MAXTEAMS) @@ -2390,7 +2394,7 @@ static void Command_Teamchange_f(void) if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) - NetPacket.packet.newteam = MAXTEAMS; + NetPacket.packet.newteam = 3; else error = true; } @@ -2418,7 +2422,7 @@ static void Command_Teamchange_f(void) else if (G_GametypeHasSpectators()) { if ((players[consoleplayer].spectator && !NetPacket.packet.newteam) || - (!players[consoleplayer].spectator && NetPacket.packet.newteam == MAXTEAMS)) + (!players[consoleplayer].spectator && NetPacket.packet.newteam == 3)) error = true; } #ifdef PARANOIA @@ -2478,7 +2482,11 @@ static void Command_Teamchange2_f(void) { UINT8 newteam = MAXTEAMS; if (M_StringOnlyHasDigits(COM_Argv(1))) + { newteam = atoi(COM_Argv(1)); + if (newteam >= teamsingame) + newteam = MAXTEAMS; + } else newteam = GetTeamByName(COM_Argv(1)); if (newteam != MAXTEAMS) @@ -2492,7 +2500,7 @@ static void Command_Teamchange2_f(void) if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) NetPacket.packet.newteam = 0; else if (!strcasecmp(COM_Argv(1), "playing") || !strcasecmp(COM_Argv(1), "1")) - NetPacket.packet.newteam = MAXTEAMS; + NetPacket.packet.newteam = 3; else error = true; } @@ -2588,7 +2596,7 @@ static void Command_ServerTeamChange_f(void) else if (!strcasecmp(COM_Argv(2), "notit") || !strcasecmp(COM_Argv(2), "2")) NetPacket.packet.newteam = 2; else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "3")) - NetPacket.packet.newteam = MAXTEAMS; + NetPacket.packet.newteam = 3; else if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) NetPacket.packet.newteam = 0; else @@ -2602,7 +2610,11 @@ static void Command_ServerTeamChange_f(void) { UINT8 newteam = MAXTEAMS; if (M_StringOnlyHasDigits(COM_Argv(1))) + { newteam = atoi(COM_Argv(1)); + if (newteam >= teamsingame) + newteam = MAXTEAMS; + } else newteam = GetTeamByName(COM_Argv(1)); if (newteam != MAXTEAMS) @@ -2616,7 +2628,7 @@ static void Command_ServerTeamChange_f(void) if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) NetPacket.packet.newteam = 0; else if (!strcasecmp(COM_Argv(2), "playing") || !strcasecmp(COM_Argv(2), "1")) - NetPacket.packet.newteam = MAXTEAMS; + NetPacket.packet.newteam = 3; else error = true; } @@ -2722,7 +2734,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (((players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 1) || (!(players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 2) || (players[playernum].spectator && NetPacket.packet.newteam == 0) || - (!players[playernum].spectator && NetPacket.packet.newteam == MAXTEAMS)) + (!players[playernum].spectator && NetPacket.packet.newteam == 3)) return; } else if (G_GametypeHasTeams()) @@ -2734,7 +2746,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) else if (G_GametypeHasSpectators()) { if ((players[playernum].spectator && !NetPacket.packet.newteam) || - (!players[playernum].spectator && NetPacket.packet.newteam == MAXTEAMS)) + (!players[playernum].spectator && NetPacket.packet.newteam == 3)) return; } else @@ -2748,8 +2760,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) return; } - // Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh - if (!LUA_HookTeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) + UINT8 ctfteam = NetPacket.packet.newteam; + + if (G_GametypeHasTeams()) + { + ctfteam = G_GetTeam(ctfteam); + } + else if (G_TagGametype() || G_GametypeHasSpectators()) + { + if (ctfteam == 3) + ctfteam = TEAM_PLAYING; + else + ctfteam = 0; + } + else + ctfteam = 0; + + if (!LUA_HookTeamSwitch(&players[playernum], ctfteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) return; //no status changes after hidetime @@ -2797,7 +2824,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) break; //Otherwise, you don't need special permissions. } - if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > 3) || error)) + if (server && ((NetPacket.packet.newteam < 0 || NetPacket.packet.newteam > MAXTEAMS) || error)) { CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]); SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); @@ -2852,15 +2879,14 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } else if (G_GametypeHasTeams()) { - UINT8 team = NetPacket.packet.newteam % MAXTEAMS; - if (!team) + if (!ctfteam) { players[playernum].ctfteam = 0; players[playernum].spectator = true; } else { - players[playernum].ctfteam = team; + players[playernum].ctfteam = ctfteam; players[playernum].spectator = false; } } @@ -2873,20 +2899,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } if (NetPacket.packet.autobalance) - CONS_Printf(M_GetText("%s was autobalanced to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80'); + CONS_Printf(M_GetText("%s was autobalanced to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80'); else if (NetPacket.packet.scrambled) - CONS_Printf(M_GetText("%s was scrambled to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80'); - else if (NetPacket.packet.newteam == MAXTEAMS) - CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum]); - else if (G_TagGametype() && NetPacket.packet.newteam != 0) + CONS_Printf(M_GetText("%s was scrambled to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80'); + else if (NetPacket.packet.newteam != 0) { - if (NetPacket.packet.newteam == 1) - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[playernum]); - else if (NetPacket.packet.newteam == 2) - CONS_Printf(M_GetText("%s is no longer IT!\n"), player_names[playernum]); + if (G_TagGametype()) + { + if (NetPacket.packet.newteam == 1) + CONS_Printf(M_GetText("%s is now IT!\n"), player_names[playernum]); + else if (NetPacket.packet.newteam == 2) + CONS_Printf(M_GetText("%s is no longer IT!\n"), player_names[playernum]); + } + else if (G_GametypeHasTeams()) + CONS_Printf(M_GetText("%s switched to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(ctfteam)), G_GetTeamName(ctfteam), '\x80'); + else + CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum]); } - else if (G_GametypeHasTeams() && NetPacket.packet.newteam != 0) - CONS_Printf(M_GetText("%s switched to %s%s%c.\n"), player_names[playernum], GetChatColorForSkincolor(G_GetTeamColor(NetPacket.packet.newteam)), G_GetTeamName(NetPacket.packet.newteam), '\x80'); else CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]); @@ -4376,6 +4405,7 @@ retryscramble: // Randomly place players on teams. if (cv_teamscramble.value == 1) { + // TODO maxcomposition = playercount / 2; // Now randomly assign players to teams. @@ -4428,7 +4458,7 @@ retryscramble: { if (repick) { - newteam = (INT16)((M_RandomByte() % 2) + TEAM_RED); + newteam = (INT16)((M_RandomByte() % 2) + 1); repick = false; } else if (i != 2) // Mystic's secret sauce - ABBA is better than ABAB, so team B doesn't get worse players all around diff --git a/src/doomstat.h b/src/doomstat.h index dfa2f2701..e7d53e6b5 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -390,7 +390,16 @@ enum { TEAM_NONE, TEAM_RED, TEAM_BLUE, - MAXTEAMS = 4 + TEAM_PLAYING = 1, + MAXTEAMS = 16 +}; + +enum { + TEAM_ICON, + TEAM_ICON_FLAG, + TEAM_ICON_GOT_FLAG, + TEAM_ICON_MISSING_FLAG, + TEAM_ICON_MAX }; typedef struct @@ -402,6 +411,7 @@ typedef struct UINT16 color; UINT16 weapon_color; UINT16 missile_color; + char *icons[TEAM_ICON_MAX]; } team_t; extern team_t teams[MAXTEAMS]; @@ -484,6 +494,8 @@ typedef struct INT16 rankings_type; INT32 pointlimit; INT32 timelimit; + UINT8 numteams; + UINT8 teams[MAXTEAMS]; } gametype_t; extern gametype_t gametypes[NUMGAMETYPES]; diff --git a/src/g_game.c b/src/g_game.c index 6f0b25f3a..45da6eeda 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3464,7 +3464,9 @@ gametype_t gametypes[NUMGAMETYPES] = { .rankings_type = RANKINGS_DEFAULT, // default settings for match: timelimit 10 mins, no pointlimit .timelimit = 10, - .pointlimit = 0 + .pointlimit = 0, + .numteams = 2, + .teams = { TEAM_RED, TEAM_BLUE } }, // GT_TAG { @@ -3496,7 +3498,9 @@ gametype_t gametypes[NUMGAMETYPES] = { .rankings_type = RANKINGS_DEFAULT, // default settings for CTF: no timelimit, pointlimit 5 .timelimit = 0, - .pointlimit = 5 + .pointlimit = 5, + .numteams = 2, + .teams = { TEAM_RED, TEAM_BLUE } }, }; @@ -3531,9 +3535,17 @@ static void G_InitTeams(void) teams[TEAM_RED].name = Z_StrDup("Red"); teams[TEAM_RED].flag_name = Z_StrDup("Red Flag"); + teams[TEAM_RED].icons[TEAM_ICON] = Z_StrDup("RMATCICO"); + teams[TEAM_RED].icons[TEAM_ICON_FLAG] = Z_StrDup("RFLAGICO"); + teams[TEAM_RED].icons[TEAM_ICON_GOT_FLAG] = Z_StrDup("GOTRFLAG"); + teams[TEAM_RED].icons[TEAM_ICON_MISSING_FLAG] = Z_StrDup("NONICON2"); teams[TEAM_BLUE].name = Z_StrDup("Blue"); teams[TEAM_BLUE].flag_name = Z_StrDup("Blue Flag"); + teams[TEAM_BLUE].icons[TEAM_ICON] = Z_StrDup("BMATCICO"); + teams[TEAM_BLUE].icons[TEAM_ICON_FLAG] = Z_StrDup("BFLAGICO"); + teams[TEAM_BLUE].icons[TEAM_ICON_GOT_FLAG] = Z_StrDup("GOTBFLAG"); + teams[TEAM_BLUE].icons[TEAM_ICON_MISSING_FLAG] = Z_StrDup("NONICON"); G_UpdateTeamSelection(); } @@ -3551,19 +3563,27 @@ void G_InitGametypes(void) void G_UpdateTeamSelection(void) { - UINT8 i; + UINT8 i = 0; - dummyteam_cons_t[0].value = 0; - dummyteam_cons_t[0].strvalue = "Spectator"; - - for (i = 1; i <= teamsingame; i++) + if (G_GametypeHasSpectators()) { - dummyteam_cons_t[i].value = i; - dummyteam_cons_t[i].strvalue = teams[i].name; + dummyteam_cons_t[0].value = 0; + dummyteam_cons_t[0].strvalue = "Spectator"; + i++; + } + + for (UINT8 j = 1; j < teamsingame; j++, i++) + { + UINT8 team = G_GetTeam(j); + dummyteam_cons_t[i].value = team; + dummyteam_cons_t[i].strvalue = teams[team].name; } dummyteam_cons_t[i].value = 0; dummyteam_cons_t[i].strvalue = NULL; + + cv_dummyteam.defaultvalue = dummyteam_cons_t[0].strvalue; + cv_dummyteam.value = 0; } // @@ -3573,6 +3593,13 @@ void G_SetGametype(INT16 gtype) { gametype = gtype; gametyperules = gametypes[gametype].rules; + + if (G_GametypeHasTeams()) + teamsingame = gametypes[gametype].numteams + 1; + else + teamsingame = 3; + + G_UpdateTeamSelection(); } // @@ -3586,7 +3613,6 @@ INT16 G_AddGametype(UINT32 rules) gametypes[newgtype].name = Z_StrDup("???"); gametypes[newgtype].rules = rules; - // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); return newgtype; @@ -3857,6 +3883,49 @@ UINT32 G_TOLFlag(INT32 pgametype) return gametypes[pgametype].typeoflevel; } +UINT8 G_GetGametypeTeam(UINT8 gtype, UINT8 team) +{ + if (team == TEAM_NONE || team >= gametypes[gtype].numteams + 1) + return TEAM_NONE; + + return gametypes[gtype].teams[team - 1] % MAXTEAMS; +} + +UINT8 G_GetTeam(UINT8 team) +{ + return G_GetGametypeTeam(gametype, team); +} + +UINT8 G_GetTeamFromTeamFlag(UINT32 flag) +{ + for (UINT16 i = 1; i < teamsingame; i++) + { + UINT32 otherflag = 1 << (i - 1); + if (flag == otherflag) + return i; + } + + return TEAM_NONE; +} + +UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags) +{ + UINT8 count = 0; + + for (UINT16 i = 1; i < teamsingame; i++) + { + UINT32 otherflag = 1 << (i - 1); + if ((flags & otherflag) != 0) + { + teamlist[count++] = i; + if (count == MAXTEAMS) + break; + } + } + + return count; +} + const char *G_GetTeamName(UINT8 team) { if (team >= numteams) @@ -3897,6 +3966,22 @@ UINT16 G_GetTeamMissileColor(UINT8 team) return teams[team].missile_color; } +const char *G_GetTeamIcon(UINT8 team, UINT8 icon_type) +{ + if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teams[team].icons[icon_type]) + return NULL; + + return teams[team].icons[icon_type]; +} + +boolean G_HasTeamIcon(UINT8 team, UINT8 icon_type) +{ + if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teams[team].icons[icon_type]) + return false; + + return true; +} + /** 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 2d7aa27c8..ee9d9f52d 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -220,11 +220,17 @@ void G_UseContinue(void); void G_AfterIntermission(void); void G_EndGame(void); // moved from y_inter.c/h and renamed +UINT8 G_GetGametypeTeam(UINT8 gtype, UINT8 team); +UINT8 G_GetTeam(UINT8 team); +UINT8 G_GetTeamFromTeamFlag(UINT32 flag); +UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags); const char *G_GetTeamName(UINT8 team); const char *G_GetTeamFlagName(UINT8 team); UINT16 G_GetTeamColor(UINT8 team); UINT16 G_GetTeamWeaponColor(UINT8 team); UINT16 G_GetTeamMissileColor(UINT8 team); +const char *G_GetTeamIcon(UINT8 team, UINT8 icon_type); +boolean G_HasTeamIcon(UINT8 team, UINT8 icon_type); void G_Ticker(boolean run); boolean G_Responder(event_t *ev); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 28cfe859e..7aa9930b1 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -83,10 +83,7 @@ static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; -patch_t *rflagico; -patch_t *bflagico; -patch_t *rmatcico; -patch_t *bmatcico; +patch_t *teamicons[MAXTEAMS][TEAM_ICON_MAX]; patch_t *tagico; patch_t *tallminus; patch_t *tallinfin; @@ -2353,23 +2350,21 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (gametyperules & GTR_TEAMFLAGS) { - if (players[tab[i].num].gotflag & GF_REDFLAG) // Red - V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); - else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue - V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, bflagico, 0); + UINT8 teamlist[MAXTEAMS]; + UINT8 teamcount = G_GetTeamListFromTeamFlags(teamlist, players[tab[i].num].gotflag); + if (teamcount > 0) + V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, ST_GetTeamIconImage(teamlist[0], TEAM_ICON_FLAG), 0); } // Draw emeralds if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) { HU_Draw32Emeralds(x+60, y+2, 255); - //HU_DrawEmeralds(x-12,y+2,255); } else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); - //HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); } if (supercheck) @@ -2482,10 +2477,10 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (gametyperules & GTR_TEAMFLAGS) { - if (players[tab[i].num].gotflag & GF_REDFLAG) // Red - V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); - else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue - V_DrawSmallScaledPatch(x-28, y-4, 0, bflagico); + UINT8 teamlist[MAXTEAMS]; + UINT8 teamcount = G_GetTeamListFromTeamFlags(teamlist, players[tab[i].num].gotflag); + if (teamcount > 0) + V_DrawSmallScaledPatch(x-28, y-4, 0, ST_GetTeamIconImage(teamlist[0], TEAM_ICON_FLAG)); } // Draw emeralds @@ -2515,8 +2510,6 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) { if (tab[i].num != serverplayer) HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0); - //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); } } } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index e10b45164..f7d1aa1c6 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -14,6 +14,7 @@ #ifndef __HU_STUFF_H__ #define __HU_STUFF_H__ +#include "doomstat.h" #include "d_event.h" #include "w_wad.h" #include "r_defs.h" @@ -88,10 +89,7 @@ extern patch_t *ntb_font[NT_FONTSIZE]; extern patch_t *nto_font[NT_FONTSIZE]; extern patch_t *ttlnum[10]; extern patch_t *emeraldpics[3][8]; -extern patch_t *rflagico; -extern patch_t *bflagico; -extern patch_t *rmatcico; -extern patch_t *bmatcico; +extern patch_t *teamicons[MAXTEAMS][TEAM_ICON_MAX]; extern patch_t *tagico; extern patch_t *tallminus; extern patch_t *tallinfin; diff --git a/src/m_menu.c b/src/m_menu.c index 7fff0de1b..ae8179a2f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -475,7 +475,8 @@ static CV_PossibleValue_t dummymares_cons_t[] = { CV_PossibleValue_t dummyteam_cons_t[MAXTEAMS + 1]; -static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL); +consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL); + static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL); static consvar_t cv_dummyrings = CVAR_INIT ("dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL); static consvar_t cv_dummylives = CVAR_INIT ("dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL); diff --git a/src/m_menu.h b/src/m_menu.h index 8532dbbe3..e8e9270da 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -437,6 +437,7 @@ extern consvar_t cv_showfocuslost; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; extern CV_PossibleValue_t gametype_cons_t[]; extern CV_PossibleValue_t dummyteam_cons_t[]; +extern consvar_t cv_dummyteam; extern INT16 startmap; extern INT32 ultimate_selectable; diff --git a/src/p_tick.c b/src/p_tick.c index 38a55fe24..0b35ed7e3 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -441,15 +441,17 @@ static void P_DoAutobalanceTeams(void) { changeteam_union NetPacket; UINT16 usvalue; - INT32 i=0; - INT32 red=0, blue=0; - INT32 redarray[MAXPLAYERS], bluearray[MAXPLAYERS]; - INT32 redflagcarrier = 0, blueflagcarrier = 0; - INT32 totalred = 0, totalblue = 0; + INT32 i; + INT32 count[MAXTEAMS]; + INT32 array[MAXTEAMS][MAXPLAYERS]; + INT32 flagcarrier[MAXTEAMS]; + INT32 total[MAXTEAMS]; NetPacket.value.l = NetPacket.value.b = 0; - memset(redarray, 0, sizeof(redarray)); - memset(bluearray, 0, sizeof(bluearray)); + memset(count, 0, sizeof(count)); + memset(array, 0, sizeof(array)); + memset(flagcarrier, 0, sizeof(flagcarrier)); + memset(total, 0, sizeof(total)); // Only do it if we have enough room in the net buffer to send it. // Otherwise, come back next time and try again. @@ -462,39 +464,28 @@ static void P_DoAutobalanceTeams(void) { if (playeringame[i] && players[i].ctfteam) { - if (players[i].ctfteam == TEAM_RED) + UINT8 team = players[i].ctfteam; + if (!players[i].gotflag) { - if (!players[i].gotflag) - { - redarray[red] = i; //store the player's number. - red++; - } - else - redflagcarrier++; + array[team][count[team]] = i; + count[team]++; } else - { - if (!players[i].gotflag) - { - bluearray[blue] = i; //store the player's number. - blue++; - } - else - blueflagcarrier++; - } + flagcarrier[team]++; } } - totalred = red + redflagcarrier; - totalblue = blue + blueflagcarrier; + for (i = 0; i < teamsingame; i++) + total[i] = count[i] + flagcarrier[i]; - if ((abs(totalred - totalblue) > max(1, (totalred + totalblue) / 8))) + // TODO + if ((abs(total[G_GetTeam(1)] - total[G_GetTeam(2)]) > max(1, (total[G_GetTeam(1)] + total[G_GetTeam(2)]) / 8))) { - if (totalred > totalblue) + if (total[G_GetTeam(1)] > total[G_GetTeam(2)]) { - i = M_RandomKey(red); - NetPacket.packet.newteam = TEAM_BLUE; - NetPacket.packet.playernum = redarray[i]; + i = M_RandomKey(count[G_GetTeam(1)]); + NetPacket.packet.newteam = 2; + NetPacket.packet.playernum = array[1][i]; NetPacket.packet.verification = true; NetPacket.packet.autobalance = true; @@ -503,9 +494,9 @@ static void P_DoAutobalanceTeams(void) } else { - i = M_RandomKey(blue); - NetPacket.packet.newteam = TEAM_RED; - NetPacket.packet.playernum = bluearray[i]; + i = M_RandomKey(count[G_GetTeam(2)]); + NetPacket.packet.newteam = 1; + NetPacket.packet.playernum = array[2][i]; NetPacket.packet.verification = true; NetPacket.packet.autobalance = true; diff --git a/src/p_user.c b/src/p_user.c index d3a39b49d..358addb13 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3181,10 +3181,7 @@ static void P_DoPlayerHeadSigns(player_t *player) sign->eflags |= MFE_VERTICALFLIP; } - if (player->gotflag & GF_REDFLAG) - sign->frame = 1|FF_FULLBRIGHT; - else //if (player->gotflag & GF_BLUEFLAG) - sign->frame = 2|FF_FULLBRIGHT; + sign->frame = G_GetTeamFromTeamFlag(player->gotflag) | FF_FULLBRIGHT; } } @@ -8680,7 +8677,7 @@ void P_MovePlayer(player_t *player) // Toss a flag if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay)) { - if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if (!player->gotflag) P_PlayerEmeraldBurst(player, true); // Toss emeralds else P_PlayerFlagBurst(player, true); @@ -10496,7 +10493,44 @@ 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) @@ -10513,27 +10547,7 @@ boolean P_SpectatorJoinGame(player_t *player) // Partial code reproduction from p_tick.c autobalance code. else if (G_GametypeHasTeams()) { - INT32 changeto = 0; - INT32 z, numplayers[MAXTEAMS]; - - //find a team by num players, score, or random if all else fails. - for (z = 0; z < MAXPLAYERS; ++z) - if (playeringame[z]) - { - numplayers[players[z].ctfteam]++; - } - // for z - - if (numplayers[TEAM_BLUE] > numplayers[TEAM_RED]) - changeto = TEAM_RED; - else if (numplayers[TEAM_RED] > numplayers[TEAM_BLUE]) - changeto = TEAM_BLUE; - else if (teamscores[TEAM_BLUE] > teamscores[TEAM_RED]) - changeto = TEAM_RED; - else if (teamscores[TEAM_RED] > teamscores[TEAM_BLUE]) - changeto = TEAM_BLUE; - else - changeto = (P_RandomFixed() & 1) + TEAM_RED; + UINT8 changeto = P_GetWorstPerformingTeam(); if (!LUA_HookTeamSwitch(player, changeto, true, false, false)) return false; @@ -10568,7 +10582,7 @@ boolean P_SpectatorJoinGame(player_t *player) // respawn in place and sit there for the rest of the round. if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { - if (!LUA_HookTeamSwitch(player, 3, true, false, false)) + if (!LUA_HookTeamSwitch(player, TEAM_PLAYING, true, false, false)) return false; if (player->mo) { diff --git a/src/st_stuff.c b/src/st_stuff.c index d3e6e3e4b..662d6b7ab 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -106,8 +106,6 @@ static patch_t *thundershield; static patch_t *invincibility; static patch_t *sneakers; static patch_t *gravboots; -static patch_t *nonicon; -static patch_t *nonicon2; static patch_t *nightopianhelper; static patch_t *linkfreeze; static patch_t *superparaloop; @@ -131,8 +129,6 @@ static patch_t *capsulefill; patch_t *ngradeletters[7]; static patch_t *minus5sec; static patch_t *minicaps; -static patch_t *gotrflag; -static patch_t *gotbflag; static patch_t *fnshico; static boolean facefreed[MAXPLAYERS]; @@ -318,11 +314,9 @@ void ST_LoadGraphics(void) gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); tagico = W_CachePatchName("TAGICO", PU_HUDGFX); - gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); - gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX); - nonicon = W_CachePatchName("NONICON", PU_HUDGFX); - nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX); + + ST_LoadTeamIcons(); // NiGHTS HUD things nightopianhelper = W_CachePatchName("NHLPICON", PU_HUDGFX); @@ -365,6 +359,28 @@ void ST_LoadGraphics(void) ngradeletters[i] = W_CachePatchName(va("GRADE%d", i), PU_HUDGFX); } +void ST_LoadTeamIcons(void) +{ + for (UINT8 i = 0; i < numteams; i++) + { + for (UINT8 j = 0; j < TEAM_ICON_MAX; j++) + teamicons[i][j] = W_CachePatchName(G_HasTeamIcon(i, j) ? G_GetTeamIcon(i, j) : "MISSING", PU_HUDGFX); + } +} + +patch_t *ST_GetTeamIconImage(UINT8 team, UINT8 icon_type) +{ + if (team >= numteams || icon_type >= TEAM_ICON_MAX || !teamicons[team][icon_type]) + return W_CachePatchName("MISSING", PU_PATCH); + + return teamicons[team][icon_type]; +} + +patch_t *ST_GetCurrentTeamIconImage(UINT8 team, UINT8 icon_type) +{ + return ST_GetTeamIconImage(G_GetTeam(team), icon_type); +} + // made separate so that skins code can reload custom face graphics void ST_LoadFaceGraphics(INT32 skinnum) { @@ -1575,11 +1591,12 @@ static void ST_drawPowerupHUD(void) // CTF flags // --------- - // YOU have a flag. Display a monitor-like icon for it. + // YOU have a flag. Display an icon for it. if (stplyr->gotflag) { + // TODO flagoffs[q] = ICONSEP; - p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag; + p = ST_GetCurrentTeamIconImage(G_GetTeamFromTeamFlag(stplyr->gotflag), TEAM_ICON_GOT_FLAG); V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, p); } else if (flagoffs[q]) @@ -2412,23 +2429,24 @@ static void ST_drawTeamHUD(void) if (F_GetPromptHideHud(0)) // y base is 0 return; - rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); - bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); - rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); - bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); - if (LUA_HudEnabled(hud_teamscores)) { + patch_t *bmatcico = NULL; + patch_t *rmatcico = NULL; + if (gametyperules & GTR_TEAMFLAGS) { - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bflagico); - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rflagico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rflagico); + bmatcico = ST_GetCurrentTeamIconImage(1, TEAM_ICON_FLAG); + rmatcico = ST_GetCurrentTeamIconImage(2, TEAM_ICON_FLAG); } else { - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico); - V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico); + bmatcico = ST_GetCurrentTeamIconImage(1, TEAM_ICON); + rmatcico = ST_GetCurrentTeamIconImage(2, TEAM_ICON); } + + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - (bmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmatcico); + V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - (rmatcico->width / 4), 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmatcico); } if (!(gametyperules & GTR_TEAMFLAGS)) @@ -2436,40 +2454,47 @@ static void ST_drawTeamHUD(void) { INT32 i; UINT16 whichflag = 0; + UINT16 allflags = 0; + + for (i = 1; i < teamsingame; i++) + allflags |= teams[G_GetTeam(i)].flag; // Show which flags aren't at base. for (i = 0; i < MAXPLAYERS; i++) { + patch_t *rmissing = ST_GetCurrentTeamIconImage(1, TEAM_ICON_MISSING_FLAG); + patch_t *bmissing = ST_GetCurrentTeamIconImage(2, TEAM_ICON_MISSING_FLAG); + // Blue flag isn't at base - if (players[i].gotflag & GF_BLUEFLAG && LUA_HudEnabled(hud_teamscores)) - V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - (nonicon->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon); + if (players[i].gotflag & teams[G_GetTeam(2)].flag && LUA_HudEnabled(hud_teamscores)) + V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - (bmissing->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, bmissing); // Red flag isn't at base - if (players[i].gotflag & GF_REDFLAG && LUA_HudEnabled(hud_teamscores)) - V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - (nonicon2->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon2); + if (players[i].gotflag & teams[G_GetTeam(1)].flag && LUA_HudEnabled(hud_teamscores)) + V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - (rmissing->width / 2), 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, rmissing); whichflag |= players[i].gotflag; - if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG)) + if (whichflag == allflags) break; // both flags were found, let's stop early } // Display a countdown timer showing how much time left until the flag returns to base. { - if (flagmobjs[TEAM_BLUE] && flagmobjs[TEAM_BLUE]->fuse > 1 && LUA_HudEnabled(hud_teamscores)) - V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[TEAM_BLUE]->fuse / TICRATE))); + if (flagmobjs[G_GetTeam(2)] && flagmobjs[G_GetTeam(2)]->fuse > 1 && LUA_HudEnabled(hud_teamscores)) + V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[G_GetTeam(2)]->fuse / TICRATE))); - if (flagmobjs[TEAM_RED] && flagmobjs[TEAM_RED]->fuse > 1 && LUA_HudEnabled(hud_teamscores)) - V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[TEAM_RED]->fuse / TICRATE))); + if (flagmobjs[G_GetTeam(1)] && flagmobjs[G_GetTeam(1)]->fuse > 1 && LUA_HudEnabled(hud_teamscores)) + V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (flagmobjs[G_GetTeam(1)]->fuse / TICRATE))); } } num: if (LUA_HudEnabled(hud_teamscores)) - V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[TEAM_BLUE])); - - if (LUA_HudEnabled(hud_teamscores)) - V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[TEAM_RED])); + { + V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[G_GetTeam(2)])); + V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", teamscores[G_GetTeam(1)])); + } #undef SEP } diff --git a/src/st_stuff.h b/src/st_stuff.h index 603be3c30..d8ffd1b45 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -41,6 +41,8 @@ void ST_changeDemoView(void); void ST_UnloadGraphics(void); void ST_LoadGraphics(void); +void ST_LoadTeamIcons(void); + // face load graphics, called when skin changes void ST_LoadFaceGraphics(INT32 playernum); void ST_ReloadSkinFaceGraphics(void); @@ -61,6 +63,9 @@ extern tic_t lt_exitticker, lt_endtime; // return if player a is in the same team as player b boolean ST_SameTeam(player_t *a, player_t *b); +patch_t *ST_GetTeamIconImage(UINT8 team, UINT8 icon_type); +patch_t *ST_GetCurrentTeamIconImage(UINT8 team, UINT8 icon_type); + //-------------------- // status bar overlay //-------------------- diff --git a/src/y_inter.c b/src/y_inter.c index 6fb016261..d9b372fc9 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -271,16 +271,10 @@ void Y_LoadIntermissionData(void) case int_ctf: case int_teammatch: { - if (!rflagico) //prevent a crash if we haven't cached our team graphics yet - { - rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); - bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX); - rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX); - bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); - } + ST_LoadTeamIcons(); - data.match.redflag = (intertype == int_ctf) ? rflagico : rmatcico; - data.match.blueflag = (intertype == int_ctf) ? bflagico : bmatcico; + data.match.redflag = (intertype == int_ctf) ? ST_GetCurrentTeamIconImage(1, TEAM_ICON_FLAG) : ST_GetCurrentTeamIconImage(1, TEAM_ICON); + data.match.blueflag = (intertype == int_ctf) ? ST_GetCurrentTeamIconImage(2, TEAM_ICON_FLAG) : ST_GetCurrentTeamIconImage(2, TEAM_ICON); } /* FALLTHRU */ case int_match: