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[]
    - gametypecolor[] - Nep: This one was blan exclusive but I added it regardless.
- 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 2026-03-10 20:56:33 -04:00 committed by NepDisk
parent 926f29dfb8
commit 4932bde9b0
16 changed files with 191 additions and 251 deletions

View file

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

View file

@ -1752,9 +1752,6 @@ void D_SRB2Main(void)
CON_Init();
memset(timelimits, 0, sizeof(timelimits));
memset(pointlimits, 0, sizeof(pointlimits));
CON_SetLoadingProgress(LOADED_HUINIT);
if (modifiedgame)
@ -2097,7 +2094,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

@ -766,10 +766,6 @@ consvar_t cv_timelimit = CVAR_INIT ("timelimit", "2", CV_NETVAR|CV_CALL|CV_NOINI
static CV_PossibleValue_t numlaps_cons_t[] = {{0, "MIN"}, {MAX_LAPS, "MAX"}, {-1, "Map default"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", 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);
@ -873,8 +869,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;
@ -960,13 +955,7 @@ void D_RegisterServerCommands(void)
Forceskin_cons_t[0].value = -1;
Forceskin_cons_t[0].strvalue = "Off";
for (i = 0; i < NUMGAMETYPES; i++)
{
gametype_cons_t[i].value = i;
gametype_cons_t[i].strvalue = Gametype_Names[i];
}
gametype_cons_t[NUMGAMETYPES].value = 0;
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
G_UpdateGametypeSelections();
// Set the values to 0/NULL, it will be overwritten later when a skin is assigned to the slot.
for (i = 1; i < MAXSKINS; i++)
@ -3420,12 +3409,12 @@ void D_SetupVote(void)
UINT8 secondgt = G_SometimesGetDifferentGametype(gt);
INT16 votebuffer[4] = {-1,-1,-1,0};
if (cv_kartencore.value && cv_encorevotes.value == 1 && (gametypedefaultrules[gt] & GTR_CIRCUIT))
if (cv_kartencore.value && cv_encorevotes.value == 1 && (gametypes[gt]->rules & GTR_CIRCUIT))
WRITEUINT8(p, (gt|VOTEMODIFIER_ENCORE));
else
WRITEUINT8(p, gt);
if (cv_kartencore.value && cv_encorevotes.value == 0 && (gametypedefaultrules[gt] & GTR_CIRCUIT))
if (cv_kartencore.value && cv_encorevotes.value == 0 && (gametyperules & GTR_CIRCUIT))
WRITEUINT8(p, secondgt|VOTEMODIFIER_ENCORE);
else
WRITEUINT8(p, secondgt);
@ -3680,7 +3669,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
{
@ -3688,7 +3677,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;
@ -3923,7 +3912,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
@ -5944,8 +5933,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);
@ -6110,10 +6099,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);
@ -6124,11 +6113,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);
}
}
@ -6429,25 +6418,25 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
// Strip illegal Encore flag.
if ((gt & VOTEMODIFIER_ENCORE)
&& !(gametypedefaultrules[(gt & ~VOTEMODIFIER_ENCORE)] & GTR_CIRCUIT))
&& !(gametypes[(gt & ~VOTEMODIFIER_ENCORE)]->rules & GTR_CIRCUIT))
{
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;
}
@ -6471,11 +6460,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_CIRCUIT))
&& !(gametypes[(secondgt & ~VOTEMODIFIER_ENCORE)]->rules & GTR_CIRCUIT))
{
secondgt &= ~VOTEMODIFIER_ENCORE;
// Apply it to the second entry instead, gametype permitting!
if (gametypedefaultrules[gt] & GTR_CIRCUIT)
if (gametypes[gt]->rules & GTR_CIRCUIT)
{
g_voteLevels[1][1] |= VOTEMODIFIER_ENCORE;
}

View file

@ -202,11 +202,16 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
}
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))
{
CacheAndPushConstant(L, word, i);
return 1;
}
i++;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}

View file

@ -642,14 +642,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;
INT32 newgtcolor = V_YELLOWMAP;
int newgtinttype = 0;
UINT8 newgtinttype = 0;
char gtconst[MAXLINELEN];
// Empty strings.
@ -700,12 +699,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"))
{
@ -765,37 +758,36 @@ 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;
gametypecolor[newgtidx] = newgtcolor;
// 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;
newgametype->color = newgtcolor;
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);
}
static mapheader_lighting_t *usemaplighting(INT32 mapnum, const char *word)
@ -4497,7 +4489,7 @@ menudrawer_f *get_menudrawer(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

@ -146,11 +146,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;
@ -458,7 +453,7 @@ extern mapheader_t** mapheaderinfo;
extern INT32 nummapheaders, mapallocsize;
// Gametypes
#define NUMGAMETYPEFREESLOTS (NUMGAMETYPES-GT_FIRSTFREESLOT)
#define NUMGAMETYPEFREESLOTS (MAXGAMETYPES-GT_FIRSTFREESLOT)
enum GameType
{
@ -467,9 +462,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 (10)
#define NUMTOLNAMES (NUMBASETOLNAMES + NUMGAMETYPEFREESLOTS)
struct gametype_t
{
const char *name;
const char *constant;
UINT32 rules;
UINT32 tol;
UINT8 intermission;
INT32 pointlimit;
INT32 timelimit;
INT32 color;
};
extern gametype_t *gametypes[MAXGAMETYPES+1];
extern INT16 numgametypes;
extern INT16 gametype;
// Gametype rules
enum GameTypeRules
@ -516,13 +531,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
@ -545,10 +555,6 @@ enum TypeOfLevel
TOL_TV = 0x0200 ///< Midnight Channel specific: draw TV like overlay on HUD
};
#define MAXTOL (1<<31)
#define NUMBASETOLNAMES (10)
#define NUMTOLNAMES (NUMBASETOLNAMES + NUMGAMETYPEFREESLOTS)
struct tolinfo_t
{
const char *name;

View file

@ -3846,28 +3846,55 @@ void G_FinishExitLevel(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_CIRCUIT|GTR_BOTS|GTR_RINGS|GTR_ENCORE|GTR_RACEODDS,
TOL_RACE,
int_race,
0,
0,
V_SKYMAP,
},
{
"Battle",
"GT_BATTLE",
GTR_BUMPERS|GTR_POINTS|GTR_RINGS|GTR_KARMA|GTR_WANTED|GTR_WANTEDSPB|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT|GTR_POINTLIMIT|GTR_BATTLEODDS|GTR_CLOSERPLAYERS|GTR_BATTLEBOXES|GTR_BATTLESPEED,
TOL_BATTLE,
int_battle,
0,
2,
V_REDMAP,
},
};
// 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_CIRCUIT|GTR_BOTS|GTR_RINGS|GTR_ENCORE|GTR_RACEODDS,
// Battle
GTR_BUMPERS|GTR_POINTS|GTR_RINGS|GTR_KARMA|GTR_WANTED|GTR_WANTEDSPB|GTR_ITEMARROWS|GTR_ITEMBREAKER|GTR_BATTLESTARTS|GTR_TIMELIMIT|GTR_POINTLIMIT|GTR_BATTLEODDS|GTR_CLOSERPLAYERS|GTR_BATTLEBOXES|GTR_BATTLESPEED
};
INT32 i = 0;
while (gametypes[i] != NULL)
{
if (!stricmp(gametypestr, gametypes[i]->name))
return i;
i++;
}
return -1; // unknown gametype
}
//
// G_SetGametype
@ -3876,41 +3903,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);
@ -3932,7 +3944,7 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
case ' ':
case '@':
case '?':
// Used for operations
// Used for operations
case '+':
case '-':
case '*':
@ -3941,7 +3953,7 @@ void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
case '^':
case '&':
case '!':
// Part of Lua's syntax
// Part of Lua's syntax
case '#':
case '=':
case '~':
@ -3970,8 +3982,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;
}
//
@ -3982,36 +3994,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;
}
INT32 gametypecolor[NUMGAMETYPES] =
{
V_SKYMAP,
V_REDMAP,
};
// 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},
@ -4052,32 +4043,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 (fasticmp(gametypestr, Gametype_Names[i]))
return i;
return -1; // unknown gametype
}
//
// G_IsSpecialStage
//
@ -4168,7 +4133,7 @@ INT16 G_SometimesGetDifferentGametype(UINT8 prefgametype)
// This is so a server CAN continue playing a gametype if they like the taste of it.
// The encore check needs prefgametype so can't use G_RaceGametype...
boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE) || encorescramble == 1)
&& ((gametyperules|gametypedefaultrules[prefgametype]) & GTR_CIRCUIT));
&& (gametypes[prefgametype]->rules & GTR_CIRCUIT));
UINT8 encoremodifier = 0;
// -- the below is only necessary if you want to use randmaps.mapbuffer here
@ -4248,8 +4213,8 @@ UINT8 G_GetGametypeColor(INT16 gt)
|| gamestate == GS_TIMEATTACK)
return orangemap[0];
if (gametypecolor[gt])
return *V_GetStringColormap(gametypecolor[gt]);
if (gametypes[gt]->color)
return *V_GetStringColormap(gametypes[gt]->color);
return yellowmap[0]; // FALLBACK
}
@ -4261,7 +4226,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)
@ -4269,7 +4236,7 @@ INT16 G_GetFirstMapOfGametype(UINT8 pgametype)
INT16 mapnum = NEXTMAP_INVALID;
/* G: not sure what to do with this
if ((gametypedefaultrules[pgametype] & GTR_CAMPAIGN) && kartcupheaders)
if ((gametypes[pgametype]->rules & GTR_CAMPAIGN) && kartcupheaders)
{
mapnum = kartcupheaders->cachedlevels[0];
}

View file

@ -202,18 +202,11 @@ void G_SaveGame(UINT32 slot, INT16 mapnum);
void G_SaveGameOver(UINT32 slot, boolean modifylives);
extern UINT32 gametypedefaultrules[NUMGAMETYPES];
extern UINT32 gametypetol[NUMGAMETYPES];
extern INT32 gametypecolor[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_SetGametypeColor(INT16 gtype,INT32 color);
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

@ -2527,8 +2527,8 @@ static void HU_DrawRankings(void)
hilicol = V_ORANGEMAP;
else
{
if (gametypecolor[gametype])
hilicol = gametypecolor[gametype];
if (gametypes[gametype]->color)
hilicol = gametypes[gametype]->color;
else
hilicol = V_YELLOWMAP;
}

View file

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

View file

@ -3209,16 +3209,16 @@ 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;
INT32 newgtcolor = V_YELLOWMAP;
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.
@ -3227,8 +3227,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)))
@ -3261,23 +3263,19 @@ 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);
} else if (i == 9 || (k && fasticmp(k, "menucolor"))) {
} else if (i == 8 || (k && fasticmp(k, "menucolor"))) {
if (!lua_isnumber(L, 3))
TYPEERROR("menucolor", LUA_TNUMBER)
{
@ -3300,31 +3298,32 @@ static int lib_gAddGametype(lua_State *L)
gtname = Z_StrDup("Unnamed gametype");
// Add the new gametype
newgtidx = G_AddGametype(newgtrules);
G_AddGametypeTOL(newgtidx, newgttol);
// Not covered by G_AddGametype alone.
if (newgtrankingstype == -1)
newgtrankingstype = newgtidx;
gametyperankings[newgtidx] = newgtrankingstype;
intermissiontypes[newgtidx] = newgtinttype;
pointlimits[newgtidx] = newgtpointlimit;
timelimits[newgtidx] = newgttimelimit;
gametypecolor[newgtidx] = newgtcolor;
// Write the new gametype name.
Gametype_Names[newgtidx] = gtname;
newgametype = Z_Calloc(sizeof (gametype_t), PU_STATIC, NULL);
if (!newgametype)
{
I_Error("Out of memory allocating gametype \"%s\"", 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;
newgametype->color = newgtcolor;
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

@ -454,7 +454,7 @@ consvar_t cv_skinselectsort = CVAR_INIT ("skinselectsort", "Name", CV_SAVE|CV_CA
// 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];
consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Race", CV_HIDEN|CV_CALL|CV_NOINIT, gametype_cons_t, Levelplatter_OnChange);
@ -613,19 +613,19 @@ inline static void M_GetGametypeColor(void)
if (gt == GT_BATTLE || levellistmode == LLM_BOSS)
{
highlightflags = gametypecolor[gt];
highlightflags = gametypes[gt]->color;
warningflags = V_ORANGEMAP;
return;
}
if (gt == GT_RACE)
{
highlightflags = gametypecolor[gt];
highlightflags = gametypes[gt]->color;
return;
}
if (gametypecolor[gt])
if (gametypes[gt]->color)
{
highlightflags = gametypecolor[gt];
highlightflags = gametypes[gt]->color;
return;
}

View file

@ -8747,7 +8747,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

@ -115,6 +115,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

@ -115,7 +115,6 @@ static INT32 listscroll_delay = 0;
static fixed_t xscroll = 0;
intertype_t intertype = int_none;
intertype_t intermissiontypes[NUMGAMETYPES];
static huddrawlist_h luahuddrawlist_intermission;
static huddrawlist_h luahuddrawlist_vote;
@ -464,8 +463,8 @@ void Y_IntermissionDrawer(void)
hilicol = V_ORANGEMAP;
else
{
if (gametypecolor[gametype])
hilicol = gametypecolor[gametype];
if (gametypes[gametype]->color)
hilicol = gametypes[gametype]->color;
else
hilicol = V_YELLOWMAP;
}
@ -1052,12 +1051,11 @@ 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;
@ -1073,8 +1071,6 @@ void Y_DetermineIntermissionType(void)
intertype = (nump < 2 ? int_battletime : int_battle);
}
}
else //if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
}
//
@ -1132,9 +1128,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;
@ -1808,8 +1801,8 @@ void Y_VoteDrawer(void)
hilicol = cons_menuhighlight.value;
else
{
if (gametypecolor[gametype])
hilicol = gametypecolor[gametype];
if (gametypes[gametype]->color)
hilicol = gametypes[gametype]->color;
else
hilicol = V_YELLOWMAP;
}
@ -2231,7 +2224,7 @@ void Y_StartVote(void)
// set up the gtc and gts
levelinfo[i].gtc = G_GetGametypeColor(g_voteLevels[i][1]);
if (i == 2 && g_voteLevels[i][1] != g_voteLevels[0][1])
levelinfo[i].gts = gametype_cons_t[g_voteLevels[i][1]].strvalue;
levelinfo[i].gts = gametypes[g_voteLevels[i][1]]->name;
else
levelinfo[i].gts = NULL;
}

View file

@ -45,7 +45,6 @@ typedef enum
} intertype_t;
extern intertype_t intertype;
extern intertype_t intermissiontypes[NUMGAMETYPES];
// Votescreen stuff
typedef struct