Allow replacing gametype data through SOC

Make other fixes
This commit is contained in:
Lactozilla 2023-08-05 22:01:50 -03:00
parent f2bbc445a0
commit b9cab85df0
9 changed files with 524 additions and 259 deletions

View file

@ -2360,7 +2360,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "team name");
}
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "spectator or playing");
else
@ -2370,7 +2375,7 @@ static void Command_Teamchange_f(void)
if (G_GametypeHasTeams())
{
if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))
if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")))
NetPacket.packet.newteam = 0;
else
{
@ -2378,7 +2383,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
@ -2407,7 +2412,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "team name");
}
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam <team>: switch to a new team (%s)\n"), "spectator or playing");
return;
@ -2466,9 +2476,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "team name");
}
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;
@ -2476,7 +2491,7 @@ static void Command_Teamchange2_f(void)
if (G_GametypeHasTeams())
{
if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))
if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")))
NetPacket.packet.newteam = 0;
else
{
@ -2484,7 +2499,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
@ -2514,7 +2529,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "team name");
}
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("changeteam2 <team>: switch to a new team (%s)\n"), "spectator or playing");
return;
@ -2581,7 +2601,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "team name");
}
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
else
@ -2604,7 +2629,7 @@ static void Command_ServerTeamChange_f(void)
}
else if (G_GametypeHasTeams())
{
if (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0"))
if (G_GametypeHasSpectators() && (!strcasecmp(COM_Argv(1), "spectator") || !strcasecmp(COM_Argv(1), "0")))
NetPacket.packet.newteam = 0;
else
{
@ -2612,7 +2637,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
@ -2643,7 +2668,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"), "team name or spectator");
{
if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "team name or spectator");
else
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "team name");
}
else if (G_GametypeHasSpectators())
CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing");
return;

View file

@ -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"))
{
@ -578,10 +575,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;

View file

@ -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"))
{
@ -1139,8 +1138,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;
@ -1148,25 +1146,20 @@ 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];
UINT8 teamcount = 0;
UINT8 newgtleftcolor, newgtrightcolor;
boolean has_desc_colors[2] = { false, false };
UINT8 teamcount = gametypes[num].teams.num;
UINT8 teamlist[MAXTEAMS];
boolean has_teams = false;
// Empty strings.
gtdescription[0] = '\0';
gtconst[0] = '\0';
strcpy(gtdescription, "???");
memset(gtconst, 0, sizeof(gtconst));
memset(gtdescription, 0, sizeof(gtconst));
memcpy(teamlist, gametypes[num].teams.list, sizeof(teamlist[0]) * teamcount);
do
{
@ -1221,6 +1214,212 @@ void readgametype(MYFILE *f, char *gtname)
continue;
}
word2 = strtok(NULL, " = ");
if (word2)
{
if (!word2lwr)
word2lwr = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
strlcpy(word2lwr, word2, MAXLINELEN);
strupr(word2);
}
else
break;
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
else if (fastcmp(word, "RULES"))
{
// GTR_
gametypes[num].rules = (UINT32)get_number(word2);
}
// Identifier
else if (fastcmp(word, "IDENTIFIER"))
{
// GT_
strncpy(gtconst, word2, MAXLINELEN);
}
// Point and time limits
else if (fastcmp(word, "DEFAULTPOINTLIMIT"))
gametypes[num].pointlimit = (INT32)i;
else if (fastcmp(word, "DEFAULTTIMELIMIT"))
gametypes[num].timelimit = (INT32)i;
// Level platter
else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR"))
{
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"))
{
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"))
{
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
gametypes[num].rankings_type = (int)get_number(word2);
}
// Intermission type
else if (fastcmp(word, "INTERMISSIONTYPE"))
{
// Case sensitive
gametypes[num].intermission_type = (int)get_number(word2lwr);
}
// Type of level
else if (fastcmp(word, "TYPEOFLEVEL"))
{
if (i) // it's just a number
gametypes[num].typeoflevel = (UINT32)i;
else
{
UINT32 tol = 0;
tmp = strtok(word2,",");
do {
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fasticmp(tmp, TYPEOFLEVEL[i].name))
break;
if (!TYPEOFLEVEL[i].name)
deh_warning("readgametype %d: unknown typeoflevel flag %s\n", num, tmp);
tol |= TYPEOFLEVEL[i].flag;
} while((tmp = strtok(NULL,",")) != NULL);
gametypes[num].typeoflevel = tol;
}
}
// Teams
else if (fastcmp(word, "TEAMLIST"))
{
tmp = strtok(word2,",");
do {
if (teamcount == MAXTEAMS)
{
deh_warning("readgametype %d: too many teams\n", num);
break;
}
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.
// (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 (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 %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);
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);
// Copy the teams
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)
{
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();
}
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)
{
@ -1236,105 +1435,83 @@ void readgametype(MYFILE *f, char *gtname)
word2[strlen(word2)-1] = '\0';
i = atoi(word2);
// Game type rules
if (fastcmp(word, "RULES"))
if (fastcmp(word, "NAME"))
{
// GTR_
newgtrules = (UINT32)get_number(word2);
Z_Free(team->name);
team->name = Z_StrDup(word2lwr);
}
// Identifier
else if (fastcmp(word, "IDENTIFIER"))
else if (fastcmp(word, "FLAGNAME"))
{
// GT_
strncpy(gtconst, word2, MAXLINELEN);
Z_Free(team->flag_name);
team->flag_name = Z_StrDup(word2lwr);
}
// Point and time limits
else if (fastcmp(word, "DEFAULTPOINTLIMIT"))
newgtpointlimit = (INT32)i;
else if (fastcmp(word, "DEFAULTTIMELIMIT"))
newgttimelimit = (INT32)i;
// Level platter
else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR"))
newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2);
else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR"))
newgtleftcolor = (UINT8)get_number(word2);
else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR"))
newgtrightcolor = (UINT8)get_number(word2);
// Rankings type
else if (fastcmp(word, "RANKINGTYPE"))
else if (fastcmp(word, "FLAG"))
{
// Case insensitive
newgtrankingstype = (int)get_number(word2);
team->flag = (UINT16)get_number(word2);
}
// Intermission type
else if (fastcmp(word, "INTERMISSIONTYPE"))
else if (fastcmp(word, "FLAGTYPE"))
{
// Case sensitive
newgtinttype = (int)get_number(word2lwr);
}
// Type of level
else if (fastcmp(word, "TYPEOFLEVEL"))
{
if (i) // it's just a number
newgttol = (UINT32)i;
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
{
UINT32 tol = 0;
tmp = strtok(word2,",");
do {
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fasticmp(tmp, TYPEOFLEVEL[i].name))
break;
if (!TYPEOFLEVEL[i].name)
deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp);
tol |= TYPEOFLEVEL[i].flag;
} while((tmp = strtok(NULL,",")) != NULL);
newgttol = tol;
deh_warning("readteam %d: Thing %d out of range (1 - %d)", num, i, NUMMOBJTYPES-1);
}
}
// Teams
else if (fastcmp(word, "TEAMLIST"))
else if (fastcmp(word, "COLOR"))
{
tmp = strtok(word2,",");
do {
if (teamcount == MAXTEAMS)
{
deh_warning("readgametype %s: too many teams\n", gtname);
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
{
teamlist[teamcount++] = team_id;
}
} while((tmp = strtok(NULL,",")) != NULL);
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);
}
// 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;
break;
}
if (!wordgt)
deh_warning("readgametype %s: unknown word '%s'", gtname, word);
deh_warning("readteam %d: unknown word '%s'", num, word);
}
}
} while (!myfeof(f)); // finish when the line is empty
@ -1344,43 +1521,8 @@ 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;
// Copy the teams
gametypes[newgtidx].teams.num = teamcount;
if (teamcount)
memcpy(gametypes[newgtidx].teams.list, teamlist, sizeof(teamlist[0]) * teamcount);
// Write the new gametype name.
gametypes[newgtidx].name = Z_StrDup(gtname);
// Write the constant name.
if (gtconst[0] == '\0')
strncpy(gtconst, gtname, MAXLINELEN);
G_AddGametypeConstant(newgtidx, gtconst);
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
CONS_Printf("Added gametype %s\n", gametypes[newgtidx].name);
ST_LoadTeamIcons();
G_UpdateTeamSelection();
}
void readlevelheader(MYFILE *f, INT32 num)
@ -4195,6 +4337,38 @@ 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;
}
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;

View file

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

View file

@ -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,61 @@ 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, "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"))
{

View file

@ -3597,11 +3597,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;
}
@ -3624,15 +3636,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;
G_UpdateGametypeSelections();
G_SetGametypeDescription(newgtype, "???");
G_SetGametypeDescriptionLeftColor(newgtype, 54);
G_SetGametypeDescriptionRightColor(newgtype, 54);
return newgtype;
}
@ -3670,20 +3684,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 != NULL)
strncpy(gametypedesc[gtype].notes, descriptiontext, 441);
gametypedesc[gtype].col[0] = leftcolor;
gametypedesc[gtype].col[1] = rightcolor;
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)
{
gametypedesc[gtype].col[0] = color;
}
void G_SetGametypeDescriptionRightColor(INT16 gtype, UINT8 color)
{
gametypedesc[gtype].col[1] = color;
}
tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
@ -3732,16 +3758,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
//

View file

@ -193,12 +193,14 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives);
void G_SetGametype(INT16 gametype);
void G_InitGametypes(void);
void G_UpdateTeamSelection(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);

View file

@ -3411,15 +3411,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;
UINT8 teamcount = 0;
UINT8 teamlist[MAXTEAMS];
@ -3540,40 +3539,52 @@ 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, gtdescription, newgtleftcolor, newgtrightcolor);
INT16 gtype = G_AddGametype();
// 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;
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;
// Copy the teams
gametypes[newgtidx].teams.num = teamcount;
gt->teams.num = teamcount;
if (teamcount)
memcpy(gametypes[newgtidx].teams.list, teamlist, sizeof(teamlist[0]) * teamcount);
memcpy(gt->teams.list, teamlist, sizeof(teamlist[0]) * teamcount);
// 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.
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;
}

View file

@ -11573,7 +11573,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;
}
// Fix team colors.
// This code isn't being done right somewhere else. Oh well.