mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-02 06:23:03 +00:00
Compromise on cheats setting modified game
Instead of modifying the game, cheats now set a separate "cheats were used in this session" variable, which returns some of the old behavior. HOWEVER, cheats will STILL allow spawning / collecting emblems & unlocking unlockables. Cheats will purely prevent saving progress. (It was always frustrating that devmode would make debugging unlockable features harder...) Lastly, the function to set no-saving was exposed to Lua (`G_SetUsedCheats(silent)`). Just thought it'd be useful for large-scale gamedata-using mods that want to add their own cheat commands.
This commit is contained in:
parent
4a520e63c6
commit
a22fa1c455
13 changed files with 87 additions and 30 deletions
|
@ -1448,6 +1448,7 @@ static boolean SV_SendServerConfig(INT32 node)
|
|||
netbuffer->u.servercfg.gamestate = (UINT8)gamestate;
|
||||
netbuffer->u.servercfg.gametype = (UINT8)gametype;
|
||||
netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame;
|
||||
netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats;
|
||||
|
||||
memcpy(netbuffer->u.servercfg.server_context, server_context, 8);
|
||||
|
||||
|
@ -4341,6 +4342,8 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
|
||||
G_SetGametype(netbuffer->u.servercfg.gametype);
|
||||
modifiedgame = netbuffer->u.servercfg.modifiedgame;
|
||||
if (netbuffer->u.servercfg.usedCheats)
|
||||
G_SetUsedCheats(true);
|
||||
memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ typedef struct
|
|||
|
||||
UINT8 gametype;
|
||||
UINT8 modifiedgame;
|
||||
UINT8 usedCheats;
|
||||
|
||||
char server_context[8]; // Unique context id, generated at server startup.
|
||||
} ATTRPACK serverconfig_pak;
|
||||
|
|
|
@ -1506,7 +1506,7 @@ void D_SRB2Main(void)
|
|||
else
|
||||
{
|
||||
if (!M_CheckParm("-server"))
|
||||
G_SetGameModified(true);
|
||||
G_SetUsedCheats(true);
|
||||
autostart = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1877,7 +1877,7 @@ static void Command_Map_f(void)
|
|||
const char *gametypename;
|
||||
boolean newresetplayers;
|
||||
|
||||
boolean mustmodifygame;
|
||||
boolean wouldSetCheats;
|
||||
|
||||
INT32 newmapnum;
|
||||
|
||||
|
@ -1898,11 +1898,11 @@ static void Command_Map_f(void)
|
|||
option_gametype = COM_CheckPartialParm("-g");
|
||||
newresetplayers = ! COM_CheckParm("-noresetplayers");
|
||||
|
||||
mustmodifygame =
|
||||
!( netgame || multiplayer ) &&
|
||||
(!modifiedgame || savemoddata );
|
||||
wouldSetCheats =
|
||||
!( netgame || multiplayer ) &&
|
||||
!( usedCheats );
|
||||
|
||||
if (mustmodifygame && !option_force)
|
||||
if (wouldSetCheats && !option_force)
|
||||
{
|
||||
/* May want to be more descriptive? */
|
||||
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
|
||||
|
@ -1956,9 +1956,9 @@ static void Command_Map_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mustmodifygame && option_force)
|
||||
if (wouldSetCheats && option_force)
|
||||
{
|
||||
G_SetGameModified(false);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
// new gametype value
|
||||
|
@ -4259,7 +4259,7 @@ static void Ringslinger_OnChange(void)
|
|||
}
|
||||
|
||||
if (cv_ringslinger.value) // Only if it's been turned on
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
static void Gravity_OnChange(void)
|
||||
|
@ -4280,7 +4280,7 @@ static void Gravity_OnChange(void)
|
|||
#endif
|
||||
|
||||
if (!CV_IsSetToDefault(&cv_gravity))
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
gravity = cv_gravity.value;
|
||||
}
|
||||
|
||||
|
@ -4596,7 +4596,7 @@ static void Fishcake_OnChange(void)
|
|||
// so don't make modifiedgame always on!
|
||||
if (cv_debug)
|
||||
{
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
else if (cv_debug != cv_fishcake.value)
|
||||
|
|
|
@ -75,6 +75,7 @@ extern SINT8 startinglivesbalance[maxgameovers+1];
|
|||
extern boolean modifiedgame;
|
||||
extern UINT16 mainwads;
|
||||
extern boolean savemoddata; // This mod saves time/emblem data.
|
||||
extern boolean usedCheats;
|
||||
extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true
|
||||
extern boolean imcontinuing; // Temporary flag while continuing
|
||||
extern boolean metalrecording;
|
||||
|
|
31
src/g_game.c
31
src/g_game.c
|
@ -96,6 +96,7 @@ SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40
|
|||
UINT16 mainwads = 0;
|
||||
boolean modifiedgame; // Set if homebrew PWAD stuff has been added.
|
||||
boolean savemoddata = false;
|
||||
boolean usedCheats = false; // Set when a gamedata-preventing cheat command is used.
|
||||
UINT8 paused;
|
||||
UINT8 modeattacking = ATTACKING_NONE;
|
||||
boolean disableSpeedAdjust = false;
|
||||
|
@ -764,6 +765,23 @@ void G_SetGameModified(boolean silent)
|
|||
Command_ExitGame_f();
|
||||
}
|
||||
|
||||
void G_SetUsedCheats(boolean silent)
|
||||
{
|
||||
if (usedCheats)
|
||||
return;
|
||||
|
||||
usedCheats = true;
|
||||
|
||||
if (!silent)
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("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.
|
||||
*
|
||||
|
@ -3894,7 +3912,7 @@ static void G_HandleSaveLevel(void)
|
|||
remove(liveeventbackup);
|
||||
cursaveslot = 0;
|
||||
}
|
||||
else if (!(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking))
|
||||
else if (!usedCheats && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking))
|
||||
{
|
||||
G_SaveGame((UINT32)cursaveslot, spstage_start);
|
||||
}
|
||||
|
@ -3902,7 +3920,7 @@ static void G_HandleSaveLevel(void)
|
|||
}
|
||||
// and doing THIS here means you don't lose your progress if you close the game mid-intermission
|
||||
else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking)
|
||||
&& cursaveslot > 0 && CanSaveLevel(lastmap+1))
|
||||
&& !usedCheats && cursaveslot > 0 && CanSaveLevel(lastmap+1))
|
||||
{
|
||||
G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages
|
||||
}
|
||||
|
@ -4181,7 +4199,7 @@ static void G_DoContinued(void)
|
|||
tokenlist = 0;
|
||||
token = 0;
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && cursaveslot > 0)
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && !usedCheats && cursaveslot > 0)
|
||||
{
|
||||
G_SaveGameOver((UINT32)cursaveslot, true);
|
||||
}
|
||||
|
@ -4480,6 +4498,13 @@ void G_SaveGameData(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (usedCheats)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Version test
|
||||
WRITEUINT32(save_p, GAMEDATA_ID);
|
||||
|
||||
|
|
|
@ -243,6 +243,7 @@ void G_LoadGameData(void);
|
|||
void G_LoadGameSettings(void);
|
||||
|
||||
void G_SetGameModified(boolean silent);
|
||||
void G_SetUsedCheats(boolean silent);
|
||||
|
||||
void G_SetGamestate(gamestate_t newstate);
|
||||
|
||||
|
|
|
@ -3612,6 +3612,16 @@ static int lib_gRemovePlayer(lua_State *L)
|
|||
}
|
||||
|
||||
|
||||
static int lib_gSetUsedCheats(lua_State *L)
|
||||
{
|
||||
// Let large-scale level packs using Lua be able to add cheat commands.
|
||||
boolean silent = lua_optboolean(L, 1);
|
||||
//NOHUD
|
||||
//INLEVEL
|
||||
G_SetUsedCheats(silent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Lcheckmapnumber (lua_State *L, int idx, const char *fun)
|
||||
{
|
||||
if (ISINLEVEL)
|
||||
|
@ -4213,6 +4223,7 @@ static luaL_Reg lib[] = {
|
|||
{"G_AddGametype", lib_gAddGametype},
|
||||
{"G_AddPlayer", lib_gAddPlayer},
|
||||
{"G_RemovePlayer", lib_gRemovePlayer},
|
||||
{"G_SetUsedCheats", lib_gSetUsedCheats},
|
||||
{"G_BuildMapName",lib_gBuildMapName},
|
||||
{"G_BuildMapTitle",lib_gBuildMapTitle},
|
||||
{"G_FindMap",lib_gFindMap},
|
||||
|
|
|
@ -204,6 +204,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"modifiedgame")) {
|
||||
lua_pushboolean(L, modifiedgame && !savemoddata);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"usedCheats")) {
|
||||
lua_pushboolean(L, usedCheats);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"menuactive")) {
|
||||
lua_pushboolean(L, menuactive);
|
||||
return 1;
|
||||
|
|
|
@ -81,7 +81,7 @@ static UINT8 cheatf_warp(void)
|
|||
S_StartSound(0, sfx_itemup);
|
||||
|
||||
// Temporarily unlock stuff.
|
||||
G_SetGameModified(false);
|
||||
G_SetUsedCheats(false);
|
||||
unlockables[31].unlocked = true; // credits
|
||||
unlockables[30].unlocked = true; // sound test
|
||||
unlockables[28].unlocked = true; // level select
|
||||
|
@ -106,7 +106,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);
|
||||
G_SetUsedCheats(false);
|
||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||
unlockables[i].unlocked = true;
|
||||
devparm = true;
|
||||
|
@ -275,7 +275,7 @@ void Command_CheatNoClip_f(void)
|
|||
plyr->pflags ^= PF_NOCLIP;
|
||||
CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off"));
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
void Command_CheatGod_f(void)
|
||||
|
@ -290,7 +290,7 @@ void Command_CheatGod_f(void)
|
|||
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);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
void Command_CheatNoTarget_f(void)
|
||||
|
@ -305,7 +305,7 @@ void Command_CheatNoTarget_f(void)
|
|||
plyr->pflags ^= PF_INVIS;
|
||||
CONS_Printf(M_GetText("SEP Field %s\n"), plyr->pflags & PF_INVIS ? M_GetText("On") : M_GetText("Off"));
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
void Command_Scale_f(void)
|
||||
|
@ -879,7 +879,7 @@ void Command_Devmode_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
void Command_Setrings_f(void)
|
||||
|
@ -905,7 +905,7 @@ void Command_Setrings_f(void)
|
|||
// no totalsphere addition to revert
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -928,7 +928,7 @@ void Command_Setlives_f(void)
|
|||
P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1)));
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -955,7 +955,7 @@ void Command_Setcontinues_f(void)
|
|||
|
||||
players[consoleplayer].continues = numcontinues;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1446,7 +1446,7 @@ void Command_ObjectPlace_f(void)
|
|||
REQUIRE_SINGLEPLAYER;
|
||||
REQUIRE_NOULTIMATE;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
|
||||
silent = COM_CheckParm("-silent");
|
||||
|
||||
|
|
20
src/m_menu.c
20
src/m_menu.c
|
@ -7082,7 +7082,7 @@ static void M_AllowSuper(INT32 choice)
|
|||
M_StartMessage(M_GetText("You are now capable of turning super.\nRemember to get all the emeralds!\n"),NULL,MM_NOTHING);
|
||||
SR_PandorasBox[6].status = IT_GRAYEDOUT;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
static void M_GetAllEmeralds(INT32 choice)
|
||||
|
@ -7093,7 +7093,7 @@ static void M_GetAllEmeralds(INT32 choice)
|
|||
M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING);
|
||||
SR_PandorasBox[7].status = IT_GRAYEDOUT;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
static void M_DestroyRobotsResponse(INT32 ch)
|
||||
|
@ -7104,7 +7104,7 @@ static void M_DestroyRobotsResponse(INT32 ch)
|
|||
// Destroy all robots
|
||||
P_DestroyRobots();
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
static void M_DestroyRobots(INT32 choice)
|
||||
|
@ -8703,6 +8703,12 @@ static void M_DrawLoad(void)
|
|||
loadgameoffset = 0;
|
||||
|
||||
M_DrawLoadGameData();
|
||||
|
||||
if (usedCheats)
|
||||
{
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING:\x80 Cheats have been activated.");
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved.");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -9004,12 +9010,18 @@ static void M_HandleLoadSave(INT32 choice)
|
|||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT)
|
||||
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !usedCheats)
|
||||
{
|
||||
loadgamescroll = 0;
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
M_StartMessage("Are you sure you want to play\n\x85ultimate mode\x80? It isn't remotely fair,\nand you don't even get an emblem for it.\n\n(Press 'Y' to confirm)\n",M_SaveGameUltimateResponse,MM_YESNO);
|
||||
}
|
||||
else if (saveSlotSelected != NOSAVESLOT && savegameinfo[saveSlotSelected-1].lives == -42 && usedCheats)
|
||||
{
|
||||
loadgamescroll = 0;
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
M_StartMessage(M_GetText("This cannot be done in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
else if (saveSlotSelected == NOSAVESLOT || savegameinfo[saveSlotSelected-1].lives != -666) // don't allow loading of "bad saves"
|
||||
{
|
||||
loadgamescroll = 0;
|
||||
|
|
|
@ -2583,7 +2583,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers)
|
||||
{
|
||||
numgameovers++;
|
||||
if (cursaveslot > 0)
|
||||
if (!usedCheats && cursaveslot > 0)
|
||||
G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7764,7 +7764,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 || demoplayback || demorecording || metalrecording || modeattacking || marathonmode)
|
||||
&& cursaveslot > 0)
|
||||
&& !usedCheats && cursaveslot > 0)
|
||||
{
|
||||
G_SaveGame((UINT32)cursaveslot, gamemap);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue