gametype_t

- New array of pointers to structures in memory (currently mixing static for base-game and Callocated for custom)
- Centralises a metric-ton of previously seperately handled properties into one struct
    - Gametype_Names[]
    - Gametype_ConstantNames[]
    - gametypetol[]
    - timelimits[]
    - pointlimits[]
    - gametypedefaultrules[]
- Don't attempt to guess custom gametype in Replay Hut (requires more work to make custom gametypes behave across the entire experience)
- I_Error if invalid gametype set
- gametyperules is deprecated since it will never be modified seperately from gametype (temporarily a #define, don't wanna bloat this commit too much)
This commit is contained in:
toaster 2022-12-26 01:07:57 +00:00
parent 59bc094fac
commit 185b36bd27
17 changed files with 189 additions and 234 deletions

View file

@ -930,7 +930,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
else
netbuffer->u.serverinfo.refusereason = 0;
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
strncpy(netbuffer->u.serverinfo.gametypename, gametypes[gametype]->name,
sizeof netbuffer->u.serverinfo.gametypename);
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();

View file

@ -1516,11 +1516,6 @@ void D_SRB2Main(void)
CON_SetLoadingProgress(LOADED_HUINIT);
memset(timelimits, 0, sizeof(timelimits));
memset(pointlimits, 0, sizeof(pointlimits));
timelimits[GT_BATTLE] = 2;
D_RegisterServerCommands();
D_RegisterClientCommands(); // be sure that this is called before D_CheckNetGame
R_RegisterEngineStuff();
@ -1802,7 +1797,7 @@ void D_SRB2Main(void)
if (newgametype == -1) // reached end of the list with no match
{
j = atoi(sgametype); // assume they gave us a gametype number, which is okay too
if (j >= 0 && j < gametypecount)
if (j >= 0 && j < numgametypes)
newgametype = (INT16)j;
}

View file

@ -481,10 +481,6 @@ consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_NETVAR|CV_CALL|CV_NO
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {MAX_LAPS, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, numlaps_cons_t, NumLaps_OnChange);
// Point and time limits for every gametype
INT32 pointlimits[NUMGAMETYPES];
INT32 timelimits[NUMGAMETYPES];
consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange);
consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL);
@ -553,8 +549,7 @@ char timedemo_csv_id[256];
boolean timedemo_quit;
INT16 gametype = GT_RACE;
UINT32 gametyperules = 0;
INT16 gametypecount = GT_FIRSTFREESLOT;
INT16 numgametypes = GT_FIRSTFREESLOT;
boolean forceresetplayers = false;
boolean deferencoremode = false;
@ -2526,7 +2521,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
CONS_Debug(DBG_GAMELOGIC, "Map change: mapnum=%d gametype=%d pencoremode=%d resetplayers=%d delay=%d skipprecutscene=%d\n",
mapnum, newgametype, pencoremode, resetplayers, delay, skipprecutscene);
if ((netgame || multiplayer) && !((gametype == newgametype) && (gametypedefaultrules[newgametype] & GTR_CAMPAIGN)))
if ((netgame || multiplayer) && !((gametype == newgametype) && (gametypes[newgametype]->rules & GTR_CAMPAIGN)))
FLS = false;
// Too lazy to change the input value for every instance of this function.......
@ -2595,7 +2590,7 @@ void D_SetupVote(void)
UINT8 secondgt = G_SometimesGetDifferentGametype();
INT16 votebuffer[4] = {-1,-1,-1,0};
if ((cv_kartencore.value == 1) && (gametypedefaultrules[gametype] & GTR_ENCORE))
if ((cv_kartencore.value == 1) && (gametyperules & GTR_ENCORE))
WRITEUINT8(p, (gametype|VOTEMODIFIER_ENCORE));
else
WRITEUINT8(p, gametype);
@ -2817,7 +2812,7 @@ static void Command_Map_f(void)
if (isdigit(gametypename[0]))
{
d = atoi(gametypename);
if (d >= 0 && d < gametypecount)
if (d >= 0 && d < numgametypes)
newgametype = d;
else
{
@ -2825,7 +2820,7 @@ static void Command_Map_f(void)
"Gametype number %d is out of range. Use a number between"
" 0 and %d inclusive. ...Or just use the name. :v\n",
d,
gametypecount-1);
numgametypes-1);
Z_Free(realmapname);
Z_Free(mapname);
return;
@ -2890,7 +2885,7 @@ static void Command_Map_f(void)
fromlevelselect =
( netgame || multiplayer ) &&
newgametype == gametype &&
gametypedefaultrules[newgametype] & GTR_CAMPAIGN;
gametypes[newgametype]->rules & GTR_CAMPAIGN;
}
}
@ -3023,7 +3018,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
gametype = READUINT8(*cp);
G_SetGametype(gametype); // I fear putting that macro as an argument
if (gametype < 0 || gametype >= gametypecount)
if (gametype < 0 || gametype >= numgametypes)
gametype = lastgametype;
else if (gametype != lastgametype)
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
@ -4807,8 +4802,8 @@ static void Command_ShowGametype_f(void)
const char *gametypestr = NULL;
// get name string for current gametype
if (gametype >= 0 && gametype < gametypecount)
gametypestr = Gametype_Names[gametype];
if (gametype >= 0 && gametype < numgametypes)
gametypestr = gametypes[gametype]->name;
if (gametypestr)
CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr);
@ -4987,10 +4982,10 @@ void D_GameTypeChanged(INT32 lastgametype)
{
const char *oldgt = NULL, *newgt = NULL;
if (lastgametype >= 0 && lastgametype < gametypecount)
oldgt = Gametype_Names[lastgametype];
if (gametype >= 0 && lastgametype < gametypecount)
newgt = Gametype_Names[gametype];
if (lastgametype >= 0 && lastgametype < numgametypes)
oldgt = gametypes[lastgametype]->name;
if (gametype >= 0 && gametype < numgametypes)
newgt = gametypes[gametype]->name;
if (oldgt && newgt)
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt);
@ -5002,11 +4997,11 @@ void D_GameTypeChanged(INT32 lastgametype)
{
if (!cv_timelimit.changed) // user hasn't changed limits
{
CV_SetValue(&cv_timelimit, timelimits[gametype]);
CV_SetValue(&cv_timelimit, gametypes[gametype]->timelimit);
}
if (!cv_pointlimit.changed)
{
CV_SetValue(&cv_pointlimit, pointlimits[gametype]);
CV_SetValue(&cv_pointlimit, gametypes[gametype]->pointlimit);
}
}
@ -5301,25 +5296,25 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
// Strip illegal Encore flag.
if ((gt & VOTEMODIFIER_ENCORE)
&& !(gametypedefaultrules[(gt & ~VOTEMODIFIER_ENCORE)] & GTR_ENCORE))
&& !(gametypes[(gt & ~VOTEMODIFIER_ENCORE)]->rules & GTR_ENCORE))
{
gt &= ~VOTEMODIFIER_ENCORE;
}
if ((gt & ~VOTEMODIFIER_ENCORE) >= gametypecount)
if ((gt & ~VOTEMODIFIER_ENCORE) >= numgametypes)
{
gt &= ~VOTEMODIFIER_ENCORE;
if (server)
I_Error("Got_SetupVotecmd: Internal gametype ID %d not found (gametypecount = %d)", gt, gametypecount);
I_Error("Got_SetupVotecmd: Internal gametype ID %d not found (numgametypes = %d)", gt, numgametypes);
CONS_Alert(CONS_WARNING, M_GetText("Vote setup with bad gametype ID %d received from %s\n"), gt, player_names[playernum]);
return;
}
if ((secondgt & ~VOTEMODIFIER_ENCORE) >= gametypecount)
if ((secondgt & ~VOTEMODIFIER_ENCORE) >= numgametypes)
{
secondgt &= ~VOTEMODIFIER_ENCORE;
if (server)
I_Error("Got_SetupVotecmd: Internal second gametype ID %d not found (gametypecount = %d)", secondgt, gametypecount);
I_Error("Got_SetupVotecmd: Internal second gametype ID %d not found (numgametypes = %d)", secondgt, numgametypes);
CONS_Alert(CONS_WARNING, M_GetText("Vote setup with bad second gametype ID %d received from %s\n"), secondgt, player_names[playernum]);
return;
}
@ -5339,11 +5334,11 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
// If third entry has an illelegal Encore flag... (illelegal!?)
if ((secondgt & VOTEMODIFIER_ENCORE)
&& !(gametypedefaultrules[(secondgt & ~VOTEMODIFIER_ENCORE)] & GTR_ENCORE))
&& !(gametypes[(secondgt & ~VOTEMODIFIER_ENCORE)]->rules & GTR_ENCORE))
{
secondgt &= ~VOTEMODIFIER_ENCORE;
// Apply it to the second entry instead, gametype permitting!
if (gametypedefaultrules[gt] & GTR_ENCORE)
if (gametypes[gt]->rules & GTR_ENCORE)
{
tempvotelevels[1][1] |= VOTEMODIFIER_ENCORE;
}

View file

@ -309,11 +309,16 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("GT_", word, 3)) {
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
i = 0;
while (gametypes[i] != NULL)
{
if (fastcmp(p, gametypes[i]->constant))
{
lua_pushinteger(L, i);
return 1;
}
i++;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}

View file

@ -764,13 +764,13 @@ void readgametype(MYFILE *f, char *gtname)
char *tmp;
INT32 i, j;
INT16 newgtidx = 0;
gametype_t *newgametype = NULL;
UINT32 newgtrules = 0;
UINT32 newgttol = 0;
INT32 newgtpointlimit = 0;
INT32 newgttimelimit = 0;
INT16 newgtrankingstype = -1;
int newgtinttype = 0;
UINT8 newgtinttype = 0;
char gtconst[MAXLINELEN];
// Empty strings.
@ -821,12 +821,6 @@ void readgametype(MYFILE *f, char *gtname)
newgtpointlimit = (INT32)i;
else if (fastcmp(word, "DEFAULTTIMELIMIT"))
newgttimelimit = (INT32)i;
// Rankings type
else if (fastcmp(word, "RANKINGTYPE"))
{
// Case insensitive
newgtrankingstype = (int)get_number(word2);
}
// Intermission type
else if (fastcmp(word, "INTERMISSIONTYPE"))
{
@ -879,36 +873,35 @@ void readgametype(MYFILE *f, char *gtname)
Z_Free(word2lwr);
// Ran out of gametype slots
if (gametypecount == NUMGAMETYPEFREESLOTS)
if (numgametypes == GT_LASTFREESLOT)
{
I_Error("Out of Gametype Freeslots while allocating \"%s\"\nLoad less addons to fix this.", gtname);
return;
}
// Add the new gametype
newgtidx = G_AddGametype(newgtrules);
G_AddGametypeTOL(newgtidx, newgttol);
newgametype = Z_Calloc(sizeof (gametype_t), PU_STATIC, NULL);
if (!newgametype)
{
I_Error("Out of memory allocating gametype \"%s\"", gtname);
}
// Not covered by G_AddGametype alone.
if (newgtrankingstype == -1)
newgtrankingstype = newgtidx;
gametyperankings[newgtidx] = newgtrankingstype;
intermissiontypes[newgtidx] = newgtinttype;
pointlimits[newgtidx] = newgtpointlimit;
timelimits[newgtidx] = newgttimelimit;
// Write the new gametype name.
Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname);
// Write the constant name.
if (gtconst[0] == '\0')
strncpy(gtconst, gtname, MAXLINELEN);
G_AddGametypeConstant(newgtidx, (const char *)gtconst);
newgametype->name = Z_StrDup((const char *)gtname);
newgametype->rules = newgtrules;
newgametype->constant = G_PrepareGametypeConstant((const char *)gtconst);
newgametype->tol = newgttol;
newgametype->intermission = newgtinttype;
newgametype->pointlimit = newgtpointlimit;
newgametype->timelimit = newgttimelimit;
gametypes[numgametypes++] = newgametype;
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]);
CONS_Printf("Added gametype %s\n", gtname);
}
void readlevelheader(MYFILE *f, char * name)
@ -3670,7 +3663,7 @@ sfxenum_t get_sfx(const char *word)
return atoi(word);
if (fastncmp("GT_",word,3))
word += 3; // take off the GT_
for (i = 0; i < NUMGAMETYPES; i++)
for (i = 0; i < MAXGAMETYPES; i++)
if (fastcmp(word, Gametype_ConstantNames[i]+3))
return i;
deh_warning("Couldn't find gametype named 'GT_%s'",word);

View file

@ -147,11 +147,6 @@ extern boolean addedtogame; // true after the server has added you
// Only true if >1 player. netgame => multiplayer but not (multiplayer=>netgame)
extern boolean multiplayer;
extern INT16 gametype;
extern UINT32 gametyperules;
extern INT16 gametypecount;
extern UINT8 splitscreen;
extern int r_splitscreen;
@ -454,7 +449,7 @@ extern mapheader_t** mapheaderinfo;
extern INT32 nummapheaders, mapallocsize;
// Gametypes
#define NUMGAMETYPEFREESLOTS (NUMGAMETYPES-GT_FIRSTFREESLOT)
#define NUMGAMETYPEFREESLOTS (MAXGAMETYPES-GT_FIRSTFREESLOT)
enum GameType
{
@ -463,9 +458,29 @@ enum GameType
GT_FIRSTFREESLOT,
GT_LASTFREESLOT = 127, // Previously (GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1) - it would be necessary to rewrite VOTEMODIFIER_ENCORE to go higher than this.
NUMGAMETYPES
MAXGAMETYPES
};
// If you alter this list, update deh_tables.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c
// If you alter this list, update defaultgametypes and *gametypes in g_game.c
#define MAXTOL (1<<31)
#define NUMBASETOLNAMES (5)
#define NUMTOLNAMES (NUMBASETOLNAMES + NUMGAMETYPEFREESLOTS)
struct gametype_t
{
const char *name;
const char *constant;
UINT32 rules;
UINT32 tol;
UINT8 intermission;
INT32 pointlimit;
INT32 timelimit;
};
extern gametype_t *gametypes[MAXGAMETYPES+1];
extern INT16 numgametypes;
extern INT16 gametype;
// Gametype rules
enum GameTypeRules
@ -504,13 +519,8 @@ enum GameTypeRules
// free: to and including 1<<31
};
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern const char *Gametype_ConstantNames[NUMGAMETYPES];
// Point and time limits for every gametype
extern INT32 pointlimits[NUMGAMETYPES];
extern INT32 timelimits[NUMGAMETYPES];
// TODO: replace every instance
#define gametyperules (gametypes[gametype]->rules)
// TypeOfLevel things
enum TypeOfLevel

View file

@ -2998,28 +2998,55 @@ void G_ExitLevel(void)
}
}
// See also the enum GameType in doomstat.h
const char *Gametype_Names[NUMGAMETYPES] =
static gametype_t defaultgametypes[] =
{
"Race", // GT_RACE
"Battle" // GT_BATTLE
// GT_RACE
{
"Race",
"GT_RACE",
GTR_CAMPAIGN|GTR_CIRCUIT|GTR_BOTS|GTR_ENCORE,
TOL_RACE,
int_race,
0,
0,
},
// GT_BATTLE
{
"Battle",
"GT_BATTLE",
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_POWERSTONES|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_CLOSERPLAYERS,
TOL_BATTLE,
int_battle,
0,
2,
},
};
// For dehacked
const char *Gametype_ConstantNames[NUMGAMETYPES] =
gametype_t *gametypes[MAXGAMETYPES+1] =
{
"GT_RACE", // GT_RACE
"GT_BATTLE" // GT_BATTLE
&defaultgametypes[GT_RACE],
&defaultgametypes[GT_BATTLE],
};
// Gametype rules
UINT32 gametypedefaultrules[NUMGAMETYPES] =
//
// G_GetGametypeByName
//
// Returns the number for the given gametype name string, or -1 if not valid.
//
INT32 G_GetGametypeByName(const char *gametypestr)
{
// Race
GTR_CAMPAIGN|GTR_CIRCUIT|GTR_BOTS|GTR_ENCORE,
// Battle
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_POWERSTONES|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_CLOSERPLAYERS
};
INT32 i = 0;
while (gametypes[i] != NULL)
{
if (!stricmp(gametypestr, gametypes[i]->name))
return i;
i++;
}
return -1; // unknown gametype
}
//
// G_SetGametype
@ -3028,41 +3055,26 @@ UINT32 gametypedefaultrules[NUMGAMETYPES] =
//
void G_SetGametype(INT16 gtype)
{
if (gtype < 0 || gtype > numgametypes)
{
I_Error("G_SetGametype: Bad gametype change %d (was %d/\"%s\")", gtype, gametype, gametypes[gametype]->name);
}
gametype = gtype;
gametyperules = gametypedefaultrules[gametype];
}
//
// G_AddGametype
//
// Add a gametype. Returns the new gametype number.
//
INT16 G_AddGametype(UINT32 rules)
{
INT16 newgtype = gametypecount;
gametypecount++;
// Set gametype rules.
gametypedefaultrules[newgtype] = rules;
Gametype_Names[newgtype] = "???";
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
return newgtype;
}
//
// G_AddGametypeConstant
// G_PrepareGametypeConstant
//
// Self-explanatory. Filters out "bad" characters.
//
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
char *G_PrepareGametypeConstant(const char *newgtconst)
{
size_t r = 0; // read
size_t w = 0; // write
char *gtconst = Z_Calloc(strlen(newgtconst) + 4, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(strlen(newgtconst) + 1, PU_STATIC, NULL);
size_t len = strlen(newgtconst);
char *gtconst = Z_Calloc(len + 4, PU_STATIC, NULL);
char *tmpconst = Z_Calloc(len + 1, PU_STATIC, NULL);
// Copy the gametype name.
strcpy(tmpconst, newgtconst);
@ -3122,8 +3134,8 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
// Free the temporary string.
Z_Free(tmpconst);
// Finally, set the constant string.
Gametype_ConstantNames[gtype] = gtconst;
// Finally, return the constant string.
return gtconst;
}
//
@ -3134,30 +3146,15 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
void G_UpdateGametypeSelections(void)
{
INT32 i;
for (i = 0; i < gametypecount; i++)
for (i = 0; i < numgametypes; i++)
{
gametype_cons_t[i].value = i;
gametype_cons_t[i].strvalue = Gametype_Names[i];
gametype_cons_t[i].strvalue = gametypes[i]->name;
}
gametype_cons_t[NUMGAMETYPES].value = 0;
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
gametype_cons_t[numgametypes].value = 0;
gametype_cons_t[numgametypes].strvalue = NULL;
}
// Gametype rankings
INT16 gametyperankings[NUMGAMETYPES] =
{
GT_RACE,
GT_BATTLE,
};
// Gametype to TOL (Type Of Level)
UINT32 gametypetol[NUMGAMETYPES] =
{
TOL_RACE, // Race
TOL_BATTLE, // Battle
TOL_TV, // Midnight Channel effect
};
tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
{"RACE",TOL_RACE},
{"BATTLE",TOL_BATTLE},
@ -3184,32 +3181,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)
{
gametypetol[gtype] = newtol;
}
//
// G_GetGametypeByName
//
// Returns the number for the given gametype name string, or -1 if not valid.
//
INT32 G_GetGametypeByName(const char *gametypestr)
{
INT32 i;
for (i = 0; i < gametypecount; i++)
if (!stricmp(gametypestr, Gametype_Names[i]))
return i;
return -1; // unknown gametype
}
//
// G_IsSpecialStage
//
@ -3339,7 +3310,9 @@ UINT8 G_GetGametypeColor(INT16 gt)
*/
UINT32 G_TOLFlag(INT32 pgametype)
{
return gametypetol[pgametype];
if (pgametype >= 0 && pgametype < numgametypes)
return gametypes[pgametype]->tol;
return 0;
}
INT16 G_GetFirstMapOfGametype(UINT8 pgametype)
@ -3350,7 +3323,7 @@ INT16 G_GetFirstMapOfGametype(UINT8 pgametype)
templevelsearch.cup = NULL;
templevelsearch.typeoflevel = G_TOLFlag(pgametype);
templevelsearch.cupmode = (!(gametypedefaultrules[pgametype] & GTR_NOCUPSELECT));
templevelsearch.cupmode = (!(gametypes[pgametype]->rules & GTR_NOCUPSELECT));
templevelsearch.timeattack = false;
templevelsearch.checklocked = true;

View file

@ -179,16 +179,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum);
void G_SaveGameOver(UINT32 slot, boolean modifylives);
extern UINT32 gametypedefaultrules[NUMGAMETYPES];
extern UINT32 gametypetol[NUMGAMETYPES];
extern INT16 gametyperankings[NUMGAMETYPES];
void G_SetGametype(INT16 gametype);
INT16 G_AddGametype(UINT32 rules);
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst);
char *G_PrepareGametypeConstant(const char *newgtconst);
void G_UpdateGametypeSelections(void);
void G_AddTOL(UINT32 newtol, const char *tolname);
void G_AddGametypeTOL(INT16 gtype, UINT32 newtol);
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);

View file

@ -2406,8 +2406,8 @@ static void HU_DrawRankings(void)
// draw the current gametype in the lower right
if (modeattacking)
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, "Record Attack");
else
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, Gametype_Names[gametype]);
else if (gametype >= 0 && gametype < numgametypes)
V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametypes[gametype]->name);
if ((gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) && !bossinfo.boss)
{

View file

@ -162,7 +162,7 @@ void K_TimerInit(void)
}
else
{
timelimitintics = timelimits[gametype] * (60*TICRATE);
timelimitintics = gametypes[gametype]->timelimit * (60*TICRATE);
}
}
else

View file

@ -2002,7 +2002,7 @@ static void M_DrawCupTitle(INT16 y, cupheader_t *cup)
else
{
if (currentMenu == &PLAY_LevelSelectDef)
V_DrawCenteredLSTitleLowString(BASEVIDWIDTH/2, y+6, 0, va("%s Mode", Gametype_Names[levellist.newgametype]));
V_DrawCenteredLSTitleLowString(BASEVIDWIDTH/2, y+6, 0, va("%s Mode", gametypes[levellist.newgametype]->name));
}
}
@ -2261,7 +2261,7 @@ void M_DrawTimeAttack(void)
laprec = mapheaderinfo[map]->mainrecord->lap;
}
if (gametypedefaultrules[levellist.newgametype] & GTR_CIRCUIT)
if (gametypes[levellist.newgametype]->rules & GTR_CIRCUIT)
{
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST LAP:");
K_drawKartTimestamp(laprec, 162+t, timeheight+6, 0, 2);
@ -3966,13 +3966,13 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
{
const char *gtstring = "???";
if (demoref->gametype >= gametypecount)
;
if (demoref->gametype >= GT_FIRSTFREESLOT)
; // TODO: Support custom gametypes in netreplays (would require deeper changes than this)
else
{
gtstring = Gametype_Names[demoref->gametype];
gtstring = gametypes[demoref->gametype]->name;
if ((gametypedefaultrules[demoref->gametype] & GTR_CIRCUIT))
if ((gametypes[demoref->gametype]->rules & GTR_CIRCUIT))
gtstring = va("%s (%s)", gtstring, kartspeed_cons_t[(demoref->kartspeed & ~DF_ENCORE) + 1].strvalue);
}
@ -3990,9 +3990,9 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
V_DrawThinString(x, y+29, V_SNAPTOTOP|highlightflags, "WINNER");
V_DrawString(x+38, y+30, V_SNAPTOTOP|V_ALLOWLOWERCASE, demoref->standings[0].name);
if (demoref->gametype < gametypecount)
if (demoref->gametype < GT_FIRSTFREESLOT)
{
if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
if (gametypes[demoref->gametype]->rules & GTR_POINTLIMIT)
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
}
@ -4005,7 +4005,7 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
{
V_DrawThinString(x+32, y+39, V_SNAPTOTOP, "NO CONTEST");
}
else if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
else if (gametypes[demoref->gametype]->rules & GTR_POINTLIMIT)
{
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", demoref->standings[0].timeorscore));
}
@ -4211,9 +4211,9 @@ void M_DrawReplayStartMenu(void)
if (demoref->standings[i].timeorscore == UINT32_MAX-1)
V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST");
else if (demoref->gametype >= gametypecount)
else if (demoref->gametype >= GT_FIRSTFREESLOT)
;
else if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
else if (gametypes[demoref->gametype]->rules & GTR_POINTLIMIT)
V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", demoref->standings[i].timeorscore));
else
V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d",

View file

@ -149,7 +149,7 @@ static consvar_t cv_menujam = CVAR_INIT ("menujam", "0", CV_SAVE, menujam_cons_t
// This gametype list is integral for many different reasons.
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
CV_PossibleValue_t gametype_cons_t[MAXGAMETYPES+1];
static CV_PossibleValue_t serversort_cons_t[] = {
{0,"Ping"},
@ -3537,7 +3537,7 @@ static void M_LevelListFromGametype(INT16 gt)
{
levellist.newgametype = gt;
levellist.levelsearch.typeoflevel = G_TOLFlag(gt);
levellist.levelsearch.cupmode = (!(gametypedefaultrules[gt] & GTR_NOCUPSELECT));
levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT));
levellist.levelsearch.cup = NULL;
first = false;
}

View file

@ -2971,15 +2971,15 @@ static int lib_gAddGametype(lua_State *L)
const char *k;
lua_Integer i;
gametype_t *newgametype = NULL;
const char *gtname = NULL;
const char *gtconst = NULL;
INT16 newgtidx = 0;
UINT32 newgtrules = 0;
UINT32 newgttol = 0;
INT32 newgtpointlimit = 0;
INT32 newgttimelimit = 0;
INT16 newgtrankingstype = -1;
int newgtinttype = 0;
UINT8 newgtinttype = 0;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
@ -2988,8 +2988,10 @@ static int lib_gAddGametype(lua_State *L)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
// Ran out of gametype slots
if (gametypecount == NUMGAMETYPEFREESLOTS)
return luaL_error(L, "Ran out of free gametype slots!");
if (numgametypes == GT_LASTFREESLOT)
{
I_Error("Out of Gametype Freeslots while allocating \"%s\"\nLoad less addons to fix this.", gtname);
}
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
@ -3022,19 +3024,15 @@ static int lib_gAddGametype(lua_State *L)
if (!lua_isnumber(L, 3))
TYPEERROR("typeoflevel", LUA_TNUMBER)
newgttol = (UINT32)lua_tointeger(L, 3);
} else if (i == 5 || (k && fasticmp(k, "rankingtype"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("rankingtype", LUA_TNUMBER)
newgtrankingstype = (INT16)lua_tointeger(L, 3);
} else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) {
} else if (i == 5 || (k && fasticmp(k, "intermissiontype"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("intermissiontype", LUA_TNUMBER)
newgtinttype = (int)lua_tointeger(L, 3);
} else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) {
} else if (i == 6 || (k && fasticmp(k, "defaultpointlimit"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("defaultpointlimit", LUA_TNUMBER)
newgtpointlimit = (INT32)lua_tointeger(L, 3);
} else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) {
} else if (i == 7 || (k && fasticmp(k, "defaulttimelimit"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("defaulttimelimit", LUA_TNUMBER)
newgttimelimit = (INT32)lua_tointeger(L, 3);
@ -3053,30 +3051,30 @@ static int lib_gAddGametype(lua_State *L)
gtname = Z_StrDup("Unnamed gametype");
// Add the new gametype
newgtidx = G_AddGametype(newgtrules);
G_AddGametypeTOL(newgtidx, newgttol);
newgametype = Z_Calloc(sizeof (gametype_t), PU_STATIC, NULL);
if (!newgametype)
{
I_Error("Out of memory allocating gametype \"%s\"", gtname);
}
// Not covered by G_AddGametype alone.
if (newgtrankingstype == -1)
newgtrankingstype = newgtidx;
gametyperankings[newgtidx] = newgtrankingstype;
intermissiontypes[newgtidx] = newgtinttype;
pointlimits[newgtidx] = newgtpointlimit;
timelimits[newgtidx] = newgttimelimit;
// Write the new gametype name.
Gametype_Names[newgtidx] = gtname;
// Write the constant name.
if (gtconst == NULL)
gtconst = gtname;
G_AddGametypeConstant(newgtidx, gtconst);
newgametype->name = gtname;
newgametype->rules = newgtrules;
newgametype->constant = G_PrepareGametypeConstant(gtconst);
newgametype->tol = newgttol;
newgametype->intermission = newgtinttype;
newgametype->pointlimit = newgtpointlimit;
newgametype->timelimit = newgttimelimit;
gametypes[numgametypes++] = newgametype;
// Update gametype_cons_t accordingly.
G_UpdateGametypeSelections();
// done
CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]);
CONS_Printf("Added gametype %s\n", gtname);
return 0;
}

View file

@ -7221,7 +7221,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// This is needed. Don't touch.
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
gametyperules = gametypedefaultrules[gametype];
CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer

View file

@ -104,6 +104,7 @@ TYPEDEF (textpage_t);
TYPEDEF (textprompt_t);
TYPEDEF (mappoint_t);
TYPEDEF (customoption_t);
TYPEDEF (gametype_t);
TYPEDEF (mapheader_t);
TYPEDEF (tolinfo_t);
TYPEDEF (cupheader_t);

View file

@ -98,7 +98,6 @@ static INT32 endtic = -1;
static INT32 sorttic = -1;
intertype_t intertype = int_none;
intertype_t intermissiontypes[NUMGAMETYPES];
static huddrawlist_h luahuddrawlist_intermission;
@ -751,15 +750,14 @@ void Y_Ticker(void)
//
void Y_DetermineIntermissionType(void)
{
// set to int_none initially
intertype = int_none;
// set initially
intertype = gametypes[gametype]->intermission;
if (gametype == GT_RACE)
intertype = int_race;
else if (gametype == GT_BATTLE)
// TODO: special cases
if (gametype == GT_BATTLE)
{
if (grandprixinfo.gp == true && bossinfo.boss == false)
intertype = int_none;
return;
else
{
UINT8 i = 0, nump = 0;
@ -772,8 +770,6 @@ void Y_DetermineIntermissionType(void)
intertype = (nump < 2 ? int_battletime : int_battle);
}
}
else //if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
}
//
@ -830,9 +826,6 @@ void Y_StartIntermission(void)
sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE);
}
if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
// We couldn't display the intermission even if we wanted to.
// But we still need to give the players their score bonuses, dummy.
//if (dedicated) return;
@ -1571,7 +1564,7 @@ void Y_StartVote(void)
// set up the gtc and gts
levelinfo[i].gtc = G_GetGametypeColor(votelevels[i][1]);
if (i == 2 && votelevels[i][1] != votelevels[0][1])
levelinfo[i].gts = Gametype_Names[votelevels[i][1]];
levelinfo[i].gts = gametypes[votelevels[i][1]]->name;
else
levelinfo[i].gts = NULL;
}

View file

@ -32,4 +32,3 @@ typedef enum
} intertype_t;
extern intertype_t intertype;
extern intertype_t intermissiontypes[NUMGAMETYPES];