mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 01:01:33 +00:00
Merge branch 'allow-modified-saving' into 'next'
[SUGOI] Allow saving in modified games. See merge request STJr/SRB2!1749
This commit is contained in:
commit
e4933b3e94
20 changed files with 180 additions and 105 deletions
|
@ -1506,6 +1506,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);
|
||||
|
||||
|
@ -4406,6 +4407,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;
|
||||
|
|
|
@ -1473,6 +1473,12 @@ void D_SRB2Main(void)
|
|||
//--------------------------------------------------------- CONFIG.CFG
|
||||
M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()"
|
||||
|
||||
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();
|
||||
|
||||
#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
||||
|
@ -1500,7 +1506,7 @@ void D_SRB2Main(void)
|
|||
else
|
||||
{
|
||||
if (!M_CheckParm("-server"))
|
||||
G_SetGameModified(true);
|
||||
G_SetUsedCheats(true);
|
||||
autostart = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1882,7 +1882,7 @@ static void Command_Map_f(void)
|
|||
const char *gametypename;
|
||||
boolean newresetplayers;
|
||||
|
||||
boolean mustmodifygame;
|
||||
boolean wouldSetCheats;
|
||||
|
||||
INT32 newmapnum;
|
||||
|
||||
|
@ -1903,11 +1903,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"));
|
||||
|
@ -1961,9 +1961,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
|
||||
|
@ -4313,7 +4313,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)
|
||||
|
@ -4334,7 +4334,7 @@ static void Gravity_OnChange(void)
|
|||
#endif
|
||||
|
||||
if (!CV_IsSetToDefault(&cv_gravity))
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
gravity = cv_gravity.value;
|
||||
}
|
||||
|
||||
|
@ -4650,7 +4650,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)
|
||||
|
@ -4667,11 +4667,11 @@ static void Fishcake_OnChange(void)
|
|||
static void Command_Isgamemodified_f(void)
|
||||
{
|
||||
if (savemoddata)
|
||||
CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n"));
|
||||
CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n"));
|
||||
else if (modifiedgame)
|
||||
CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n"));
|
||||
CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n"));
|
||||
else
|
||||
CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n"));
|
||||
CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n"));
|
||||
}
|
||||
|
||||
static void Command_Cheats_f(void)
|
||||
|
|
|
@ -2907,7 +2907,9 @@ static boolean GoodDataFileName(const char *s)
|
|||
p = s + strlen(s) - strlen(tail);
|
||||
if (p <= s) return false; // too short
|
||||
if (!fasticmp(p, tail)) return false; // doesn't end in .dat
|
||||
if (fasticmp(s, "gamedata.dat")) return false;
|
||||
|
||||
if (fasticmp(s, "gamedata.dat")) return false; // Don't overwrite default gamedata
|
||||
if (fasticmp(s, "main.dat")) return false; // Don't overwrite default time attack replays
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1575,7 +1575,9 @@ void F_GameEvaluationDrawer(void)
|
|||
{
|
||||
V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:");
|
||||
|
||||
if (!(netgame) && (!modifiedgame || savemoddata))
|
||||
if (netgame)
|
||||
V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!");
|
||||
else
|
||||
{
|
||||
INT32 startcoord = 32;
|
||||
|
||||
|
@ -1590,10 +1592,6 @@ 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!");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1657,7 +1655,7 @@ void F_GameEvaluationTicker(void)
|
|||
HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!");
|
||||
S_StartSound(NULL, sfx_s3k68);
|
||||
}
|
||||
else if (!modifiedgame || savemoddata)
|
||||
else
|
||||
{
|
||||
++timesBeaten;
|
||||
|
||||
|
@ -1672,13 +1670,6 @@ void F_GameEvaluationTicker(void)
|
|||
|
||||
G_SaveGameData();
|
||||
}
|
||||
else
|
||||
{
|
||||
HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8);
|
||||
HU_SetCEchoDuration(6);
|
||||
HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Modified games can't unlock extras!");
|
||||
S_StartSound(NULL, sfx_s3k68);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
119
src/g_game.c
119
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;
|
||||
|
@ -755,7 +756,24 @@ void G_SetGameModified(boolean silent)
|
|||
savemoddata = false;
|
||||
|
||||
if (!silent)
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to record statistics.\n"));
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play Record Attack.\n"));
|
||||
|
||||
// If in record attack recording, cancel it.
|
||||
if (modeattacking)
|
||||
M_EndModeAttackRun();
|
||||
else if (marathonmode)
|
||||
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)
|
||||
|
@ -3842,8 +3860,7 @@ static void G_UpdateVisited(void)
|
|||
{
|
||||
boolean spec = G_IsSpecialStage(gamemap);
|
||||
// Update visitation flags?
|
||||
if ((!modifiedgame || savemoddata) // Not modified
|
||||
&& !multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode
|
||||
if (!multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode
|
||||
&& !stagefailed) // Did not fail the stage
|
||||
{
|
||||
UINT8 earnedEmblems;
|
||||
|
@ -3911,14 +3928,18 @@ static void G_HandleSaveLevel(void)
|
|||
remove(liveeventbackup);
|
||||
cursaveslot = 0;
|
||||
}
|
||||
else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking))
|
||||
else if (!usedCheats && !(netgame || multiplayer || ultimatemode || demorecording || 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 || demoplayback || demorecording || metalrecording || modeattacking)
|
||||
&& (!modifiedgame || savemoddata) && 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
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -4194,8 +4215,10 @@ static void G_DoContinued(void)
|
|||
tokenlist = 0;
|
||||
token = 0;
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && (!modifiedgame || savemoddata) && cursaveslot > 0)
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && !usedCheats && cursaveslot > 0)
|
||||
{
|
||||
G_SaveGameOver((UINT32)cursaveslot, true);
|
||||
}
|
||||
|
||||
// Reset # of lives
|
||||
pl->lives = (ultimatemode) ? 1 : startinglivesbalance[numgameovers];
|
||||
|
@ -4260,13 +4283,17 @@ void G_LoadGameSettings(void)
|
|||
S_InitRuntimeSounds();
|
||||
}
|
||||
|
||||
#define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual
|
||||
#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3
|
||||
|
||||
// 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
|
||||
|
@ -4277,6 +4304,9 @@ void G_LoadGameData(void)
|
|||
UINT8 recmares;
|
||||
INT32 curmare;
|
||||
|
||||
// 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
|
||||
|
@ -4284,27 +4314,35 @@ void G_LoadGameData(void)
|
|||
totalplaytime = 0; // total play time (separate from all)
|
||||
|
||||
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
|
||||
#ifdef COMPAT_GAMEDATA_ID // backwards compat behavior
|
||||
&& versionID != COMPAT_GAMEDATA_ID
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const char *gdfolder = "the SRB2 folder";
|
||||
if (strcmp(srb2home,"."))
|
||||
|
@ -4317,13 +4355,35 @@ void G_LoadGameData(void)
|
|||
|
||||
totalplaytime = READUINT32(save_p);
|
||||
|
||||
modded = READUINT8(save_p);
|
||||
#ifdef COMPAT_GAMEDATA_ID
|
||||
if (versionID == COMPAT_GAMEDATA_ID)
|
||||
{
|
||||
// We'll temporarily use the old condition when loading an older file.
|
||||
// The proper mod-specific hash will get saved in afterwards.
|
||||
boolean modded = READUINT8(save_p);
|
||||
|
||||
// Aha! Someone's been screwing with the save file!
|
||||
if ((modded && !savemoddata))
|
||||
goto datacorrupt;
|
||||
else if (modded != true && modded != false)
|
||||
goto datacorrupt;
|
||||
if (modded && !savemoddata)
|
||||
{
|
||||
goto datacorrupt;
|
||||
}
|
||||
else if (modded != true && modded != false)
|
||||
{
|
||||
goto datacorrupt;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Quick & dirty hash for what mod this save file is for.
|
||||
UINT32 modID = READUINT32(save_p);
|
||||
UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder);
|
||||
|
||||
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++)
|
||||
|
@ -4409,6 +4469,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();
|
||||
|
||||
|
@ -4448,7 +4514,7 @@ void G_SaveGameData(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (modifiedgame && !savemoddata)
|
||||
if (usedCheats)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
|
@ -4456,12 +4522,11 @@ void G_SaveGameData(void)
|
|||
}
|
||||
|
||||
// Version test
|
||||
WRITEUINT32(save_p, 0xFCAFE211);
|
||||
WRITEUINT32(save_p, GAMEDATA_ID);
|
||||
|
||||
WRITEUINT32(save_p, totalplaytime);
|
||||
|
||||
btemp = (UINT8)(savemoddata || modifiedgame);
|
||||
WRITEUINT8(save_p, btemp);
|
||||
WRITEUINT32(save_p, quickncasehash(timeattackfolder, sizeof timeattackfolder));
|
||||
|
||||
// TODO put another cipher on these things? meh, I don't care...
|
||||
for (i = 0; i < NUMMAPS; i++)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -2994,7 +2994,7 @@ static void HU_DrawCoopOverlay(void)
|
|||
V_DrawSmallScaledPatch(148, 172, 0, tokenicon);
|
||||
}
|
||||
|
||||
if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
|
||||
if (LUA_HudEnabled(hud_tabemblems))
|
||||
{
|
||||
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
|
||||
V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon);
|
||||
|
|
|
@ -3630,6 +3630,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)
|
||||
|
@ -4232,6 +4242,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;
|
||||
|
|
|
@ -72,16 +72,13 @@ static UINT8 cheatf_ultimate(void)
|
|||
|
||||
static UINT8 cheatf_warp(void)
|
||||
{
|
||||
if (modifiedgame)
|
||||
return 0;
|
||||
|
||||
if (menuactive && currentMenu != &MainDef)
|
||||
return 0; // Only on the main menu!
|
||||
|
||||
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
|
||||
|
@ -97,16 +94,13 @@ static UINT8 cheatf_devmode(void)
|
|||
{
|
||||
UINT8 i;
|
||||
|
||||
if (modifiedgame)
|
||||
return 0;
|
||||
|
||||
if (menuactive && currentMenu != &MainDef)
|
||||
return 0; // Only on the main menu!
|
||||
|
||||
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 +269,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 +284,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 +299,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 +873,7 @@ void Command_Devmode_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
|
||||
void Command_Setrings_f(void)
|
||||
|
@ -905,7 +899,7 @@ void Command_Setrings_f(void)
|
|||
// no totalsphere addition to revert
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -928,7 +922,7 @@ void Command_Setlives_f(void)
|
|||
P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1)));
|
||||
}
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -955,7 +949,7 @@ void Command_Setcontinues_f(void)
|
|||
|
||||
players[consoleplayer].continues = numcontinues;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1446,7 +1440,7 @@ void Command_ObjectPlace_f(void)
|
|||
REQUIRE_SINGLEPLAYER;
|
||||
REQUIRE_NOULTIMATE;
|
||||
|
||||
G_SetGameModified(multiplayer);
|
||||
G_SetUsedCheats(false);
|
||||
|
||||
silent = COM_CheckParm("-silent");
|
||||
|
||||
|
|
|
@ -200,9 +200,6 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void)
|
|||
char cechoText[992] = "";
|
||||
UINT8 cechoLines = 0;
|
||||
|
||||
if (modifiedgame && !savemoddata)
|
||||
return false;
|
||||
|
||||
M_CheckUnlockConditions();
|
||||
|
||||
// Go through extra emblems
|
||||
|
|
36
src/m_menu.c
36
src/m_menu.c
|
@ -757,12 +757,12 @@ static menuitem_t SR_EmblemHintMenu[] =
|
|||
static menuitem_t SP_MainMenu[] =
|
||||
{
|
||||
// Note: If changing the positions here, also change them in M_SinglePlayerMenu()
|
||||
{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76},
|
||||
{IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84},
|
||||
{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92},
|
||||
{IT_SECRET, NULL, "Marathon Run", M_Marathon, 100},
|
||||
{IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108},
|
||||
{IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}
|
||||
{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76},
|
||||
{IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84},
|
||||
{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92},
|
||||
{IT_SECRET, NULL, "Marathon Run", M_Marathon, 100},
|
||||
{IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108},
|
||||
{IT_CALL | IT_STRING, NULL, "Statistics", M_Statistics, 116}
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -3515,10 +3515,12 @@ boolean M_Responder(event_t *ev)
|
|||
{
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL
|
||||
|| (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU)
|
||||
&& (currentMenu->menuitems[itemOn].status & IT_CALLTYPE))
|
||||
&& (currentMenu->menuitems[itemOn].status & IT_CALLTYPE))
|
||||
{
|
||||
#ifndef DEVELOP
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata)
|
||||
// TODO: Replays are scary, so I left the remaining instances of this alone.
|
||||
// It'd be nice to get rid of this once and for all though!
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && (modifiedgame && !savemoddata) && !usedCheats)
|
||||
{
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
|
@ -6710,7 +6712,7 @@ static void M_DrawAddons(void)
|
|||
|
||||
// draw save icon
|
||||
x = BASEVIDWIDTH - x - 16;
|
||||
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
|
||||
V_DrawSmallScaledPatch(x, y + 4, (!usedCheats ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
|
||||
|
||||
if (modifiedgame)
|
||||
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]);
|
||||
|
@ -7081,7 +7083,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)
|
||||
|
@ -7092,7 +7094,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)
|
||||
|
@ -7103,7 +7105,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,9 +8705,9 @@ static void M_DrawLoad(void)
|
|||
|
||||
M_DrawLoadGameData();
|
||||
|
||||
if (modifiedgame && !savemoddata)
|
||||
if (usedCheats)
|
||||
{
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified.");
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING:\x80 Cheats have been activated.");
|
||||
V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved.");
|
||||
}
|
||||
}
|
||||
|
@ -9009,17 +9011,17 @@ static void M_HandleLoadSave(INT32 choice)
|
|||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame)
|
||||
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata)
|
||||
{
|
||||
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 && !(!modifiedgame || savemoddata))
|
||||
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 modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
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"
|
||||
{
|
||||
|
|
|
@ -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 ((!modifiedgame || savemoddata) && cursaveslot > 0)
|
||||
if (!usedCheats && cursaveslot > 0)
|
||||
G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12003,11 +12003,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
|
|||
break;
|
||||
case MT_EMBLEM:
|
||||
if (netgame || multiplayer)
|
||||
return false; // Single player
|
||||
|
||||
if (modifiedgame && !savemoddata)
|
||||
return false; // No cheating!!
|
||||
|
||||
return false; // Single player (You're next on my shit list)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -7792,7 +7792,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
nextmapoverride = 0;
|
||||
skipstats = 0;
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata))
|
||||
if (!(netgame || multiplayer || demoplayback))
|
||||
mapvisited[gamemap-1] |= MV_VISITED;
|
||||
else if (netgame || multiplayer)
|
||||
mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently
|
||||
|
@ -7810,8 +7810,10 @@ 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)
|
||||
&& (!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.
|
||||
}
|
||||
lastmaploaded = gamemap; // HAS to be set after saving!!
|
||||
|
|
|
@ -1795,7 +1795,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
{ // Unlockable triggers required
|
||||
INT32 trigid = triggerline->args[1];
|
||||
|
||||
if ((modifiedgame && !savemoddata) || (netgame || multiplayer))
|
||||
if (netgame || multiplayer)
|
||||
return false;
|
||||
else if (trigid < 0 || trigid > 31) // limited by 32 bit variable
|
||||
{
|
||||
|
@ -1810,7 +1810,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
{ // An unlockable itself must be unlocked!
|
||||
INT32 unlockid = triggerline->args[1];
|
||||
|
||||
if ((modifiedgame && !savemoddata) || (netgame || multiplayer))
|
||||
if (netgame || multiplayer)
|
||||
return false;
|
||||
else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count
|
||||
{
|
||||
|
@ -2937,7 +2937,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
break;
|
||||
|
||||
case 441: // Trigger unlockable
|
||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer))
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
INT32 trigid = line->args[0];
|
||||
|
||||
|
|
|
@ -1092,7 +1092,7 @@ void Y_Ticker(void)
|
|||
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching!
|
||||
|
||||
// Update when done with tally
|
||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
|
||||
if (!(netgame || multiplayer) && !demoplayback)
|
||||
{
|
||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
||||
S_StartSound(NULL, sfx_s3k68);
|
||||
|
@ -1228,7 +1228,7 @@ void Y_Ticker(void)
|
|||
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching!
|
||||
|
||||
// Update when done with tally
|
||||
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
|
||||
if (!(netgame || multiplayer) && !demoplayback)
|
||||
{
|
||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
||||
S_StartSound(NULL, sfx_s3k68);
|
||||
|
|
Loading…
Reference in a new issue