diff --git a/src/command.c b/src/command.c index a0f2967bf..8f72331f7 100644 --- a/src/command.c +++ b/src/command.c @@ -73,6 +73,15 @@ CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}}; CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; +// Cheats +#ifdef DEVELOP + #define VALUE "On" +#else + #define VALUE "Off" +#endif +consvar_t cv_cheats = CVAR_INIT ("cheats", VALUE, CV_NETVAR|CV_CALL, CV_OnOff, CV_CheatsChanged); +#undef VALUE + // SRB2kart CV_PossibleValue_t kartspeed_cons_t[] = { {KARTSPEED_AUTO, "Auto"}, @@ -336,6 +345,9 @@ void COM_Init(void) // allocate command buffer VS_Alloc(&com_text, COM_BUF_SIZE); + // cheats is a special cvar, so register it ASAP + CV_RegisterVar(&cv_cheats); + // add standard commands COM_AddCommand("alias", COM_Alias_f); COM_AddCommand("echo", COM_Echo_f); @@ -1340,12 +1352,11 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) boolean override = false; INT32 overrideval = 0; - // If we want messages informing us if cheats have been enabled or disabled, - // we need to rework the consvars a little bit. This call crashes the game - // on load because not all variables will be registered at that time. -/* boolean prevcheats = false; - if (var->flags & CV_CHEAT) - prevcheats = CV_CheatsEnabled(); */ + if ((var->flags & CV_CHEAT) && CV_CheatsEnabled() == false) + { + // Enforce to default value without cheats. + valstr = var->defaultvalue; + } if (var->PossibleValue) { @@ -1506,17 +1517,6 @@ found: } finish: - // See the note above. -/* if (var->flags & CV_CHEAT) - { - boolean newcheats = CV_CheatsEnabled(); - - if (!prevcheats && newcheats) - CONS_Printf(M_GetText("Cheats have been enabled.\n")); - else if (prevcheats && !newcheats) - CONS_Printf(M_GetText("Cheats have been disabled.\n")); - } */ - if (var->flags & CV_SHOWMODIFONETIME || var->flags & CV_SHOWMODIF) { CONS_Printf(M_GetText("%s set to %s\n"), var->name, var->string); @@ -1526,10 +1526,13 @@ finish: { DEBFILE(va("%s set to %s\n", var->name, var->string)); } + var->flags |= CV_MODIFIED; + // raise 'on change' code LUA_CVarChanged(var); // let consolelib know what cvar this is. - if (var->flags & CV_CALL && !stealth) + + if ((var->flags & CV_CALL) && !stealth) var->func(); return; @@ -1750,14 +1753,33 @@ void CV_LoadDemoVars(UINT8 **p) static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth); -void CV_ResetCheatNetVars(void) +void CV_CheatsChanged(void) { - consvar_t *cvar; + if (CV_CheatsEnabled()) + { + G_SetUsedCheats(); + } + else + { + consvar_t *cvar; + UINT8 i; - // Stealthset everything back to default. - for (cvar = consvar_vars; cvar; cvar = cvar->next) - if (cvar->flags & CV_CHEAT) - CV_SetCVar(cvar, cvar->defaultvalue, true); + // Set everything back to default. + for (cvar = consvar_vars; cvar; cvar = cvar->next) + if (cvar->flags & CV_CHEAT) + CV_SetCVar(cvar, cvar->defaultvalue, false); + + // Reset any other cheat command effects here, as well. + cv_debug = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + players[i].cheats = 0; + } + } } // Returns true if the variable's current value is its default value @@ -1768,16 +1790,9 @@ boolean CV_IsSetToDefault(consvar_t *v) // If any cheats CVars are not at their default settings, return true. // Else return false. -// This returns a UINT8 because I'm too lazy to deal with the packet structure. -// Deal with it. =P -UINT8 CV_CheatsEnabled(void) +boolean CV_CheatsEnabled(void) { - consvar_t *cvar; - - for (cvar = consvar_vars; cvar; cvar = cvar->next) - if ((cvar->flags & CV_CHEAT) && strcmp(cvar->defaultvalue, cvar->string)) - return 1; - return 0; + return (boolean)cv_cheats.value; } /** Sets a value to a variable, performing some checks and calling the diff --git a/src/command.h b/src/command.h index a9558626b..d76cb0bd8 100644 --- a/src/command.h +++ b/src/command.h @@ -122,7 +122,7 @@ typedef enum CV_NOSHOWHELP = 512, // Don't show variable in the HELP list Tails 08-13-2002 CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console // can only be set when we have the pointer to it - // used on menus + // used on menus CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. CV_NOLUA = 4096,/* don't let this be called from Lua */ } cvflags_t; @@ -223,10 +223,10 @@ void CV_RevertNetVars(void); void CV_LoadDemoVars(UINT8 **p); // reset cheat netvars after cheats is deactivated -void CV_ResetCheatNetVars(void); +void CV_CheatsChanged(void); boolean CV_IsSetToDefault(consvar_t *v); -UINT8 CV_CheatsEnabled(void); +boolean CV_CheatsEnabled(void); // Returns cvar by name. Exposed here for Lua. consvar_t *CV_FindVar(const char *name); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b03eb478e..2a1ec303b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -901,7 +901,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], sizeof netbuffer->u.serverinfo.gametypename); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; - netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); + netbuffer->u.serverinfo.cheatsenabled = (UINT8)CV_CheatsEnabled(); netbuffer->u.serverinfo.kartvars = (UINT8) ( (gamespeed & SV_SPEEDMASK) | diff --git a/src/d_main.c b/src/d_main.c index 9c5b6e254..cbd6a2a8d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1548,6 +1548,12 @@ void D_SRB2Main(void) if (M_CheckParm("-noupload")) COM_BufAddText("downloading 0\n"); + if (M_CheckParm("-gamedata") && M_IsNextParm()) + { + // Moved from G_LoadGameData itself, as it would cause some crazy + // confusion issues when loading mods. + strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + } G_LoadGameData(); wipegamestate = gamestate; @@ -1631,7 +1637,7 @@ void D_SRB2Main(void) { if (!M_CheckParm("-server")) { - G_SetGameModified(true, true); + G_SetUsedCheats(); // Start up a "minor" grand prix session memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); @@ -1842,15 +1848,16 @@ void D_SRB2Main(void) { // Prevent warping to nonexistent levels if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR) + { I_Error("Could not warp to %s (map not found)\n", G_BuildMapName(pstartmap)); - // Prevent warping to locked levels - // ... unless you're in a dedicated server. Yes, technically this means you can view any level by - // running a dedicated server and joining it yourself, but that's better than making dedicated server's - // lives hell. - else if (!dedicated && M_MapLocked(pstartmap)) - I_Error("You need to unlock this level before you can warp to it!\n"); + } else { + if (M_MapLocked(pstartmap)) + { + G_SetUsedCheats(); + } + D_MapChange(pstartmap, gametype, (cv_kartencore.value == 1), true, 0, false, false); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 28b816b3a..fe411f139 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -62,12 +62,6 @@ #include "doomstat.h" #include "deh_tables.h" -#ifdef NETGAME_DEVMODE -#define CV_RESTRICT CV_NETVAR -#else -#define CV_RESTRICT 0 -#endif - #ifdef HAVE_DISCORDRPC #include "discord.h" #endif @@ -148,10 +142,6 @@ static void KartEncore_OnChange(void); static void KartComeback_OnChange(void); static void KartEliminateLast_OnChange(void); -#ifdef NETGAME_DEVMODE -static void Fishcake_OnChange(void); -#endif - static void Command_Playdemo_f(void); static void Command_Timedemo_f(void); static void Command_Stopdemo_f(void); @@ -213,7 +203,6 @@ static void Command_ShowScores_f(void); static void Command_ShowTime_f(void); static void Command_Isgamemodified_f(void); -static void Command_Cheats_f(void); #ifdef _DEBUG static void Command_Togglemodified_f(void); static void Command_Archivetest_f(void); @@ -245,9 +234,6 @@ static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL} consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", 0, CV_OnOff, NULL); -#ifdef NETGAME_DEVMODE -static consvar_t cv_fishcake = CVAR_INIT ("fishcake", "Off", CV_CALL|CV_NOSHOWHELP|CV_RESTRICT, CV_OnOff, Fishcake_OnChange); -#endif static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); @@ -341,35 +327,35 @@ consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = { //Alam: Dummy for save #endif // SRB2kart -consvar_t cv_superring = CVAR_INIT ("superring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_sneaker = CVAR_INIT ("sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_rocketsneaker = CVAR_INIT ("rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_invincibility = CVAR_INIT ("invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_banana = CVAR_INIT ("banana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_droptarget = CVAR_INIT ("droptarget", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_shrink = CVAR_INIT ("shrink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_lightningshield = CVAR_INIT ("lightningshield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_bubbleshield = CVAR_INIT ("bubbleshield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_flameshield = CVAR_INIT ("flameshield", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_hyudoro = CVAR_INIT ("hyudoro", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_pogospring = CVAR_INIT ("pogospring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_kitchensink = CVAR_INIT ("kitchensink", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_superring = CVAR_INIT ("superring", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_sneaker = CVAR_INIT ("sneaker", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_rocketsneaker = CVAR_INIT ("rocketsneaker", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_invincibility = CVAR_INIT ("invincibility", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_banana = CVAR_INIT ("banana", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_droptarget = CVAR_INIT ("droptarget", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_shrink = CVAR_INIT ("shrink", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_lightningshield = CVAR_INIT ("lightningshield", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_bubbleshield = CVAR_INIT ("bubbleshield", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_flameshield = CVAR_INIT ("flameshield", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_hyudoro = CVAR_INIT ("hyudoro", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_pogospring = CVAR_INIT ("pogospring", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_kitchensink = CVAR_INIT ("kitchensink", "On", CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_dualsneaker = CVAR_INIT ("dualsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_triplesneaker = CVAR_INIT ("triplesneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_triplebanana = CVAR_INIT ("triplebanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_decabanana = CVAR_INIT ("decabanana", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_tripleorbinaut = CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_dualsneaker = CVAR_INIT ("dualsneaker", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_triplesneaker = CVAR_INIT ("triplesneaker", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_triplebanana = CVAR_INIT ("triplebanana", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_decabanana = CVAR_INIT ("decabanana", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_tripleorbinaut = CVAR_INIT ("tripleorbinaut", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_quadorbinaut = CVAR_INIT ("quadorbinaut", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_dualjawz = CVAR_INIT ("dualjawz", "On", CV_NETVAR, CV_OnOff, NULL); static CV_PossibleValue_t kartminimap_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_kartminimap = CVAR_INIT ("kartminimap", "4", CV_SAVE, kartminimap_cons_t, NULL); @@ -378,9 +364,9 @@ static CV_PossibleValue_t kartinvinsfx_cons_t[] = {{0, "Music"}, {1, "SFX"}, {0, consvar_t cv_kartinvinsfx = CVAR_INIT ("kartinvinsfx", "SFX", CV_SAVE, kartinvinsfx_cons_t, NULL); consvar_t cv_kartspeed = CVAR_INIT ("kartspeed", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartspeed_cons_t, KartSpeed_OnChange); static CV_PossibleValue_t kartbumpers_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}}; -consvar_t cv_kartbumpers = CVAR_INIT ("kartbumpers", "3", CV_NETVAR|CV_CHEAT, kartbumpers_cons_t, NULL); -consvar_t cv_kartfrantic = CVAR_INIT ("kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange); -consvar_t cv_kartcomeback = CVAR_INIT ("kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange); +consvar_t cv_kartbumpers = CVAR_INIT ("kartbumpers", "3", CV_NETVAR, kartbumpers_cons_t, NULL); +consvar_t cv_kartfrantic = CVAR_INIT ("kartfrantic", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartFrantic_OnChange); +consvar_t cv_kartcomeback = CVAR_INIT ("kartcomeback", "On", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange); static CV_PossibleValue_t kartencore_cons_t[] = {{-1, "Auto"}, {0, "Off"}, {1, "On"}, {0, NULL}}; consvar_t cv_kartencore = CVAR_INIT ("kartencore", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartencore_cons_t, KartEncore_OnChange); static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; @@ -409,9 +395,9 @@ static CV_PossibleValue_t kartbot_cons_t[] = { }; consvar_t cv_kartbot = CVAR_INIT ("kartbot", "0", CV_NETVAR, kartbot_cons_t, NULL); -consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); +consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); -consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL); static CV_PossibleValue_t kartdebugitem_cons_t[] = { @@ -420,37 +406,30 @@ static CV_PossibleValue_t kartdebugitem_cons_t[] = #undef FOREACH {0} }; -consvar_t cv_kartdebugitem = CVAR_INIT ("kartdebugitem", "0", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugitem_cons_t, NULL); +consvar_t cv_kartdebugitem = CVAR_INIT ("kartdebugitem", "0", CV_NETVAR|CV_CHEAT, kartdebugitem_cons_t, NULL); static CV_PossibleValue_t kartdebugamount_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; -consvar_t cv_kartdebugamount = CVAR_INIT ("kartdebugamount", "1", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugamount_cons_t, NULL); -#ifdef DEVELOP -#define VALUE "Yes" -#else -#define VALUE "No" -#endif -consvar_t cv_kartallowgiveitem = CVAR_INIT ("kartallowgiveitem", VALUE, CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_YesNo, NULL); -#undef VALUE +consvar_t cv_kartdebugamount = CVAR_INIT ("kartdebugamount", "1", CV_NETVAR|CV_CHEAT, kartdebugamount_cons_t, NULL); -consvar_t cv_kartdebugdistribution = CVAR_INIT ("kartdebugdistribution", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL); -consvar_t cv_kartdebughuddrop = CVAR_INIT ("kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL); +consvar_t cv_kartdebugdistribution = CVAR_INIT ("kartdebugdistribution", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_kartdebughuddrop = CVAR_INIT ("kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); static CV_PossibleValue_t kartdebugwaypoint_cons_t[] = {{0, "Off"}, {1, "Forwards"}, {2, "Backwards"}, {0, NULL}}; -consvar_t cv_kartdebugwaypoints = CVAR_INIT ("kartdebugwaypoints", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugwaypoint_cons_t, NULL); -consvar_t cv_kartdebugbotpredict = CVAR_INIT ("kartdebugbotpredict", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL); +consvar_t cv_kartdebugwaypoints = CVAR_INIT ("kartdebugwaypoints", "Off", CV_NETVAR|CV_CHEAT, kartdebugwaypoint_cons_t, NULL); +consvar_t cv_kartdebugbotpredict = CVAR_INIT ("kartdebugbotpredict", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_kartdebugcheckpoint = CVAR_INIT ("kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); -consvar_t cv_kartdebugnodes = CVAR_INIT ("kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); -consvar_t cv_kartdebugcolorize = CVAR_INIT ("kartdebugcolorize", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); -consvar_t cv_kartdebugdirector = CVAR_INIT ("kartdebugdirector", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); +consvar_t cv_kartdebugcheckpoint = CVAR_INIT ("kartdebugcheckpoint", "Off", CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_kartdebugnodes = CVAR_INIT ("kartdebugnodes", "Off", CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_kartdebugcolorize = CVAR_INIT ("kartdebugcolorize", "Off", CV_CHEAT, CV_OnOff, NULL); +consvar_t cv_kartdebugdirector = CVAR_INIT ("kartdebugdirector", "Off", CV_CHEAT, CV_OnOff, NULL); static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}}; consvar_t cv_votetime = CVAR_INIT ("votetime", "20", CV_NETVAR, votetime_cons_t, NULL); -consvar_t cv_gravity = CVAR_INIT ("gravity", "0.8", CV_RESTRICT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); // change DEFAULT_GRAVITY if you change this +consvar_t cv_gravity = CVAR_INIT ("gravity", "0.8", CV_CHEAT|CV_FLOAT|CV_CALL, NULL, Gravity_OnChange); // change DEFAULT_GRAVITY if you change this consvar_t cv_soundtest = CVAR_INIT ("soundtest", "0", CV_CALL, NULL, SoundTest_OnChange); static CV_PossibleValue_t minitimelimit_cons_t[] = {{15, "MIN"}, {9999, "MAX"}, {0, NULL}}; -consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "30", CV_NETVAR|CV_CHEAT, minitimelimit_cons_t, NULL); +consvar_t cv_countdowntime = CVAR_INIT ("countdowntime", "30", CV_NETVAR, minitimelimit_cons_t, NULL); consvar_t cv_autobalance = CVAR_INIT ("autobalance", "Off", CV_SAVE|CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange); consvar_t cv_teamscramble = CVAR_INIT ("teamscramble", "Off", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange); @@ -459,7 +438,7 @@ consvar_t cv_scrambleonchange = CVAR_INIT ("scrambleonchange", "Off", CV_SAVE|CV consvar_t cv_itemfinder = CVAR_INIT ("itemfinder", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, ItemFinder_OnChange); // Scoring type options -consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_overtime = CVAR_INIT ("overtime", "Yes", CV_NETVAR, CV_YesNo, NULL); consvar_t cv_rollingdemos = CVAR_INIT ("rollingdemos", "On", CV_SAVE, CV_OnOff, NULL); @@ -470,7 +449,7 @@ consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CA static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; consvar_t cv_numlaps = CVAR_INIT ("numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange); static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, "Map default"}, {0, NULL}}; -consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange); +consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL, basenumlaps_cons_t, BaseNumLaps_OnChange); // Point and time limits for every gametype INT32 pointlimits[NUMGAMETYPES]; @@ -671,7 +650,6 @@ void D_RegisterServerCommands(void) COM_AddCommand("isgamemodified", Command_Isgamemodified_f); // test COM_AddCommand("showscores", Command_ShowScores_f); COM_AddCommand("showtime", Command_ShowTime_f); - COM_AddCommand("cheats", Command_Cheats_f); // test #ifdef _DEBUG COM_AddCommand("togglemodified", Command_Togglemodified_f); COM_AddCommand("archivetest", Command_Archivetest_f); @@ -883,10 +861,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_netstat); CV_RegisterVar(&cv_netticbuffer); -#ifdef NETGAME_DEVMODE - CV_RegisterVar(&cv_fishcake); -#endif - // HUD CV_RegisterVar(&cv_itemfinder); CV_RegisterVar(&cv_showinputjoy); @@ -2577,7 +2551,8 @@ static void Command_Map_f(void) const char *gametypename; boolean newresetplayers; - boolean mustmodifygame; + boolean usingcheats; + boolean ischeating; INT32 newmapnum; @@ -2601,20 +2576,8 @@ static void Command_Map_f(void) option_skill = COM_CheckPartialParm("-s"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - mustmodifygame = !(netgame || multiplayer) && !majormods; - - if (mustmodifygame && !option_force) - { - /* May want to be more descriptive? */ - CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); - return; - } - - if (!newresetplayers && !cv_debug) - { - CONS_Printf(M_GetText("DEVMODE must be enabled.\n")); - return; - } + usingcheats = CV_CheatsEnabled(); + ischeating = (!(netgame || multiplayer)) || (!newresetplayers); if (option_gametype) { @@ -2657,9 +2620,15 @@ static void Command_Map_f(void) return; } - if (mustmodifygame && option_force) + if (M_MapLocked(newmapnum)) { - G_SetGameModified(multiplayer, true); + ischeating = true; + } + + if (ischeating && !usingcheats) + { + CONS_Printf(M_GetText("Cheats must be enabled.\n")); + return; } // new gametype value @@ -2716,7 +2685,7 @@ static void Command_Map_f(void) { newencoremode = !newencoremode; - if (!M_SecretUnlocked(SECRET_ENCORE) && newencoremode == true && !option_force) + if (!M_SecretUnlocked(SECRET_ENCORE) && newencoremode == true && !usingcheats) { CONS_Alert(CONS_NOTICE, M_GetText("You haven't unlocked Encore Mode yet!\n")); return; @@ -2728,10 +2697,12 @@ static void Command_Map_f(void) // don't use a gametype the map doesn't support if (cv_debug || option_force || cv_skipmapcheck.value) + { fromlevelselect = false; // The player wants us to trek on anyway. Do so. - // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer + } else { + // G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer if (!( mapheaderinfo[newmapnum-1] && mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype) @@ -2829,18 +2800,6 @@ static void Command_Map_f(void) } } - // Prevent warping to locked levels - // ... unless you're in a dedicated server. Yes, technically this means you can view any level by - // running a dedicated server and joining it yourself, but that's better than making dedicated server's - // lives hell. - if (!dedicated && M_MapLocked(newmapnum)) - { - CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); - Z_Free(realmapname); - Z_Free(mapname); - return; - } - if (tutorialmode && tutorialgcs) { G_CopyControls(gamecontrol[0], gamecontroldefault[0][gcs_custom], gcl_full, num_gcl_full); // using gcs_custom as temp storage @@ -4625,23 +4584,12 @@ void D_GameTypeChanged(INT32 lastgametype) static void Gravity_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug - && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) + if (netgame) { - CONS_Printf(M_GetText("You haven't earned this yet.\n")); - CV_StealthSet(&cv_gravity, cv_gravity.defaultvalue); + // TODO: multiplayer support return; } -#ifndef NETGAME_GRAVITY - if(netgame) - { - CV_StealthSet(&cv_gravity, cv_gravity.defaultvalue); - return; - } -#endif - if (!CV_IsSetToDefault(&cv_gravity)) - G_SetGameModified(multiplayer, true); gravity = cv_gravity.value; } @@ -4860,7 +4808,7 @@ static void Command_Mapmd5_f(void) static void Command_ExitLevel_f(void) { - if (!(netgame || multiplayer) && !cv_debug) + if (!(netgame || multiplayer) && !CV_CheatsEnabled()) CONS_Printf(M_GetText("This only works in a netgame.\n")); else if (!(server || (IsPlayerAdmin(consoleplayer)))) CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); @@ -4953,7 +4901,7 @@ static void Got_GiveItemcmd(UINT8 **cp, INT32 playernum) amt = READUINT8 (*cp); if ( - ( netgame && ! cv_kartallowgiveitem.value ) || + ( !CV_CheatsEnabled() ) || ( item < KITEM_SAD || item >= NUMKARTITEMS ) ) { @@ -5052,23 +5000,6 @@ void Command_Retry_f(void) } } -#ifdef NETGAME_DEVMODE -// Allow the use of devmode in netgames. -static void Fishcake_OnChange(void) -{ - cv_debug = cv_fishcake.value; - // consvar_t's get changed to default when registered - // so don't make modifiedgame always on! - if (cv_debug) - { - G_SetGameModified(multiplayer, true); - } - - else if (cv_debug != cv_fishcake.value) - CV_SetValue(&cv_fishcake, cv_debug); -} -#endif - /** Reports to the console whether or not the game has been modified. * * \todo Make it obvious, so a console command won't be necessary. @@ -5087,27 +5018,6 @@ static void Command_Isgamemodified_f(void) CONS_Printf("The game has not been modified. You can play Record Attack, earn medals and unlock extras.\n"); } -static void Command_Cheats_f(void) -{ - if (COM_CheckParm("off")) - { - if (!(server || (IsPlayerAdmin(consoleplayer)))) - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - else - CV_ResetCheatNetVars(); - return; - } - - if (CV_CheatsEnabled()) - { - CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n")); - if (server || (IsPlayerAdmin(consoleplayer))) - CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n")); - } - else - CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n")); -} - #ifdef _DEBUG static void Command_Togglemodified_f(void) { @@ -5160,8 +5070,6 @@ static void Command_Archivetest_f(void) #endif /** Give yourself an, optional quantity or one of, an item. - * - * \sa cv_kartallowgiveitem */ static void Command_KartGiveItem_f(void) { @@ -5175,8 +5083,7 @@ static void Command_KartGiveItem_f(void) int i; - /* Allow always in local games. */ - if (! netgame || cv_kartallowgiveitem.value) + if (CV_CheatsEnabled()) { ac = COM_Argc(); if (ac < 2) @@ -5516,7 +5423,7 @@ static void Skin_OnChange(void) if (!Playing()) return; // do whatever you want - if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. + if (!CV_CheatsEnabled() && !(multiplayer || netgame) // In single player. && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y { CV_StealthSet(&cv_skin[0], skins[players[consoleplayer].skin].name); @@ -5592,7 +5499,7 @@ static void Color_OnChange(void) } else { - if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. + if (!CV_CheatsEnabled() && !(multiplayer || netgame)) // In single player. { CV_StealthSet(&cv_skin[0], skins[players[consoleplayer].skin].name); return; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index f6d172bcc..0d1ce4d43 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -86,7 +86,7 @@ extern consvar_t cv_kartusepwrlv; extern consvar_t cv_votetime; -extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartallowgiveitem, cv_kartdebugdistribution, cv_kartdebughuddrop; +extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugdistribution, cv_kartdebughuddrop; extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector; extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict; diff --git a/src/d_player.h b/src/d_player.h index c6328c3ca..adeb14ea1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -66,8 +66,8 @@ typedef enum // Accessibility and cheats PF_KICKSTARTACCEL = 1<<4, // Is accelerate in kickstart mode? - PF_GODMODE = 1<<5, - PF_NOCLIP = 1<<6, + // 1<<5 free + // 1<<6 free PF_WANTSTOJOIN = 1<<7, // Spectator that wants to join @@ -105,6 +105,13 @@ typedef enum // up to 1<<31 is free } pflags_t; +typedef enum +{ + PC_GODMODE = 1, + PC_NOCLIP = 1<<1, + // up to 1<<31 is free +} pcheats_t; + typedef enum { // Are animation frames playing? @@ -350,6 +357,7 @@ typedef struct player_s // Bit flags. // See pflags_t, above. pflags_t pflags; + pcheats_t cheats; // playing animation. panim_t panim; diff --git a/src/doomdef.h b/src/doomdef.h index f36e780e6..54067f806 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -122,7 +122,7 @@ extern char logfilename[1024]; #endif /* A mod name to further distinguish versions. */ -#define SRB2APPLICATION "SRB2Kart" +#define SRB2APPLICATION "RingRacers" //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 #ifdef DEVELOP @@ -146,7 +146,7 @@ extern char logfilename[1024]; #define VERSIONSTRINGW WSTRING (VERSIONSTRING) /* A custom URL protocol for server links. */ -#define SERVER_URL_PROTOCOL "srb2kart://" +#define SERVER_URL_PROTOCOL "ringracers://" // Does this version require an added patch file? // Comment or uncomment this as necessary. @@ -619,12 +619,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; // None of these that are disabled in the normal build are guaranteed to work perfectly // Compile them at your own risk! -/// Allows the use of devmode in multiplayer. AKA "fishcake" -//#define NETGAME_DEVMODE - -/// Allows gravity changes in netgames, no questions asked. -//#define NETGAME_GRAVITY - /// Dumps the contents of a network save game upon consistency failure for debugging. //#define DUMPCONSISTENCY diff --git a/src/doomstat.h b/src/doomstat.h index 4b3f75d13..5908a6b69 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -95,6 +95,7 @@ extern boolean modifiedgame; extern boolean majormods; extern UINT16 mainwads; extern boolean savemoddata; // This mod saves time/emblem data. +extern boolean usedCheats; extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; @@ -685,8 +686,6 @@ extern INT16 scrambleteams[MAXPLAYERS]; //for CTF team scramble extern INT16 scrambletotal; //for CTF team scramble extern INT16 scramblecount; //for CTF team scramble -extern INT32 cheats; - // SRB2kart extern UINT8 gamespeed; extern boolean franticitems; diff --git a/src/f_finale.c b/src/f_finale.c index 52f2556f4..81ca4c816 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1035,7 +1035,7 @@ void F_GameEvaluationDrawer(void) { V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); - if (!(netgame) && (!modifiedgame || savemoddata)) + if (!usedCheats) { INT32 startcoord = 32; @@ -1050,10 +1050,8 @@ void F_GameEvaluationDrawer(void) } } } - else if (netgame) - V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); else - V_DrawString(8, 96, V_YELLOWMAP, "Modified games\ncan't unlock\nextras!"); + V_DrawString(8, 96, V_YELLOWMAP, "Cheated games\ncan't unlock\nextras!"); } #endif @@ -1107,14 +1105,7 @@ void F_GameEvaluationTicker(void) if (finalecount == 5*TICRATE) { - if (netgame || multiplayer) // modify this when we finally allow unlocking stuff in 2P - { - HU_SetCEchoFlags(V_YELLOWMAP); - HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!"); - S_StartSound(NULL, sfx_s3k68); - } - else if (!modifiedgame || savemoddata) + if (!usedCheats) { ++timesBeaten; @@ -1127,7 +1118,7 @@ void F_GameEvaluationTicker(void) { HU_SetCEchoFlags(V_YELLOWMAP); HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Modified games can't unlock extras!"); + HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Cheated games can't unlock extras!"); S_StartSound(NULL, sfx_s3k68); } } diff --git a/src/g_game.c b/src/g_game.c index 896ea00ea..91c130333 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -122,6 +122,7 @@ UINT16 mainwads = 0; boolean modifiedgame = false; // Set if homebrew PWAD stuff has been added. boolean majormods = false; // Set if Lua/Gameplay SOC/replacement map has been added. boolean savemoddata = false; +boolean usedCheats = false; // Set when a "cheats on" is ever used. UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; boolean imcontinuing = false; @@ -297,8 +298,6 @@ INT16 scrambleteams[MAXPLAYERS]; //for CTF team scramble INT16 scrambletotal; //for CTF team scramble INT16 scramblecount; //for CTF team scramble -INT32 cheats; //for multiplayer cheat commands - // SRB2Kart // Cvars that we don't want changed mid-game UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard @@ -658,6 +657,22 @@ void G_SetGameModified(boolean silent, boolean major) Command_ExitGame_f(); } +// for consistency among messages: this sets cheats as used. +void G_SetUsedCheats(void) +{ + if (usedCheats) + return; + + usedCheats = true; + CONS_Alert(CONS_NOTICE, M_GetText("Cheats activated -- game must be restarted to save progress.\n")); + + // If in record attack recording, cancel it. + if (modeattacking) + M_EndModeAttackRun(); + else if (marathonmode) + Command_ExitGame_f(); +} + /** Builds an original game map name from a map number. * The complexity is due to MAPA0-MAPZZ. * @@ -2188,6 +2203,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT32 followitem; INT32 pflags; + INT32 cheats; UINT8 ctfteam; @@ -2266,6 +2282,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) botrival = players[player].botvars.rival; pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE)); + cheats = 0; // SRB2kart if (betweenmaps || leveltime < introtime) @@ -2339,7 +2356,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) // As long as we're not in multiplayer, carry over cheatcodes from map to map if (!(netgame || multiplayer)) - pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP)); + cheats = players[player].cheats; if (!betweenmaps) { @@ -2356,6 +2373,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->roundscore = roundscore; p->lives = lives; p->pflags = pflags; + p->cheats = cheats; p->ctfteam = ctfteam; p->jointime = jointime; p->splitscreenindex = splitscreenindex; @@ -3407,7 +3425,7 @@ tryagain: if ((mapheaderinfo[ix]->typeoflevel & tolflags) != tolflags || ix == pprevmap - || (!dedicated && M_MapLocked(ix+1)) + || M_MapLocked(ix+1) || (usehellmaps != (mapheaderinfo[ix]->menuflags & LF2_HIDEINMENU))) // this is bad continue; //isokmap = false; @@ -3528,11 +3546,8 @@ void G_AddMapToBuffer(INT16 map) // static void G_UpdateVisited(void) { - boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? - if ((!modifiedgame || savemoddata) // Not modified - && !multiplayer && !demo.playback // SP/RA/NiGHTS mode - && !(spec && stagefailed)) // Not failed the special stage + if (!demo.playback) // Not watching a demo { UINT8 earnedEmblems; @@ -3575,14 +3590,16 @@ static void G_HandleSaveLevel(void) remove(liveeventbackup); cursaveslot = 0; } - else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demo.recording || metalrecording || modeattacking)) + else if (!usedCheats && !(netgame || multiplayer || ultimatemode || demo.recording || metalrecording || modeattacking)) G_SaveGame((UINT32)cursaveslot, spstage_start); } } // and doing THIS here means you don't lose your progress if you close the game mid-intermission - else if (!(ultimatemode || netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) - && (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + else if (!(ultimatemode || demo.playback || demo.recording || metalrecording || modeattacking) + && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + { G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages + } } // @@ -3943,7 +3960,7 @@ static void G_DoContinued(void) tokenlist = 0; token = 0; - if (!(netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) && (!modifiedgame || savemoddata) && cursaveslot > 0) + if (!(netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) && !usedCheats && cursaveslot > 0) G_SaveGameOver((UINT32)cursaveslot, true); // Reset # of lives @@ -4012,19 +4029,25 @@ void G_LoadGameSettings(void) S_InitRuntimeSounds(); } +#define GAMEDATA_ID 0x61688195 // Change every major version, as usual + // G_LoadGameData // Loads the main data file, which stores information such as emblems found, etc. void G_LoadGameData(void) { size_t length; INT32 i, j; - UINT8 modded = false; + + UINT32 versionID; UINT8 rtemp; //For records tic_t rectime; tic_t reclap; + // Stop saving, until we successfully load it again. + gamedataloaded = false; + // Clear things so previously read gamedata doesn't transfer // to new gamedata G_ClearRecords(); // main and nights records @@ -4037,27 +4060,31 @@ void G_LoadGameData(void) vspowerlevel[i] = PWRLVRECORD_START; if (M_CheckParm("-nodata")) - return; // Don't load. - - // Allow saving of gamedata beyond this point - gamedataloaded = true; - - if (M_CheckParm("-gamedata") && M_IsNextParm()) { - strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + // Don't load at all. + return; } if (M_CheckParm("-resetdata")) - return; // Don't load (essentially, reset). + { + // Don't load, but do save. (essentially, reset) + gamedataloaded = true; + return; + } length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); - if (!length) // Aw, no game data. Their loss! + if (!length) + { + // No gamedata. We can save a new one. + gamedataloaded = true; return; + } save_p = savebuffer; // Version check - if (READUINT32(save_p) != 0xFCAFE211) + versionID = READUINT32(save_p); + if (versionID != GAMEDATA_ID) { const char *gdfolder = "the Ring Racers folder"; if (strcmp(srb2home,".")) @@ -4065,7 +4092,7 @@ void G_LoadGameData(void) Z_Free(savebuffer); save_p = NULL; - I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); + I_Error("Game data is not for Ring Racers v2.0.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } totalplaytime = READUINT32(save_p); @@ -4078,13 +4105,17 @@ void G_LoadGameData(void) goto datacorrupt; } - modded = READUINT8(save_p); + { + // Quick & dirty hash for what mod this save file is for. + UINT32 modID = READUINT32(save_p); + UINT32 expectedID = quickncasehash(timeattackfolder, 64); - // Aha! Someone's been screwing with the save file! - if ((modded && !savemoddata)) - goto datacorrupt; - else if (modded != true && modded != false) - goto datacorrupt; + if (modID != expectedID) + { + // Aha! Someone's been screwing with the save file! + goto datacorrupt; + } + } // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) @@ -4141,6 +4172,12 @@ void G_LoadGameData(void) Z_Free(savebuffer); save_p = NULL; + // Don't consider loaded until it's a success! + // It used to do this much earlier, but this would cause the gamedata to + // save over itself when it I_Errors from the corruption landing point below, + // which can accidentally delete players' legitimate data if the code ever has any tiny mistakes! + gamedataloaded = true; + // Silent update unlockables in case they're out of sync with conditions M_SilentUpdateUnlockablesAndEmblems(); @@ -4178,18 +4215,15 @@ void G_SaveGameData(void) return; } -#if 0 - // SRB2Kart: Let players unlock stuff with addons. - if (modifiedgame && !savemoddata) + if (usedCheats) { free(savebuffer); save_p = savebuffer = NULL; return; } -#endif // Version test - WRITEUINT32(save_p, 0xFCAFE211); + WRITEUINT32(save_p, GAMEDATA_ID); WRITEUINT32(save_p, totalplaytime); WRITEUINT32(save_p, matchesplayed); @@ -4197,7 +4231,7 @@ void G_SaveGameData(void) for (i = 0; i < PWRLV_NUMTYPES; i++) WRITEUINT16(save_p, vspowerlevel[i]); - WRITEUINT8(save_p, (UINT8)savemoddata); + WRITEUINT32(save_p, quickncasehash(timeattackfolder, 64)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) @@ -4605,7 +4639,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool memset(&players[i].respawn, 0, sizeof (players[i].respawn)); // Clear cheatcodes too, just in case. - players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP); + players[i].cheats = 0; players[i].roundscore = 0; diff --git a/src/g_game.h b/src/g_game.h index 52c7c7a0d..6a40543f2 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -243,6 +243,7 @@ void G_LoadGameData(void); void G_LoadGameSettings(void); void G_SetGameModified(boolean silent, boolean major); +void G_SetUsedCheats(void); void G_SetGamestate(gamestate_t newstate); diff --git a/src/k_kart.c b/src/k_kart.c index 0c530ae9e..54e9ca821 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -257,7 +257,6 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugitem); CV_RegisterVar(&cv_kartdebugamount); - CV_RegisterVar(&cv_kartallowgiveitem); CV_RegisterVar(&cv_kartdebugdistribution); CV_RegisterVar(&cv_kartdebughuddrop); CV_RegisterVar(&cv_kartdebugwaypoints); diff --git a/src/m_cheat.c b/src/m_cheat.c index ce925e931..dc4ad96cc 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -97,7 +97,7 @@ static UINT8 cheatf_warp(void) if (success) { - G_SaveGameData(); //G_SetGameModified(false); + G_SaveGameData(); //G_SetUsedCheats(); S_StartSound(0, sfx_kc42); } @@ -121,7 +121,7 @@ static UINT8 cheatf_devmode(void) S_StartSound(0, sfx_itemup); // Just unlock all the things and turn on -debug and console devmode. - G_SetGameModified(false, false); // might need to revist the latter later + G_SetUsedCheats(); for (i = 0; i < MAXUNLOCKABLES; i++) unlockables[i].unlocked = true; devparm = true; @@ -264,11 +264,8 @@ boolean cht_Responder(event_t *ev) } // Console cheat commands rely on these a lot... -#define REQUIRE_PANDORA if (!M_SecretUnlocked(SECRET_PANDORA) && !cv_debug)\ -{ CONS_Printf(M_GetText("You haven't earned this yet.\n")); return; } - -#define REQUIRE_DEVMODE if (!cv_debug)\ -{ CONS_Printf(M_GetText("DEVMODE must be enabled.\n")); return; } +#define REQUIRE_CHEATS if (!CV_CheatsEnabled())\ +{ CONS_Printf(M_GetText("Cheats must be enabled.\n")); return; } #define REQUIRE_OBJECTPLACE if (!objectplacing)\ { CONS_Printf(M_GetText("OBJECTPLACE must be enabled.\n")); return; } @@ -284,37 +281,35 @@ void Command_CheatNoClip_f(void) { player_t *plyr; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make netplay compatible plyr = &players[consoleplayer]; if (!plyr->mo || P_MobjWasRemoved(plyr->mo)) return; - plyr->pflags ^= PF_NOCLIP; - CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off")); + plyr->cheats ^= PC_NOCLIP; + CONS_Printf(M_GetText("No Clipping %s\n"), plyr->cheats & PC_NOCLIP ? M_GetText("On") : M_GetText("Off")); - if (plyr->pflags & PF_NOCLIP) + if (plyr->cheats & PC_NOCLIP) plyr->mo->flags |= MF_NOCLIP; else plyr->mo->flags &= ~MF_NOCLIP; - - G_SetGameModified(multiplayer, true); } void Command_CheatGod_f(void) { player_t *plyr; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible plyr = &players[consoleplayer]; - plyr->pflags ^= PF_GODMODE; - CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); - - G_SetGameModified(multiplayer, true); + plyr->cheats ^= PC_GODMODE; + CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->cheats & PC_GODMODE ? M_GetText("On") : M_GetText("Off")); } void Command_Scale_f(void) @@ -322,9 +317,9 @@ void Command_Scale_f(void) const double scaled = atof(COM_Argv(1)); fixed_t scale = FLOAT_TO_FIXED(scaled); - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (scale < FRACUNIT/100 || scale > 100*FRACUNIT) //COM_Argv(1) will return a null string if they did not give a paramater, so... { @@ -342,9 +337,9 @@ void Command_Scale_f(void) void Command_Gravflip_f(void) { - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (players[consoleplayer].mo) players[consoleplayer].mo->flags2 ^= MF2_OBJECTFLIP; @@ -352,9 +347,9 @@ void Command_Gravflip_f(void) void Command_Hurtme_f(void) { - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() < 2) { @@ -372,9 +367,9 @@ void Command_RTeleport_f(void) player_t *p = &players[consoleplayer]; subsector_t *ss; - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() < 3 || COM_Argc() > 7) { @@ -434,9 +429,9 @@ void Command_Teleport_f(void) player_t *p = &players[consoleplayer]; subsector_t *ss; - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() < 3 || COM_Argc() > 11) { @@ -650,9 +645,9 @@ void Command_Teleport_f(void) void Command_Skynum_f(void) { - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() != 2) { @@ -668,9 +663,9 @@ void Command_Skynum_f(void) void Command_Weather_f(void) { - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() != 2) { @@ -688,9 +683,9 @@ void Command_Toggletwod_f(void) { player_t *p = &players[consoleplayer]; - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (p->mo) p->mo->flags2 ^= MF2_TWOD; @@ -703,6 +698,9 @@ void Command_Toggletwod_f(void) // Don't enable this for normal builds... void Command_CauseCfail_f(void) { + REQUIRE_CHEATS; + REQUIRE_INLEVEL; + if (consoleplayer == serverplayer) { CONS_Printf(M_GetText("Only remote players can use this command.\n")); @@ -745,9 +743,9 @@ void Command_Dumplua_f(void) void Command_Savecheckpoint_f(void) { - REQUIRE_DEVMODE; + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible players[consoleplayer].respawn.pointx = players[consoleplayer].mo->x; players[consoleplayer].respawn.pointy = players[consoleplayer].mo->y; @@ -760,8 +758,8 @@ void Command_Savecheckpoint_f(void) /* void Command_Getallemeralds_f(void) { + REQUIRE_CHEATS; REQUIRE_SINGLEPLAYER; - REQUIRE_PANDORA; emeralds = EMERALD_ALL; @@ -770,6 +768,7 @@ void Command_Getallemeralds_f(void) void Command_Resetemeralds_f(void) { + REQUIRE_CHEATS; REQUIRE_SINGLEPLAYER; emeralds = 0; @@ -780,9 +779,8 @@ void Command_Resetemeralds_f(void) void Command_Devmode_f(void) { -#ifndef _DEBUG - REQUIRE_SINGLEPLAYER; -#endif + REQUIRE_CHEATS; + REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() > 1) { @@ -799,15 +797,12 @@ void Command_Devmode_f(void) CONS_Printf(M_GetText("devmode : enable debugging tools and info, prepend with 0x to use hexadecimal\n")); return; } - - G_SetGameModified(multiplayer, true); } void Command_Setrings_f(void) { + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -815,16 +810,13 @@ void Command_Setrings_f(void) players[consoleplayer].rings = 0; P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings - - G_SetGameModified(multiplayer, true); } } void Command_Setlives_f(void) { + REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - REQUIRE_PANDORA; if (COM_Argc() > 1) { @@ -839,8 +831,6 @@ void Command_Setlives_f(void) players[consoleplayer].lives = 0; P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1))); } - - G_SetGameModified(multiplayer, true); } } @@ -1149,7 +1139,6 @@ void OP_ObjectplaceMovement(player_t *player) void Command_Writethings_f(void) { REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; REQUIRE_OBJECTPLACE; P_WriteThings(); @@ -1161,9 +1150,8 @@ void Command_ObjectPlace_f(void) size_t silent; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - - G_SetGameModified(multiplayer, true); + REQUIRE_CHEATS; + REQUIRE_SINGLEPLAYER; // this one will very likely never be multiplayer compatible... silent = COM_CheckParm("-silent"); diff --git a/src/m_cond.c b/src/m_cond.c index ceff3c167..5aa3157a5 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -382,17 +382,23 @@ UINT8 M_SecretUnlocked(INT32 type) UINT8 M_MapLocked(INT32 mapnum) { - #ifdef DEVELOP - if (1) + (void)mapnum; + return false; +#else + // Don't lock maps in dedicated servers. + // That just makes hosts' lives hell. + if (dedicated) return false; -#endif - + if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) return false; + if (!unlockables[mapheaderinfo[mapnum-1]->unlockrequired].unlocked) return true; + return false; +#endif } INT32 M_CountEmblems(void) diff --git a/src/m_menu.c b/src/m_menu.c index dc753db68..f517e117e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6376,7 +6376,7 @@ static void M_GetAllEmeralds(INT32 choice) emeralds = EMERALD_ALL; M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING); - G_SetGameModified(multiplayer, true); + G_SetUsedCheats(); } static void M_DestroyRobotsResponse(INT32 ch) @@ -6387,7 +6387,7 @@ static void M_DestroyRobotsResponse(INT32 ch) // Destroy all robots P_DestroyRobots(); - G_SetGameModified(multiplayer, true); + G_SetUsedCheats(); } static void M_DestroyRobots(INT32 choice) diff --git a/src/p_inter.c b/src/p_inter.c index 27455872d..38754a7db 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1893,7 +1893,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player) // Player is the target { - if (player->pflags & PF_GODMODE) + if (player->cheats & PC_GODMODE) return false; if (!force) diff --git a/src/p_map.c b/src/p_map.c index 473ded5fe..1c75246a3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2239,7 +2239,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) fixed_t tryy = thiscam->y; #ifndef NOCLIPCAM - if ((players[displayplayers[i]].pflags & PF_NOCLIP) || (leveltime < introtime)) // Noclipping player camera noclips too!! + if ((players[displayplayers[i]].cheats & PC_NOCLIP) || (leveltime < introtime)) // Noclipping player camera noclips too!! #else if (!(players[displayplayers[i]].pflags & PF_NOCONTEST)) // Time Over should not clip through walls #endif diff --git a/src/p_mobj.c b/src/p_mobj.c index 5219fb707..c164ccf3a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2040,7 +2040,7 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if (mo->player && mo->player->pflags & PF_GODMODE) + if (mo->player && mo->player->cheats & PC_GODMODE) return false; if (((mo->z <= mo->subsector->sector->floorheight @@ -3531,7 +3531,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled player->karthud[khud_timeovercam] = (2*TICRATE)+1; } - if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + if (!resetcalled && !(player->cheats & PC_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. { P_ResetCamera(player, thiscam); } @@ -10583,7 +10583,7 @@ void P_RemoveSavegameMobj(mobj_t *mobj) static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); -consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); void P_SpawnPrecipitation(void) { @@ -11417,31 +11417,23 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) switch (i) { - case MT_EMBLEM: - if (netgame || multiplayer) - return false; // Single player only + case MT_ITEMCAPSULE: + { + boolean isRingCapsule = (mthing->angle < 1 || mthing->angle == KITEM_SUPERRING || mthing->angle >= NUMKARTITEMS); - if (modifiedgame && !savemoddata) - return false; // No cheating!! + // don't spawn ring capsules in GTR_SPHERES gametypes + if (isRingCapsule && (gametyperules & GTR_SPHERES)) + return false; - break; - case MT_ITEMCAPSULE: - { - boolean isRingCapsule = (mthing->angle < 1 || mthing->angle == KITEM_SUPERRING || mthing->angle >= NUMKARTITEMS); - - // don't spawn ring capsules in GTR_SPHERES gametypes - if (isRingCapsule && (gametyperules & GTR_SPHERES)) - return false; - - // in record attack, only spawn ring capsules - // (behavior can be inverted with the Extra flag, i.e. item capsule spawns and ring capsule does not) - if (modeattacking - && (!(mthing->options & MTF_EXTRA) == !isRingCapsule)) - return false; - } - break; - default: - break; + // in record attack, only spawn ring capsules + // (behavior can be inverted with the Extra flag, i.e. item capsule spawns and ring capsule does not) + if (modeattacking + && (!(mthing->options & MTF_EXTRA) == !isRingCapsule)) + return false; + } + break; + default: + break; } // No bosses outside of a combat situation. diff --git a/src/p_setup.c b/src/p_setup.c index a47077ba5..c281d5497 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4133,9 +4133,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Initialize sector node list. P_Initsecnode(); - if (netgame || multiplayer) - cv_debug = 0; - if (metalplayback) G_StopMetalDemo(); @@ -4476,7 +4473,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) { // I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020 if (!(ultimatemode || netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking || marathonmode) - && (!modifiedgame || savemoddata) && cursaveslot > 0) + && !usedCheats && cursaveslot > 0) G_SaveGame((UINT32)cursaveslot, gamemap); // If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted. } diff --git a/src/p_user.c b/src/p_user.c index ffc53012b..eb1541486 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3084,7 +3084,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } #ifndef NOCLIPCAM - cameranoclip = ((player->pflags & PF_NOCLIP) + cameranoclip = ((player->cheats & PC_NOCLIP) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!! || (leveltime < introtime)); // Kart intro cam #endif diff --git a/src/r_skins.c b/src/r_skins.c index ae5e0363c..bf71570e0 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -298,7 +298,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->kartweight = skin->kartweight; #if 0 - if (!(cv_debug || devparm) && !(netgame || multiplayer || demo.playback)) + if (!CV_CheatsEnabled() && !(netgame || multiplayer || demo.playback)) { for (i = 0; i <= r_splitscreen; i++) {