diff --git a/src/deh_lua.c b/src/deh_lua.c index 3571212f7f84fbe61e4858473226b37392b3bb32..a08477b26d95584405c383670768823115fc6fc6 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -133,19 +133,16 @@ static inline int lib_freeslot(lua_State *L) } else if (fastcmp(type, "TEAM")) { - UINT8 i; - for (i = 0; i < MAXTEAMS; i++) - if (!teamnames[i]) { - CONS_Printf("Team TEAM_%s allocated.\n",word); - teamnames[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); - strcpy(teamnames[i],word); - lua_pushinteger(L, i); - numteams++; - r++; - break; - } - if (i == MAXTEAMS) + if (numteams == MAXTEAMS) CONS_Alert(CONS_WARNING, "Ran out of free team slots!\n"); + UINT8 i = numteams; + CONS_Printf("Team TEAM_%s allocated.\n",word); + teamnames[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); + strcpy(teamnames[i],word); + lua_pushinteger(L, i); + numteams++; + r++; + break; } else if (fastcmp(type, "SPR2")) { @@ -579,10 +576,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) } else if (fastncmp("TEAM_",word,5)) { p = word+5; - for (i = 0; i < MAXTEAMS; i++) + for (i = 0; i < numteams; i++) { - if (!teamnames[i]) - break; if (fastcmp(p, teamnames[i])) { CacheAndPushConstant(L, word, i); return 1; diff --git a/src/deh_soc.c b/src/deh_soc.c index 0130b9a7a47c140bfc004b6cea459b88fe67854e..ad47c535ddd9421e477b24d3a5004f66eb4bc590 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -475,13 +475,12 @@ void readfreeslots(MYFILE *f) } else if (fastcmp(type, "TEAM")) { - for (i = 0; i < MAXTEAMS; i++) - if (!teamnames[i]) { - teamnames[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); - strcpy(teamnames[i],word); - numteams++; - break; - } + if (numteams < MAXTEAMS) + { + teamnames[numteams] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); + strcpy(teamnames[numteams],word); + numteams++; + } } else if (fastcmp(type, "SPR2")) { @@ -1152,8 +1151,9 @@ void readgametype(MYFILE *f, INT32 num) char gtconst[MAXLINELEN]; char gtdescription[441]; - UINT8 teamcount = 0; + UINT8 teamcount = gametypes[num].teams.num; UINT8 teamlist[MAXTEAMS]; + boolean has_teams = false; UINT8 newgtleftcolor, newgtrightcolor; boolean has_desc_colors[2] = { false, false }; @@ -1329,26 +1329,20 @@ void readgametype(MYFILE *f, INT32 num) do { if (teamcount == MAXTEAMS) { - deh_warning("readgametype %s: too many teams\n", gtname); + deh_warning("readgametype %d: too many teams\n", num); break; } - UINT8 team_id = TEAM_NONE; - for (i = 1; i < MAXTEAMS; i++) - { - if (!teamnames[i]) - break; - if (fasticmp(tmp, teamnames[i])) - { - team_id = i; - break; - } - } - if (team_id == TEAM_NONE) - deh_warning("readgametype %s: unknown team %s\n", gtname, tmp); - else + char *tmp2 = Z_StrDup(tmp); + strupr(tmp2); + UINT8 team_id = get_team(tmp2); + if (team_id != TEAM_NONE) { teamlist[teamcount++] = team_id; + has_teams = true; } + else + deh_warning("readgametype %d: unknown team %s\n", num, tmp); + Z_Free(tmp2); } while((tmp = strtok(NULL,",")) != NULL); } // This SOC probably provided gametype rules as words, instead of using the RULES keyword. @@ -1384,9 +1378,12 @@ void readgametype(MYFILE *f, INT32 num) G_SetGametypeDescriptionRightColor(num, newgtrightcolor); // Copy the teams - gametypes[num].teams.num = teamcount; - if (teamcount) - memcpy(gametypes[num].teams.list, teamlist, sizeof(teamlist[0]) * teamcount); + if (has_teams) + { + gametypes[num].teams.num = teamcount; + if (teamcount) + memcpy(gametypes[num].teams.list, teamlist, sizeof(teamlist[0]) * teamcount); + } // Write the constant name. if (gametypes[num].constant_name == NULL) @@ -1403,6 +1400,133 @@ void readgametype(MYFILE *f, INT32 num) G_UpdateGametypeSelections(); } +void readteam(MYFILE *f, INT32 num) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word; + char *word2, *word2lwr = NULL; + INT32 i; + + team_t *team = &teams[num]; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + word = strtok(s, " "); + if (word) + strupr(word); + else + break; + + word2 = strtok(NULL, " = "); + if (word2) + { + if (!word2lwr) + word2lwr = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + strcpy(word2lwr, word2); + strupr(word2); + } + else + break; + + if (word2[strlen(word2)-1] == '\n') + word2[strlen(word2)-1] = '\0'; + i = atoi(word2); + + if (fastcmp(word, "NAME")) + { + Z_Free(team->name); + team->name = Z_StrDup(word2lwr); + } + else if (fastcmp(word, "FLAGNAME")) + { + Z_Free(team->flag_name); + team->flag_name = Z_StrDup(word2lwr); + } + else if (fastcmp(word, "FLAG")) + { + team->flag = (UINT16)get_number(word2); + } + else if (fastcmp(word, "FLAGTYPE")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_mobjtype(word2); // find a thing by name + if (i < NUMMOBJTYPES && i > 0) + team->flag_mobj_type = i; + else + { + deh_warning("readteam %d: Thing %d out of range (1 - %d)", num, i, NUMMOBJTYPES-1); + } + } + else if (fastcmp(word, "COLOR")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_skincolor(word2); // find a skincolor by name + if (i && i < numskincolors) + team->color = i; + else + { + deh_warning("readteam %d: Color %d out of range (1 - %d)", num, i, numskincolors-1); + } + } + else if (fastcmp(word, "WEAPONCOLOR")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_skincolor(word2); // find a skincolor by name + if (i && i < numskincolors) + team->weapon_color = i; + else + { + deh_warning("readteam %d: Weapon color %d out of range (1 - %d)", num, i, numskincolors-1); + } + } + else if (fastcmp(word, "MISSILECOLOR")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_skincolor(word2); // find a skincolor by name + if (i && i < numskincolors) + team->missile_color = i; + else + { + deh_warning("readteam %d: Missile color %d out of range (1 - %d)", num, i, numskincolors-1); + } + } + else if (fastcmp(word, "ICON")) + { + G_SetTeamIcon(num, TEAM_ICON, word2lwr); + } + else if (fastcmp(word, "FLAGICON")) + { + G_SetTeamIcon(num, TEAM_ICON_FLAG, word2lwr); + } + else if (fastcmp(word, "GOTFLAGICON")) + { + G_SetTeamIcon(num, TEAM_ICON_GOT_FLAG, word2lwr); + } + else if (fastcmp(word, "MISSINGFLAGICON")) + { + G_SetTeamIcon(num, TEAM_ICON_MISSING_FLAG, word2lwr); + } + else + { + deh_warning("readteam %d: unknown word '%s'", num, word); + } + } + } while (!myfeof(f)); // finish when the line is empty + + // Free strings. + Z_Free(s); + if (word2lwr) + Z_Free(word2lwr); + + ST_LoadTeamIcons(); + G_UpdateTeamSelection(); +} + void readlevelheader(MYFILE *f, INT32 num) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -4232,6 +4356,22 @@ INT16 get_gametype(const char *word) return GT_COOP; } +UINT8 get_team(const char *word) +{ + UINT8 i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("TEAM_",word,5)) + word += 5; // take off the TEAM_ + for (i = 0; i < numteams; i++) + { + if (fastcmp(word, teamnames[i])) + return i; + } + deh_warning("Couldn't find team named 'TEAM_%s'",word); + return TEAM_NONE; +} + 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 dabf8e0a91c06139f2cf607783d224c48947e6af..a060e72e3eec67419808bfd77aea5af595a7991d 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -56,6 +56,7 @@ hudnum_t get_huditem(const char *word); menutype_t get_menutype(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,6 +72,7 @@ void readtextprompt(MYFILE *f, INT32 num); void readcutscene(MYFILE *f, INT32 num); void readlevelheader(MYFILE *f, INT32 num); 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 51f960ac30b6b89d677b00d5c117a8b942365059..2c00ff133067899d86599f3edffcdbb152824d95 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -428,6 +428,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) ignorelines(f); } } + else if (fastcmp(word, "TEAM")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_team(word2); // find a team by name + if (i >= 0 && i < MAXTEAMS) + readteam(f, i); + else + { + deh_warning("Team %d out of range (0 - %d)", i, MAXTEAMS); + ignorelines(f); + } + } else if (fastcmp(word, "CUTSCENE")) { if (i > 0 && i < 129) diff --git a/src/g_game.c b/src/g_game.c index ad7866c8ae29494ffa23571daeed70a14767efd9..5f070711128ce8c770d19ceaf1148086e692b7d2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3592,11 +3592,23 @@ void G_UpdateTeamSelection(void) i++; } + // If no selections were added, somehow, we add at least two fallbacks. + if (i == 0) + { + dummyteam_cons_t[i].value = 0; + dummyteam_cons_t[i].strvalue = "Spectator"; + i++; + + dummyteam_cons_t[i].value = 1; + dummyteam_cons_t[i].strvalue = "Playing"; + i++; + } + dummyteam_cons_t[i].value = 0; dummyteam_cons_t[i].strvalue = NULL; cv_dummyteam.defaultvalue = dummyteam_cons_t[0].strvalue; - cv_dummyteam.value = 0; + cv_dummyteam.value = dummyteam_cons_t[0].value; cv_dummyteam.string = cv_dummyteam.defaultvalue; } diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index bf694425d2888a00b48594b39521c150b9591d8d..0658387752ca37211da606d48ae88cdee8209215 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -2314,7 +2314,7 @@ static void Command_Teamchange_f(void) if (M_StringOnlyHasDigits(COM_Argv(1))) { newteam = atoi(COM_Argv(1)); - if (newteam >= teamsingame) + if (newteam == TEAM_NONE || newteam >= teamsingame) newteam = MAXTEAMS; } else @@ -2430,7 +2430,7 @@ static void Command_Teamchange2_f(void) if (M_StringOnlyHasDigits(COM_Argv(1))) { newteam = atoi(COM_Argv(1)); - if (newteam >= teamsingame) + if (newteam == TEAM_NONE || newteam >= teamsingame) newteam = MAXTEAMS; } else @@ -2567,7 +2567,7 @@ static void Command_ServerTeamChange_f(void) if (M_StringOnlyHasDigits(COM_Argv(1))) { newteam = atoi(COM_Argv(1)); - if (newteam >= teamsingame) + if (newteam == TEAM_NONE || newteam >= teamsingame) newteam = MAXTEAMS; } else