mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-03-07 20:01:21 +00:00
Gamedata-related changes + Crash tracking
- Combine multiple adjacent saves
- Generally could happen during game ticking, combined via gamedata->deferredstate
- DEFINITELY happened in splitscreen PWR handling, adjust those loops directly
- Write "dirty" state via gamedata->crashflags on everything except safe, intentful unloads
- Add UC_CRASH, which unlocks dependent on the above "dirty" state being present at gamedata load
- We can use this for something more useful and less funny later.
- Play "O_LOSERC" on the menu, starting with the Challenges screen, if a UC_CRASH condition has been met.
This commit is contained in:
parent
b4217e1afd
commit
53ce2e4287
17 changed files with 117 additions and 40 deletions
|
|
@ -977,6 +977,9 @@ void D_ClearState(void)
|
|||
|
||||
cursongcredit.def = NULL;
|
||||
|
||||
if (gamedata->deferredsave)
|
||||
G_SaveGameData(true);
|
||||
|
||||
G_SetGamestate(GS_NULL);
|
||||
wipegamestate = GS_NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2482,6 +2482,11 @@ static void readcondition(UINT8 set, UINT32 id, char *word2)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(params[0], "CRASH"))
|
||||
{
|
||||
//PARAMCHECK(1);
|
||||
ty = UC_CRASH;
|
||||
}
|
||||
else if (fastcmp(params[0], "AND"))
|
||||
{
|
||||
//PARAMCHECK(1);
|
||||
|
|
@ -2689,7 +2694,7 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
if (!GoodDataFileName(word2))
|
||||
I_Error("Maincfg: bad data file name '%s'\n", word2);
|
||||
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(false); // undirty your old gamedata
|
||||
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
|
||||
strlwr(gamedatafilename);
|
||||
savemoddata = true;
|
||||
|
|
|
|||
|
|
@ -1081,7 +1081,7 @@ void F_GameEvaluationTicker(void)
|
|||
++gamedata->timesBeaten;
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
54
src/g_game.c
54
src/g_game.c
|
|
@ -649,7 +649,7 @@ void G_UpdateRecords(void)
|
|||
}
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
gamedata->deferredsave = true;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2282,19 +2282,6 @@ static inline void G_PlayerFinishLevel(INT32 player)
|
|||
|
||||
p->starpostnum = 0;
|
||||
memset(&p->respawn, 0, sizeof (p->respawn));
|
||||
|
||||
// SRB2kart: Increment the "matches played" counter.
|
||||
if (player == consoleplayer)
|
||||
{
|
||||
if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified)
|
||||
{
|
||||
gamedata->matchesplayed++;
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
}
|
||||
|
||||
legitimateexit = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3697,7 +3684,7 @@ static void G_UpdateVisited(void)
|
|||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
|
||||
static boolean CanSaveLevel(INT32 mapnum)
|
||||
|
|
@ -4005,6 +3992,19 @@ static void G_DoCompleted(void)
|
|||
if (modeattacking && pausedelay)
|
||||
pausedelay = 0;
|
||||
|
||||
if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified)
|
||||
{
|
||||
// Done before forced addition of PF_NOCONTEST to make UCRP_NOCONTEST harder to achieve
|
||||
gamedata->matchesplayed++;
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
gamedata->deferredsave = true;
|
||||
}
|
||||
|
||||
if (gamedata->deferredsave)
|
||||
G_SaveGameData(true);
|
||||
|
||||
legitimateexit = false;
|
||||
|
||||
gameaction = ga_nothing;
|
||||
|
||||
if (metalplayback)
|
||||
|
|
@ -4317,7 +4317,7 @@ void G_LoadGameSettings(void)
|
|||
}
|
||||
|
||||
#define GD_VERSIONCHECK 0xBA5ED123 // Change every major version, as usual
|
||||
#define GD_VERSIONMINOR 1 // Change every format update
|
||||
#define GD_VERSIONMINOR 2 // Change every format update
|
||||
|
||||
static const char *G_GameDataFolder(void)
|
||||
{
|
||||
|
|
@ -4351,6 +4351,7 @@ void G_LoadGameData(void)
|
|||
|
||||
gamedata->totalplaytime = 0; // total play time (separate from all)
|
||||
gamedata->matchesplayed = 0; // SRB2Kart: matches played & finished
|
||||
gamedata->crashflags = 0;
|
||||
|
||||
if (M_CheckParm("-nodata"))
|
||||
{
|
||||
|
|
@ -4398,6 +4399,13 @@ void G_LoadGameData(void)
|
|||
gamedata->totalplaytime = READUINT32(save.p);
|
||||
gamedata->matchesplayed = READUINT32(save.p);
|
||||
|
||||
if (versionMinor > 1)
|
||||
{
|
||||
gamedata->crashflags = READUINT8(save.p);
|
||||
if (gamedata->crashflags & GDCRASH_LAST)
|
||||
gamedata->crashflags |= GDCRASH_ANY;
|
||||
}
|
||||
|
||||
{
|
||||
// Quick & dirty hash for what mod this save file is for.
|
||||
UINT32 modID = READUINT32(save.p);
|
||||
|
|
@ -4543,13 +4551,15 @@ void G_LoadGameData(void)
|
|||
|
||||
// G_SaveGameData
|
||||
// Saves the main data file, which stores information such as emblems found, etc.
|
||||
void G_SaveGameData(void)
|
||||
void G_SaveGameData(boolean dirty)
|
||||
{
|
||||
size_t length;
|
||||
INT32 i, j;
|
||||
UINT8 btemp;
|
||||
savebuffer_t save = {0};
|
||||
|
||||
gamedata->deferredsave = false;
|
||||
|
||||
if (!gamedata->loaded)
|
||||
return; // If never loaded (-nodata), don't save
|
||||
|
||||
|
|
@ -4561,7 +4571,7 @@ void G_SaveGameData(void)
|
|||
return;
|
||||
}
|
||||
|
||||
length = (4+1+4+4+1+(MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+4+4+2);
|
||||
length = (4+1+4+4+1+4+(MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+4+4+2);
|
||||
if (gamedata->challengegrid)
|
||||
{
|
||||
length += gamedata->challengegridwidth * CHALLENGEGRIDHEIGHT;
|
||||
|
|
@ -4580,6 +4590,14 @@ void G_SaveGameData(void)
|
|||
WRITEUINT8(save.p, GD_VERSIONMINOR); // 1
|
||||
WRITEUINT32(save.p, gamedata->totalplaytime); // 4
|
||||
WRITEUINT32(save.p, gamedata->matchesplayed); // 4
|
||||
|
||||
{
|
||||
UINT8 crashflags = (gamedata->crashflags & GDCRASH_ANY);
|
||||
if (dirty)
|
||||
crashflags |= GDCRASH_LAST;
|
||||
WRITEUINT8(save.p, crashflags); // 1
|
||||
}
|
||||
|
||||
WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64));
|
||||
|
||||
// To save space, use one bit per collected/achieved/unlocked flag
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ boolean G_IsTitleCardAvailable(void);
|
|||
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
|
||||
void G_LoadGame(UINT32 slot, INT16 mapoverride);
|
||||
|
||||
void G_SaveGameData(void);
|
||||
void G_SaveGameData(boolean dirty);
|
||||
|
||||
void G_SaveGame(UINT32 slot, INT16 mapnum);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "v_video.h"
|
||||
#include "f_finale.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_cond.h"
|
||||
|
||||
#ifdef PC_DOS
|
||||
#include <stdio.h> // for snprintf
|
||||
|
|
@ -338,9 +339,17 @@ boolean M_Responder(event_t *ev)
|
|||
void M_PlayMenuJam(void)
|
||||
{
|
||||
menu_t *refMenu = (menuactive ? currentMenu : restoreMenu);
|
||||
static boolean loserclubpermitted = false;
|
||||
boolean loserclub = (loserclubpermitted && (gamedata->crashflags & GDCRASH_LOSERCLUB));
|
||||
|
||||
if (challengesmenu.pending)
|
||||
{
|
||||
S_StopMusic();
|
||||
cursongcredit.def = NULL;
|
||||
|
||||
loserclubpermitted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Playing())
|
||||
return;
|
||||
|
|
@ -351,15 +360,27 @@ void M_PlayMenuJam(void)
|
|||
{
|
||||
S_StopMusic();
|
||||
cursongcredit.def = NULL;
|
||||
return;
|
||||
}
|
||||
else
|
||||
else if (!loserclub)
|
||||
{
|
||||
if (NotCurrentlyPlaying(refMenu->music))
|
||||
{
|
||||
S_ChangeMusicInternal(refMenu->music, true);
|
||||
S_ShowMusicCredit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (loserclub)
|
||||
{
|
||||
if (refMenu != NULL && NotCurrentlyPlaying("LOSERC"))
|
||||
{
|
||||
S_ChangeMusicInternal("LOSERC", true);
|
||||
S_ShowMusicCredit();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -397,6 +397,7 @@ void K_CashInPowerLevels(void)
|
|||
{
|
||||
SINT8 powerType = K_UsingPowerLevels();
|
||||
UINT8 i;
|
||||
boolean gamedataupdate;
|
||||
|
||||
//CONS_Printf("\n========\n");
|
||||
//CONS_Printf("Cashing in power level changes...\n");
|
||||
|
|
@ -417,14 +418,19 @@ void K_CashInPowerLevels(void)
|
|||
{
|
||||
pr->powerlevels[powerType] = clientpowerlevels[i][powerType];
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
gamedataupdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
clientPowerAdd[i] = 0;
|
||||
}
|
||||
|
||||
if (gamedataupdate)
|
||||
{
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
|
||||
//CONS_Printf("========\n");
|
||||
}
|
||||
|
||||
|
|
@ -638,6 +644,6 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
|
|||
pr->powerlevels[powerType] = yourPower + inc;
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/m_cond.c
12
src/m_cond.c
|
|
@ -486,6 +486,7 @@ void M_ClearSecrets(void)
|
|||
gamedata->challengegridwidth = 0;
|
||||
|
||||
gamedata->timesBeaten = 0;
|
||||
gamedata->crashflags = 0;
|
||||
|
||||
// Re-unlock any always unlocked things
|
||||
M_UpdateUnlockablesAndExtraEmblems(false);
|
||||
|
|
@ -592,6 +593,13 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
|
|||
return gamedata->unlocked[cn->requirement-1];
|
||||
case UC_CONDITIONSET: // requires condition set x to already be achieved
|
||||
return M_Achieved(cn->requirement-1);
|
||||
case UC_CRASH:
|
||||
if (gamedata->crashflags & (GDCRASH_LAST|GDCRASH_ANY))
|
||||
{
|
||||
gamedata->crashflags |= GDCRASH_LOSERCLUB;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case UC_AND: // Just for string building
|
||||
return true;
|
||||
|
|
@ -859,6 +867,10 @@ static const char *M_GetConditionString(condition_t *cn)
|
|||
gamedata->unlocked[cn->requirement-1]
|
||||
? unlockables[cn->requirement-1].name
|
||||
: "???");
|
||||
case UC_CRASH:
|
||||
if (gamedata->crashflags & (GDCRASH_LAST|GDCRASH_ANY))
|
||||
return "Relaunch \"Dr. Robotnik's Ring Racers\" after a crash";
|
||||
return NULL;
|
||||
|
||||
case UC_AND:
|
||||
return "&";
|
||||
|
|
|
|||
10
src/m_cond.h
10
src/m_cond.h
|
|
@ -43,6 +43,8 @@ typedef enum
|
|||
UC_UNLOCKABLE, // UNLOCKABLE [unlockable number]
|
||||
UC_CONDITIONSET, // CONDITIONSET [condition set number]
|
||||
|
||||
UC_CRASH, // Hee ho !
|
||||
|
||||
UC_AND, // Just for string building
|
||||
|
||||
UCRP_REQUIRESPLAYING, // All conditions below this can only be checked if (Playing() && gamestate == GS_LEVEL).
|
||||
|
|
@ -177,12 +179,17 @@ typedef enum
|
|||
#endif
|
||||
#define challengegridloops (gamedata->challengegridwidth >= CHALLENGEGRIDLOOPWIDTH)
|
||||
|
||||
#define GDCRASH_LAST 0x01
|
||||
#define GDCRASH_ANY 0x02
|
||||
#define GDCRASH_LOSERCLUB 0x04
|
||||
|
||||
// GAMEDATA STRUCTURE
|
||||
// Everything that would get saved in gamedata.dat
|
||||
struct gamedata_t
|
||||
{
|
||||
// WHENEVER OR NOT WE'RE READY TO SAVE
|
||||
boolean loaded;
|
||||
boolean deferredsave;
|
||||
|
||||
// CONDITION SETS ACHIEVED
|
||||
boolean achieved[MAXCONDITIONSETS];
|
||||
|
|
@ -204,6 +211,9 @@ struct gamedata_t
|
|||
// PLAY TIME
|
||||
UINT32 totalplaytime;
|
||||
UINT32 matchesplayed;
|
||||
|
||||
// Funny
|
||||
UINT8 crashflags;
|
||||
};
|
||||
|
||||
extern gamedata_t *gamedata;
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ void M_ChallengesTick(void)
|
|||
{
|
||||
// All done! Let's save the unlocks we've busted open.
|
||||
challengesmenu.pending = false;
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
}
|
||||
else if (challengesmenu.fade < 5)
|
||||
|
|
|
|||
|
|
@ -554,7 +554,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
gamedata->collected[special->health-1] = gotcollected = true;
|
||||
if (!M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
S_StartSound(NULL, sfx_ncitem);
|
||||
G_SaveGameData();
|
||||
gamedata->deferredsave = true;
|
||||
}
|
||||
|
||||
if (netgame)
|
||||
|
|
|
|||
|
|
@ -7444,6 +7444,7 @@ static void P_InitGametype(void)
|
|||
|
||||
// Started a game? Move on to the next jam when you go back to the title screen
|
||||
CV_SetValue(&cv_menujam_update, 1);
|
||||
gamedata->crashflags &= ~GDCRASH_LOSERCLUB;
|
||||
}
|
||||
|
||||
struct minimapinfo minimapinfo;
|
||||
|
|
@ -7936,7 +7937,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
|
||||
|
||||
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
|
||||
G_AddMapToBuffer(gamemap-1);
|
||||
|
|
|
|||
|
|
@ -3310,7 +3310,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
// Unlocked something?
|
||||
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
{
|
||||
G_SaveGameData(); // only save if unlocked something
|
||||
gamedata->deferredsave = true; // only save if unlocked something
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -632,8 +632,9 @@ void P_Ticker(boolean run)
|
|||
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
|
||||
|
||||
// TODO would this be laggy with more conditions in play...
|
||||
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
G_SaveGameData();
|
||||
if ((!demo.playback && M_UpdateUnlockablesAndExtraEmblems(true))
|
||||
|| gamedata->deferredsave)
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
|
||||
// Keep track of how long they've been playing!
|
||||
|
|
|
|||
|
|
@ -1737,7 +1737,7 @@ void I_Quit(void)
|
|||
if (Playing())
|
||||
K_PlayerForfeit(consoleplayer, true);
|
||||
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
G_SaveGameData(false); // Tails 12-08-2002 -- undirty your save
|
||||
//added:16-02-98: when recording a demo, should exit using 'q' key,
|
||||
// but sometimes we forget and use 'F10'.. so save here too.
|
||||
|
||||
|
|
@ -1821,7 +1821,7 @@ void I_Error(const char *error, ...)
|
|||
if (errorcount == 8)
|
||||
{
|
||||
M_SaveConfig(NULL);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
if (errorcount > 20)
|
||||
{
|
||||
|
|
@ -1852,7 +1852,7 @@ void I_Error(const char *error, ...)
|
|||
|
||||
M_SaveConfig(NULL); // save game config, cvars..
|
||||
D_SaveBan(); // save the ban list
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
G_SaveGameData(true); // Tails 12-08-2002
|
||||
|
||||
// Shutdown. Here might be other errors.
|
||||
|
||||
|
|
|
|||
|
|
@ -2983,7 +2983,7 @@ void I_Quit(void)
|
|||
if (Playing())
|
||||
K_PlayerForfeit(consoleplayer, true);
|
||||
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
G_SaveGameData(false); // Tails 12-08-2002 -- undirty your save
|
||||
//added:16-02-98: when recording a demo, should exit using 'q' key,
|
||||
// but sometimes we forget and use 'F10'.. so save here too.
|
||||
|
||||
|
|
@ -3078,7 +3078,7 @@ void I_Error(const char *error, ...)
|
|||
if (errorcount == 9)
|
||||
{
|
||||
M_SaveConfig(NULL);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
if (errorcount > 20)
|
||||
{
|
||||
|
|
@ -3142,7 +3142,7 @@ void I_Error(const char *error, ...)
|
|||
#ifndef NONET
|
||||
D_SaveBan(); // save the ban list
|
||||
#endif
|
||||
G_SaveGameData(); // Tails 12-08-2002
|
||||
G_SaveGameData(true); // Tails 12-08-2002
|
||||
|
||||
// Shutdown. Here might be other errors.
|
||||
if (demorecording)
|
||||
|
|
|
|||
|
|
@ -607,7 +607,7 @@ void I_Error(const char *error, ...)
|
|||
if (errorcount == 7)
|
||||
{
|
||||
M_SaveConfig(NULL);
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
if (errorcount > 20)
|
||||
{
|
||||
|
|
@ -636,7 +636,7 @@ void I_Error(const char *error, ...)
|
|||
if (!errorcount)
|
||||
{
|
||||
M_SaveConfig(NULL); // save game config, cvars..
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(true);
|
||||
}
|
||||
|
||||
// save demo, could be useful for debug
|
||||
|
|
@ -726,7 +726,7 @@ void I_Quit(void)
|
|||
G_CheckDemoStatus();
|
||||
|
||||
M_SaveConfig(NULL); // save game config, cvars..
|
||||
G_SaveGameData();
|
||||
G_SaveGameData(false); // undirty your save
|
||||
|
||||
// maybe it needs that the ticcount continues,
|
||||
// or something else that will be finished by I_ShutdownSystem(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue