diff --git a/src/deh_soc.c b/src/deh_soc.c index 5ec9816d635f6b566408b8c1c5ae5e35b7222a46..646ec874436027ece44577446a820086f9d28f9c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1130,8 +1130,7 @@ void readsprite2(MYFILE *f, INT32 num) Z_Free(s); } -// copypasted from readPlayer :] -void readgametype(MYFILE *f, char *gtname) +void readgametype(MYFILE *f, INT32 num) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; @@ -1139,21 +1138,15 @@ void readgametype(MYFILE *f, char *gtname) char *tmp; INT32 i, j; - INT16 newgtidx = 0; - UINT32 newgtrules = 0; - UINT32 newgttol = 0; - INT32 newgtpointlimit = 0; - INT32 newgttimelimit = 0; - UINT8 newgtleftcolor = 0; - UINT8 newgtrightcolor = 0; - INT16 newgtrankingstype = -1; - int newgtinttype = 0; + char *gtname = gametypes[num].name; + char gtconst[32]; char gtdescription[441]; - char gtconst[MAXLINELEN]; - // Empty strings. - gtdescription[0] = '\0'; - gtconst[0] = '\0'; + UINT8 newgtleftcolor, newgtrightcolor; + boolean has_desc_colors[2] = { false, false }; + + memset(gtconst, 0, sizeof(gtconst)); + memset(gtdescription, 0, sizeof(gtconst)); do { @@ -1212,8 +1205,8 @@ void readgametype(MYFILE *f, char *gtname) if (word2) { if (!word2lwr) - word2lwr = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - strcpy(word2lwr, word2); + word2lwr = Z_Calloc(MAXLINELEN, PU_STATIC, NULL); + strlcpy(word2lwr, word2, MAXLINELEN); strupr(word2); } else @@ -1221,13 +1214,21 @@ void readgametype(MYFILE *f, char *gtname) if (word2[strlen(word2)-1] == '\n') word2[strlen(word2)-1] = '\0'; + if (word2lwr[strlen(word2lwr)-1] == '\n') + word2lwr[strlen(word2lwr)-1] = '\0'; i = atoi(word2); + // Name + if (fastcmp(word, "NAME")) + { + Z_Free(gametypes[num].name); + gametypes[num].name = Z_StrDup(word2lwr); + } // Game type rules - if (fastcmp(word, "RULES")) + else if (fastcmp(word, "RULES")) { // GTR_ - newgtrules = (UINT32)get_number(word2); + gametypes[num].rules = (UINT32)get_number(word2); } // Identifier else if (fastcmp(word, "IDENTIFIER")) @@ -1237,33 +1238,60 @@ void readgametype(MYFILE *f, char *gtname) } // Point and time limits else if (fastcmp(word, "DEFAULTPOINTLIMIT")) - newgtpointlimit = (INT32)i; + gametypes[num].pointlimit = (INT32)i; else if (fastcmp(word, "DEFAULTTIMELIMIT")) - newgttimelimit = (INT32)i; + gametypes[num].timelimit = (INT32)i; // Level platter else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR")) - newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2); + { + INT32 color = (INT32)i; + if (color >= 0 && color <= 255) + { + newgtleftcolor = newgtrightcolor = (UINT8)color; + has_desc_colors[0] = has_desc_colors[1] = true; + } + else + deh_warning("readgametype %d: Level platter header color %d out of range (0 - 255)", num, i); + } else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR")) - newgtleftcolor = (UINT8)get_number(word2); + { + INT32 color = (INT32)i; + if (color >= 0 && color <= 255) + { + newgtleftcolor = (UINT8)color; + has_desc_colors[0] = true; + } + else + deh_warning("readgametype %d: Level platter header left color %d out of range (0 - 255)", num, i); + } else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR")) - newgtrightcolor = (UINT8)get_number(word2); + { + INT32 color = (INT32)i; + if (color >= 0 && color < 255) + { + newgtrightcolor = (UINT8)color; + has_desc_colors[1] = true; + } + else + deh_warning("readgametype %d: Level platter header right color %d out of range (0 - 255)", num, i); + } // Rankings type else if (fastcmp(word, "RANKINGTYPE")) { // Case insensitive - newgtrankingstype = (int)get_number(word2); + gametypes[num].rankings_type = (int)get_number(word2); } // Intermission type else if (fastcmp(word, "INTERMISSIONTYPE")) { // Case sensitive - newgtinttype = (int)get_number(word2lwr); + gametypes[num].intermission_type = (int)get_number(word2lwr); } // Type of level else if (fastcmp(word, "TYPEOFLEVEL")) { if (i) // it's just a number - newgttol = (UINT32)i; + gametypes[num].typeoflevel = (UINT32)i; else { UINT32 tol = 0; @@ -1273,28 +1301,28 @@ void readgametype(MYFILE *f, char *gtname) if (fasticmp(tmp, TYPEOFLEVEL[i].name)) break; if (!TYPEOFLEVEL[i].name) - deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp); + deh_warning("readgametype %d: unknown typeoflevel flag %s\n", num, tmp); tol |= TYPEOFLEVEL[i].flag; } while((tmp = strtok(NULL,",")) != NULL); - newgttol = tol; + gametypes[num].typeoflevel = tol; } } - // The SOC probably provided gametype rules as words, - // instead of using the RULES keyword. - // Like for example "NOSPECTATORSPAWN = TRUE". - // This is completely valid, and looks better anyway. + // This SOC probably provided gametype rules as words, instead of using the RULES keyword. + // (For example, "NOSPECTATORSPAWN = TRUE") else { UINT32 wordgt = 0; for (j = 0; GAMETYPERULE_LIST[j]; j++) if (fastcmp(word, GAMETYPERULE_LIST[j])) { wordgt |= (1<<j); - if (i || word2[0] == 'T' || word2[0] == 'Y') - newgtrules |= wordgt; + if (word2[0] == 'T' || word2[0] == 'Y') + gametypes[num].rules |= wordgt; + else if (word2[0] == 'F' || word2[0] == 'N') + gametypes[num].rules &= ~wordgt; break; } if (!wordgt) - deh_warning("readgametype %s: unknown word '%s'", gtname, word); + deh_warning("readgametype %d: unknown word '%s'", num, word); } } } while (!myfeof(f)); // finish when the line is empty @@ -1304,38 +1332,26 @@ void readgametype(MYFILE *f, char *gtname) if (word2lwr) Z_Free(word2lwr); - // Ran out of gametype slots - if (gametypecount == NUMGAMETYPEFREESLOTS) - { - CONS_Alert(CONS_WARNING, "Ran out of free gametype slots!\n"); - return; - } - - // Add the new gametype - newgtidx = G_AddGametype(newgtrules); - G_AddGametypeTOL(newgtidx, newgttol); - G_SetGametypeDescription(newgtidx, gtdescription, newgtleftcolor, newgtrightcolor); - - // Not covered by G_AddGametype alone. - if (newgtrankingstype == -1) - newgtrankingstype = newgtidx; - gametypes[newgtidx].rankings_type = newgtrankingstype; - gametypes[newgtidx].intermission_type = newgtinttype; - gametypes[newgtidx].pointlimit = newgtpointlimit; - gametypes[newgtidx].timelimit = newgttimelimit; - - // Write the new gametype name. - gametypes[newgtidx].name = Z_StrDup(gtname); + if (gtdescription[0]) + G_SetGametypeDescription(num, gtdescription); + if (has_desc_colors[0]) + G_SetGametypeDescriptionLeftColor(num, newgtleftcolor); + if (has_desc_colors[1]) + G_SetGametypeDescriptionRightColor(num, newgtrightcolor); // Write the constant name. - if (gtconst[0] == '\0') - strncpy(gtconst, gtname, MAXLINELEN); - G_AddGametypeConstant(newgtidx, gtconst); + if (gametypes[num].constant_name == NULL) + { + if (gtconst[0] == '\0') + G_AddGametypeConstant(num, gtname); + else + G_AddGametypeConstant(num, gtconst); + } + else if (gtconst[0] != '\0') + G_AddGametypeConstant(num, gtconst); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); - - CONS_Printf("Added gametype %s\n", gametypes[newgtidx].name); } void readlevelheader(MYFILE *f, INT32 num) @@ -4151,6 +4167,22 @@ skincolornum_t get_skincolor(const char *word) return SKINCOLOR_GREEN; } +INT16 get_gametype(const char *word) +{ + INT16 i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("GT_",word,3)) + word += 3; // take off the GT_ + for (i = 0; i < gametypecount; i++) + { + if (fastcmp(word, gametypes[i].constant_name + 3)) + return i; + } + deh_warning("Couldn't find gametype named 'GT_%s'",word); + return GT_COOP; +} + spritenum_t get_sprite(const char *word) { // Returns the value of SPR_ enumerations spritenum_t i; diff --git a/src/deh_soc.h b/src/deh_soc.h index 029390133761c597c88cefb679cc847f8ce5e520..a060e72e3eec67419808bfd77aea5af595a7991d 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -54,9 +54,9 @@ playersprite_t get_sprite2(const char *word); sfxenum_t get_sfx(const char *word); hudnum_t get_huditem(const char *word); menutype_t get_menutype(const char *word); -//INT16 get_gametype(const char *word); -//powertype_t get_power(const char *word); skincolornum_t get_skincolor(const char *word); +INT16 get_gametype(const char *word); +UINT8 get_team(const char *word); void readwipes(MYFILE *f); void readmaincfg(MYFILE *f); @@ -71,7 +71,8 @@ void readmenu(MYFILE *f, INT32 num); void readtextprompt(MYFILE *f, INT32 num); void readcutscene(MYFILE *f, INT32 num); void readlevelheader(MYFILE *f, INT32 num); -void readgametype(MYFILE *f, char *gtname); +void readgametype(MYFILE *f, INT32 num); +void readteam(MYFILE *f, INT32 num); void readsprite2(MYFILE *f, INT32 num); void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2); #ifdef HWRENDER diff --git a/src/dehacked.c b/src/dehacked.c index fd2a701715e17ce7dab0b6c829147113844972fe..51f960ac30b6b89d677b00d5c117a8b942365059 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -172,9 +172,9 @@ static void ignorelines(MYFILE *f) static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - char textline[MAXLINELEN]; char *word; char *word2; + char word2lwr[MAXLINELEN]; INT32 i; if (!deh_loaded) @@ -189,7 +189,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) while (!myfeof(f)) { myfgets(s, MAXLINELEN, f); - memcpy(textline, s, MAXLINELEN); if (s[0] == '\n' || s[0] == '#') continue; @@ -216,10 +215,14 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) continue; } word2 = strtok(NULL, " "); + word2lwr[0] = '\0'; if (word2) { + strcpy(word2lwr, word2); strupr(word2); if (word2[strlen(word2) - 1] == '\n') word2[strlen(word2) - 1] = '\0'; + if (word2lwr[strlen(word2lwr) - 1] == '\n') + word2lwr[strlen(word2lwr) - 1] = '\0'; i = atoi(word2); } else @@ -381,33 +384,49 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } else if (fastcmp(word, "GAMETYPE")) { - // Get the gametype name from textline - // instead of word2, so that gametype names - // aren't allcaps - INT32 c; - for (c = 0; c < MAXLINELEN; c++) + char *gtname = NULL; + if (word2lwr[0]) { - if (textline[c] == '\0') - break; - if (textline[c] == ' ') + gtname = word2lwr; + + for (size_t j = 0; j < strlen(gtname); j++) { - char *gtname = (textline+c+1); - if (gtname) + if (gtname[j] == '\0') + break; + if (gtname[j] < 32 || gtname[j] == '\n') { - // remove funny characters - INT32 j; - for (j = 0; j < (MAXLINELEN - c); j++) - { - if (gtname[j] == '\0') - break; - if (gtname[j] < 32) - gtname[j] = '\0'; - } - readgametype(f, gtname); + gtname[j] = '\0'; + break; } - break; } } + + if (!gtname || !strlen(gtname)) + { + deh_warning("Invalid gametype name"); + ignorelines(f); + } + else + { + INT32 gametype_id = G_GetGametypeByName(gtname); + if (gametype_id == -1) + { + if (!strncmp(gtname, "GT_", 3)) + gametype_id = get_gametype(gtname + 3); + else if (gametypecount != NUMGAMETYPEFREESLOTS) + { + gametype_id = G_AddGametype(); + CONS_Printf("Added gametype %s\n", gtname); + } + else + deh_warning("Ran out of free gametype slots"); + } + + if (gametype_id != -1) + readgametype(f, gametype_id); + else + ignorelines(f); + } } else if (fastcmp(word, "CUTSCENE")) { diff --git a/src/g_game.c b/src/g_game.c index 3bd7c3db67150785b58f3bf57243e23c1c82249b..d870208c3822d3e6423a03256ec9ebb271cb80a5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3520,16 +3520,17 @@ void G_SetGametype(INT16 gtype) // // Adds a gametype. Returns the new gametype number. // -INT16 G_AddGametype(UINT32 rules) +INT16 G_AddGametype(void) { INT16 newgtype = gametypecount; gametypecount++; gametypes[newgtype].name = Z_StrDup("???"); - gametypes[newgtype].rules = rules; + gametypes[newgtype].rules = 0; - // Update gametype_cons_t accordingly. - G_UpdateGametypeSelections(); + G_SetGametypeDescription(newgtype, "???"); + G_SetGametypeDescriptionLeftColor(newgtype, 54); + G_SetGametypeDescriptionRightColor(newgtype, 54); return newgtype; } @@ -3567,20 +3568,32 @@ void G_UpdateGametypeSelections(void) } gametype_cons_t[NUMGAMETYPES].value = 0; gametype_cons_t[NUMGAMETYPES].strvalue = NULL; + + cv_newgametype.defaultvalue = gametype_cons_t[0].strvalue; + + if (cv_newgametype.string && G_GetGametypeByName(cv_newgametype.string) == -1) + { + cv_newgametype.value = 0; + cv_newgametype.string = gametype_cons_t[0].strvalue; + } } -// -// G_SetGametypeDescription -// -// Set a description for the specified gametype. -// (Level platter) -// -void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor) +void G_SetGametypeDescription(INT16 gtype, const char *descriptiontext) +{ + if (descriptiontext) + strlcpy(gametypedesc[gtype].notes, descriptiontext, sizeof gametypedesc[gtype].notes); + else + memset(gametypedesc[gtype].notes, 0, sizeof gametypedesc[gtype].notes); +} + +void G_SetGametypeDescriptionLeftColor(INT16 gtype, UINT8 color) { - if (descriptiontext != NULL) - strncpy(gametypedesc[gtype].notes, descriptiontext, 441); - gametypedesc[gtype].col[0] = leftcolor; - gametypedesc[gtype].col[1] = rightcolor; + gametypedesc[gtype].col[0] = color; +} + +void G_SetGametypeDescriptionRightColor(INT16 gtype, UINT8 color) +{ + gametypedesc[gtype].col[1] = color; } tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = { @@ -3629,16 +3642,6 @@ void G_AddTOL(UINT32 newtol, const char *tolname) TYPEOFLEVEL[i].flag = newtol; } -// -// G_AddGametypeTOL -// -// Assigns a type of level to a gametype. -// -void G_AddGametypeTOL(INT16 gtype, UINT32 newtol) -{ - gametypes[gtype].typeoflevel = newtol; -} - // // G_GetGametypeByName // diff --git a/src/g_game.h b/src/g_game.h index 97e38d88a131de729f2c9d3c2d280dae2d0b1d31..7b2e6620bb62778bf3c007044220ffb6b3243fbb 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -193,12 +193,14 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives); void G_SetGametype(INT16 gametype); void G_InitGametypes(void); -INT16 G_AddGametype(UINT32 rules); +INT16 G_AddGametype(void); void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); void G_UpdateGametypeSelections(void); void G_AddTOL(UINT32 newtol, const char *tolname); -void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); -void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor); + +void G_SetGametypeDescription(INT16 gtype, const char *descriptiontext); +void G_SetGametypeDescriptionLeftColor(INT16 gtype, UINT8 color); +void G_SetGametypeDescriptionRightColor(INT16 gtype, UINT8 color); INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 5fcd0f9b22bfe63d94f13e726e1f7784e5199ad0..e4aae50a8aa65b0ff6833661dc57367d45183999 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3553,15 +3553,14 @@ static int lib_gAddGametype(lua_State *L) char *gtname = NULL; char *gtconst = NULL; - const char *gtdescription = NULL; - INT16 newgtidx = 0; + char *gtdescription = NULL; UINT32 newgtrules = 0; UINT32 newgttol = 0; INT32 newgtpointlimit = 0; INT32 newgttimelimit = 0; - UINT8 newgtleftcolor = 0; - UINT8 newgtrightcolor = 0; - INT16 newgtrankingstype = -1; + UINT8 newgtleftcolor = 54; + UINT8 newgtrightcolor = 54; + INT16 newgtrankingstype = RANKINGS_DEFAULT; int newgtinttype = 0; luaL_checktype(L, 1, LUA_TTABLE); @@ -3651,36 +3650,47 @@ static int lib_gAddGametype(lua_State *L) // Set defaults if (gtname == NULL) gtname = Z_StrDup("Unnamed gametype"); - if (gtdescription == NULL) - gtdescription = Z_StrDup("???"); + + if (G_GetGametypeByName(gtname) != -1) + { + luaL_error(L, "gametype %s already exists", gtname); + Z_Free(gtname); + Z_Free(gtconst); + Z_Free(gtdescription); + return 0; + } // Add the new gametype - newgtidx = G_AddGametype(newgtrules); - G_AddGametypeTOL(newgtidx, newgttol); - G_SetGametypeDescription(newgtidx, NULL, newgtleftcolor, newgtrightcolor); - strncpy(gametypedesc[newgtidx].notes, gtdescription, 441); - - // Not covered by G_AddGametype alone. - if (newgtrankingstype == -1) - newgtrankingstype = newgtidx; - gametypes[newgtidx].rankings_type = newgtrankingstype; - gametypes[newgtidx].intermission_type = newgtinttype; - gametypes[newgtidx].pointlimit = newgtpointlimit; - gametypes[newgtidx].timelimit = newgttimelimit; - - // Write the new gametype name. - gametypes[newgtidx].name = gtname; - - // Write the constant name. - if (gtconst == NULL) - gtconst = gtname; - G_AddGametypeConstant(newgtidx, gtconst); - - // Update gametype_cons_t accordingly. + INT16 gtype = G_AddGametype(); + + gametype_t *gt = &gametypes[gtype]; + + gt->name = gtname; + + if (gtconst) + G_AddGametypeConstant(gtype, gtconst); + else + G_AddGametypeConstant(gtype, gtname); + + if (gtdescription) + G_SetGametypeDescription(gtype, gtdescription); + G_SetGametypeDescriptionLeftColor(gtype, newgtleftcolor); + G_SetGametypeDescriptionRightColor(gtype, newgtrightcolor); + + gt->rules = newgtrules; + gt->typeoflevel = newgttol; + gt->rankings_type = newgtrankingstype; + gt->intermission_type = newgtinttype; + gt->pointlimit = newgtpointlimit; + gt->timelimit = newgttimelimit; + G_UpdateGametypeSelections(); - // done - CONS_Printf("Added gametype %s\n", gametypes[newgtidx].name); + CONS_Printf("Added gametype %s\n", gt->name); + + Z_Free(gtconst); + Z_Free(gtdescription); + return 0; } diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index bb453fd613ea8af3fb13bcee384bab4f97e54a43..40c20576f9084d7ff44e4a7d48d62a0fd1e3028a 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -2280,7 +2280,12 @@ static void Command_Teamchange_f(void) if (COM_Argc() <= 1) { if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "spectator or playing"); else @@ -2294,7 +2299,7 @@ static void Command_Teamchange_f(void) NetPacket.packet.newteam = 1; else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))) NetPacket.packet.newteam = 0; else error = true; @@ -2317,7 +2322,12 @@ static void Command_Teamchange_f(void) if (error) { if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "spectator or playing"); return; @@ -2376,9 +2386,14 @@ static void Command_Teamchange2_f(void) if (COM_Argc() <= 1) { if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "spectator or playing"); else CONS_Alert(CONS_NOTICE, M_GetText("This command cannot be used in this gametype.\n")); return; @@ -2390,7 +2405,7 @@ static void Command_Teamchange2_f(void) NetPacket.packet.newteam = 1; else if (!strcasecmp(COM_Argv(1), "blue") || !strcasecmp(COM_Argv(1), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")) + else if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))) NetPacket.packet.newteam = 0; else error = true; @@ -2414,7 +2429,12 @@ static void Command_Teamchange2_f(void) if (error) { if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "spectator or playing"); return; @@ -2481,7 +2501,12 @@ static void Command_ServerTeamChange_f(void) if (G_TagGametype()) CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); else @@ -2508,7 +2533,7 @@ static void Command_ServerTeamChange_f(void) NetPacket.packet.newteam = 1; else if (!strcasecmp(COM_Argv(2), "blue") || !strcasecmp(COM_Argv(2), "2")) NetPacket.packet.newteam = 2; - else if (!strcasecmp(COM_Argv(2), "spectator") || !strcasecmp(COM_Argv(2), "0")) + else if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))) NetPacket.packet.newteam = 0; else error = true; @@ -2533,7 +2558,12 @@ static void Command_ServerTeamChange_f(void) if (G_TagGametype()) CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + { + if (G_GametypeHasSpectators()) + CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + else + CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red or blue"); + } else if (G_GametypeHasSpectators()) CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); return; diff --git a/src/p_mobj.c b/src/p_mobj.c index 7a5aaf42497c422f9d5d745aee99dafff011ae6f..eb5c7a0af1e8324c3b192e0dc00f8f0fb875c892 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11607,7 +11607,12 @@ void P_SpawnPlayer(INT32 playernum) { // Fix stupid non spectator spectators. if (!p->spectator && !p->ctfteam) - p->spectator = true; + { + if (G_GametypeHasSpectators()) + p->spectator = true; + else + p->ctfteam = 1; + } } if ((netgame || multiplayer) && ((gametyperules & GTR_SPAWNINVUL) || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS))