Make teams more customizable

This commit is contained in:
Lactozilla 2023-08-05 17:26:00 -03:00
parent be4dc010b8
commit 4a2f3a2b18
13 changed files with 316 additions and 161 deletions

View file

@ -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 (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() && 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 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
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

View file

@ -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];

View file

@ -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;
if (G_GametypeHasSpectators())
{
dummyteam_cons_t[0].value = 0;
dummyteam_cons_t[0].strvalue = "Spectator";
i++;
}
for (i = 1; i <= teamsingame; i++)
for (UINT8 j = 1; j < teamsingame; j++, i++)
{
dummyteam_cons_t[i].value = i;
dummyteam_cons_t[i].strvalue = teams[i].name;
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

View file

@ -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);

View file

@ -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");
}
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)
{
redarray[red] = i; //store the player's number.
red++;
array[team][count[team]] = i;
count[team]++;
}
else
redflagcarrier++;
}
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;

View file

@ -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)
{

View file

@ -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,64 +2429,72 @@ 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
{
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))
goto num;
{
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
}

View file

@ -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
//--------------------

View file

@ -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: