mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Conversion to using gamedata_t
A small piece of (STJr/SRB2!1756). Due to how RR currently handles time attack records and how it WILL handle unlocks, it's not currently feasible to split everything such that you can have two independent gamedata_t... but what's done so far is certainly more sane and less dependent on global variables Other minor refactors: - M_UpdateUnlockablesAndExtraEmblems and M_SilentUpdateUnlockablesAndEmblems are now one function with a boolean for loudness - Unlock prints are currently living in the console, since the cecho stuff was a little broken
This commit is contained in:
parent
6a2aa87e95
commit
845fe12b52
18 changed files with 174 additions and 186 deletions
|
|
@ -1377,6 +1377,8 @@ void D_SRB2Main(void)
|
||||||
Z_Init();
|
Z_Init();
|
||||||
CON_SetLoadingProgress(LOADED_ZINIT);
|
CON_SetLoadingProgress(LOADED_ZINIT);
|
||||||
|
|
||||||
|
M_NewGameDataStruct();
|
||||||
|
|
||||||
// Do this up here so that WADs loaded through the command line can use ExecCfg
|
// Do this up here so that WADs loaded through the command line can use ExecCfg
|
||||||
COM_Init();
|
COM_Init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,6 @@ extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
|
||||||
extern INT32 viewwindowx, viewwindowy;
|
extern INT32 viewwindowx, viewwindowy;
|
||||||
extern INT32 viewwidth, scaledviewwidth;
|
extern INT32 viewwidth, scaledviewwidth;
|
||||||
|
|
||||||
extern boolean gamedataloaded;
|
|
||||||
|
|
||||||
// Player taking events, and displaying.
|
// Player taking events, and displaying.
|
||||||
extern INT32 consoleplayer;
|
extern INT32 consoleplayer;
|
||||||
extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
|
extern INT32 displayplayers[MAXSPLITSCREENPLAYERS];
|
||||||
|
|
@ -538,9 +536,6 @@ typedef struct
|
||||||
extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES];
|
extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES];
|
||||||
extern UINT32 lastcustomtol;
|
extern UINT32 lastcustomtol;
|
||||||
|
|
||||||
extern tic_t totalplaytime;
|
|
||||||
extern UINT32 matchesplayed;
|
|
||||||
|
|
||||||
extern UINT8 stagefailed;
|
extern UINT8 stagefailed;
|
||||||
|
|
||||||
// Emeralds stored as bits to throw savegame hackers off.
|
// Emeralds stored as bits to throw savegame hackers off.
|
||||||
|
|
@ -682,8 +677,6 @@ extern INT16 votelevels[4][2];
|
||||||
extern SINT8 votes[MAXPLAYERS];
|
extern SINT8 votes[MAXPLAYERS];
|
||||||
extern SINT8 pickedvote;
|
extern SINT8 pickedvote;
|
||||||
|
|
||||||
extern UINT32 timesBeaten; // # of times the game has been beaten.
|
|
||||||
|
|
||||||
// ===========================
|
// ===========================
|
||||||
// Internal parameters, fixed.
|
// Internal parameters, fixed.
|
||||||
// ===========================
|
// ===========================
|
||||||
|
|
|
||||||
|
|
@ -866,7 +866,7 @@ boolean F_CreditResponder(event_t *event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (!(timesBeaten) && !(netgame || multiplayer) && !cht_debug)
|
/*if (!(gamedata->timesBeaten) && !(netgame || multiplayer) && !cht_debug)
|
||||||
return false;*/
|
return false;*/
|
||||||
|
|
||||||
if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_BACKSPACE)
|
if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_BACKSPACE)
|
||||||
|
|
@ -1024,31 +1024,6 @@ void F_GameEvaluationDrawer(void)
|
||||||
|
|
||||||
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
|
V_DrawCreditString((BASEVIDWIDTH - V_CreditStringWidth(endingtext))<<(FRACBITS-1), (BASEVIDHEIGHT-100)<<(FRACBITS-1), 0, endingtext);
|
||||||
|
|
||||||
#if 0 // the following looks like hot garbage the more unlockables we add, and we now have a lot of unlockables
|
|
||||||
if (finalecount >= 5*TICRATE)
|
|
||||||
{
|
|
||||||
V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:");
|
|
||||||
|
|
||||||
if (!usedCheats)
|
|
||||||
{
|
|
||||||
INT32 startcoord = 32;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
|
||||||
{
|
|
||||||
if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS
|
|
||||||
&& unlockables[i].type && !unlockables[i].nocecho)
|
|
||||||
{
|
|
||||||
if (unlockables[i].unlocked)
|
|
||||||
V_DrawString(8, startcoord, 0, unlockables[i].name);
|
|
||||||
startcoord += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
V_DrawString(8, 96, V_YELLOWMAP, "Cheated games\ncan't unlock\nextras!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (marathonmode)
|
if (marathonmode)
|
||||||
{
|
{
|
||||||
const char *rtatext, *cuttext;
|
const char *rtatext, *cuttext;
|
||||||
|
|
@ -1101,9 +1076,9 @@ void F_GameEvaluationTicker(void)
|
||||||
{
|
{
|
||||||
if (!usedCheats)
|
if (!usedCheats)
|
||||||
{
|
{
|
||||||
++timesBeaten;
|
++gamedata->timesBeaten;
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
S_StartSound(NULL, sfx_s3k68);
|
S_StartSound(NULL, sfx_s3k68);
|
||||||
|
|
||||||
G_SaveGameData();
|
G_SaveGameData();
|
||||||
|
|
@ -1611,7 +1586,7 @@ void F_EndingDrawer(void)
|
||||||
//colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret
|
//colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret
|
||||||
V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<<V_ALPHASHIFT), str);
|
V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<<V_ALPHASHIFT), str);
|
||||||
V_DrawCharacter(32, BASEVIDHEIGHT-16, '>'|(trans<<V_ALPHASHIFT), false);
|
V_DrawCharacter(32, BASEVIDHEIGHT-16, '>'|(trans<<V_ALPHASHIFT), false);
|
||||||
V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<<V_ALPHASHIFT), " [S] ===>");
|
V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((gamedata->timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<<V_ALPHASHIFT), " [S] ===>");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finalecount > STOPPINGPOINT-(20+(2*TICRATE)))
|
if (finalecount > STOPPINGPOINT-(20+(2*TICRATE)))
|
||||||
|
|
|
||||||
66
src/g_game.c
66
src/g_game.c
|
|
@ -189,7 +189,8 @@ struct quake quake;
|
||||||
|
|
||||||
// Map Header Information
|
// Map Header Information
|
||||||
mapheader_t** mapheaderinfo = {NULL};
|
mapheader_t** mapheaderinfo = {NULL};
|
||||||
INT32 nummapheaders, mapallocsize = 0;
|
INT32 nummapheaders = 0;
|
||||||
|
INT32 mapallocsize = 0;
|
||||||
|
|
||||||
// Kart cup definitions
|
// Kart cup definitions
|
||||||
cupheader_t *kartcupheaders = NULL;
|
cupheader_t *kartcupheaders = NULL;
|
||||||
|
|
@ -208,10 +209,6 @@ UINT32 tokenlist; // List of tokens collected
|
||||||
boolean gottoken; // Did you get a token? Used for end of act
|
boolean gottoken; // Did you get a token? Used for end of act
|
||||||
INT32 tokenbits; // Used for setting token bits
|
INT32 tokenbits; // Used for setting token bits
|
||||||
|
|
||||||
tic_t totalplaytime;
|
|
||||||
UINT32 matchesplayed; // SRB2Kart
|
|
||||||
boolean gamedataloaded = false;
|
|
||||||
|
|
||||||
// Temporary holding place for nights data for the current map
|
// Temporary holding place for nights data for the current map
|
||||||
//nightsdata_t ntemprecords;
|
//nightsdata_t ntemprecords;
|
||||||
|
|
||||||
|
|
@ -340,9 +337,6 @@ static void G_ResetRandMapBuffer(void)
|
||||||
//intentionally not resetting randmaps.counttogametype here
|
//intentionally not resetting randmaps.counttogametype here
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grading
|
|
||||||
UINT32 timesBeaten;
|
|
||||||
|
|
||||||
typedef struct joystickvector2_s
|
typedef struct joystickvector2_s
|
||||||
{
|
{
|
||||||
INT32 xaxis;
|
INT32 xaxis;
|
||||||
|
|
@ -600,7 +594,7 @@ static void G_UpdateRecordReplays(void)
|
||||||
if ((earnedEmblems = M_CheckLevelEmblems()))
|
if ((earnedEmblems = M_CheckLevelEmblems()))
|
||||||
CONS_Printf(M_GetText("\x82" "Earned %hu medal%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
CONS_Printf(M_GetText("\x82" "Earned %hu medal%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
|
|
||||||
// SRB2Kart - save here so you NEVER lose your earned times/medals.
|
// SRB2Kart - save here so you NEVER lose your earned times/medals.
|
||||||
|
|
@ -2194,8 +2188,8 @@ static inline void G_PlayerFinishLevel(INT32 player)
|
||||||
{
|
{
|
||||||
if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified)
|
if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified)
|
||||||
{
|
{
|
||||||
matchesplayed++;
|
gamedata->matchesplayed++;
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
G_SaveGameData();
|
G_SaveGameData();
|
||||||
}
|
}
|
||||||
|
|
@ -3691,7 +3685,7 @@ static void G_UpdateVisited(void)
|
||||||
if ((earnedEmblems = M_CompletionEmblems()))
|
if ((earnedEmblems = M_CompletionEmblems()))
|
||||||
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
G_SaveGameData();
|
G_SaveGameData();
|
||||||
}
|
}
|
||||||
|
|
@ -3876,7 +3870,7 @@ static void G_GetNextMap(void)
|
||||||
while (cup)
|
while (cup)
|
||||||
{
|
{
|
||||||
// Not unlocked? Grab the next result afterwards
|
// Not unlocked? Grab the next result afterwards
|
||||||
if (!marathonmode && cup->unlockrequired != -1 && !unlockables[cup->unlockrequired].unlocked)
|
if (!marathonmode && cup->unlockrequired != -1 && !gamedata->unlocked[cup->unlockrequired])
|
||||||
{
|
{
|
||||||
cup = cup->next;
|
cup = cup->next;
|
||||||
gettingresult = 1;
|
gettingresult = 1;
|
||||||
|
|
@ -4326,15 +4320,15 @@ void G_LoadGameData(void)
|
||||||
UINT32 numgamedatamapheaders;
|
UINT32 numgamedatamapheaders;
|
||||||
|
|
||||||
// Stop saving, until we successfully load it again.
|
// Stop saving, until we successfully load it again.
|
||||||
gamedataloaded = false;
|
gamedata->loaded = false;
|
||||||
|
|
||||||
// Clear things so previously read gamedata doesn't transfer
|
// Clear things so previously read gamedata doesn't transfer
|
||||||
// to new gamedata
|
// to new gamedata
|
||||||
G_ClearRecords(); // main and nights records
|
G_ClearRecords(); // records
|
||||||
M_ClearSecrets(); // emblems, unlocks, maps visited, etc
|
M_ClearSecrets(); // emblems, unlocks, maps visited, etc
|
||||||
|
|
||||||
totalplaytime = 0; // total play time (separate from all)
|
gamedata->totalplaytime = 0; // total play time (separate from all)
|
||||||
matchesplayed = 0; // SRB2Kart: matches played & finished
|
gamedata->matchesplayed = 0; // SRB2Kart: matches played & finished
|
||||||
|
|
||||||
if (M_CheckParm("-nodata"))
|
if (M_CheckParm("-nodata"))
|
||||||
{
|
{
|
||||||
|
|
@ -4345,7 +4339,7 @@ void G_LoadGameData(void)
|
||||||
if (M_CheckParm("-resetdata"))
|
if (M_CheckParm("-resetdata"))
|
||||||
{
|
{
|
||||||
// Don't load, but do save. (essentially, reset)
|
// Don't load, but do save. (essentially, reset)
|
||||||
gamedataloaded = true;
|
gamedata->loaded = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4353,7 +4347,7 @@ void G_LoadGameData(void)
|
||||||
if (!length)
|
if (!length)
|
||||||
{
|
{
|
||||||
// No gamedata. We can save a new one.
|
// No gamedata. We can save a new one.
|
||||||
gamedataloaded = true;
|
gamedata->loaded = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4372,8 +4366,8 @@ void G_LoadGameData(void)
|
||||||
I_Error("Game data is not for Ring Racers v2.0.\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);
|
gamedata->totalplaytime = READUINT32(save_p);
|
||||||
matchesplayed = READUINT32(save_p);
|
gamedata->matchesplayed = READUINT32(save_p);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Quick & dirty hash for what mod this save file is for.
|
// Quick & dirty hash for what mod this save file is for.
|
||||||
|
|
@ -4392,32 +4386,32 @@ void G_LoadGameData(void)
|
||||||
{
|
{
|
||||||
rtemp = READUINT8(save_p);
|
rtemp = READUINT8(save_p);
|
||||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||||
emblemlocations[j+i].collected = ((rtemp >> j) & 1);
|
gamedata->collected[j+i] = ((rtemp >> j) & 1);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
||||||
{
|
{
|
||||||
rtemp = READUINT8(save_p);
|
rtemp = READUINT8(save_p);
|
||||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||||
extraemblems[j+i].collected = ((rtemp >> j) & 1);
|
gamedata->extraCollected[j+i] = ((rtemp >> j) & 1);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXUNLOCKABLES;)
|
for (i = 0; i < MAXUNLOCKABLES;)
|
||||||
{
|
{
|
||||||
rtemp = READUINT8(save_p);
|
rtemp = READUINT8(save_p);
|
||||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||||
unlockables[j+i].unlocked = ((rtemp >> j) & 1);
|
gamedata->unlocked[j+i] = ((rtemp >> j) & 1);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXCONDITIONSETS;)
|
for (i = 0; i < MAXCONDITIONSETS;)
|
||||||
{
|
{
|
||||||
rtemp = READUINT8(save_p);
|
rtemp = READUINT8(save_p);
|
||||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||||
conditionSets[j+i].achieved = ((rtemp >> j) & 1);
|
gamedata->achieved[j+i] = ((rtemp >> j) & 1);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
||||||
timesBeaten = READUINT32(save_p);
|
gamedata->timesBeaten = READUINT32(save_p);
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
numgamedatamapheaders = READUINT32(save_p);
|
numgamedatamapheaders = READUINT32(save_p);
|
||||||
|
|
@ -4469,10 +4463,10 @@ void G_LoadGameData(void)
|
||||||
// It used to do this much earlier, but this would cause the gamedata to
|
// 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,
|
// 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!
|
// which can accidentally delete players' legitimate data if the code ever has any tiny mistakes!
|
||||||
gamedataloaded = true;
|
gamedata->loaded = true;
|
||||||
|
|
||||||
// Silent update unlockables in case they're out of sync with conditions
|
// Silent update unlockables in case they're out of sync with conditions
|
||||||
M_SilentUpdateUnlockablesAndEmblems();
|
M_UpdateUnlockablesAndExtraEmblems(false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -4498,7 +4492,7 @@ void G_SaveGameData(void)
|
||||||
INT32 i, j;
|
INT32 i, j;
|
||||||
UINT8 btemp;
|
UINT8 btemp;
|
||||||
|
|
||||||
if (!gamedataloaded)
|
if (!gamedata->loaded)
|
||||||
return; // If never loaded (-nodata), don't save
|
return; // If never loaded (-nodata), don't save
|
||||||
|
|
||||||
if (usedCheats)
|
if (usedCheats)
|
||||||
|
|
@ -4522,8 +4516,8 @@ void G_SaveGameData(void)
|
||||||
// Version test
|
// Version test
|
||||||
|
|
||||||
WRITEUINT32(save_p, GD_VERSIONCHECK); // 4
|
WRITEUINT32(save_p, GD_VERSIONCHECK); // 4
|
||||||
WRITEUINT32(save_p, totalplaytime); // 4
|
WRITEUINT32(save_p, gamedata->totalplaytime); // 4
|
||||||
WRITEUINT32(save_p, matchesplayed); // 4
|
WRITEUINT32(save_p, gamedata->matchesplayed); // 4
|
||||||
WRITEUINT32(save_p, quickncasehash(timeattackfolder, 64));
|
WRITEUINT32(save_p, quickncasehash(timeattackfolder, 64));
|
||||||
|
|
||||||
// To save space, use one bit per collected/achieved/unlocked flag
|
// To save space, use one bit per collected/achieved/unlocked flag
|
||||||
|
|
@ -4531,7 +4525,7 @@ void G_SaveGameData(void)
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||||
btemp |= (emblemlocations[j+i].collected << j);
|
btemp |= (gamedata->collected[j+i] << j);
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
@ -4539,7 +4533,7 @@ void G_SaveGameData(void)
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||||
btemp |= (extraemblems[j+i].collected << j);
|
btemp |= (gamedata->extraCollected[j+i] << j);
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
@ -4547,7 +4541,7 @@ void G_SaveGameData(void)
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||||
btemp |= (unlockables[j+i].unlocked << j);
|
btemp |= (gamedata->unlocked[j+i] << j);
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
@ -4555,12 +4549,12 @@ void G_SaveGameData(void)
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||||
btemp |= (conditionSets[j+i].achieved << j);
|
btemp |= (gamedata->achieved[j+i] << j);
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITEUINT32(save_p, timesBeaten); // 4
|
WRITEUINT32(save_p, gamedata->timesBeaten); // 4
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
WRITEUINT32(save_p, nummapheaders); // 4
|
WRITEUINT32(save_p, nummapheaders); // 4
|
||||||
|
|
|
||||||
|
|
@ -1494,7 +1494,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
|
||||||
static boolean canplaysound = true;
|
static boolean canplaysound = true;
|
||||||
tic_t timetoreach = emblem->var;
|
tic_t timetoreach = emblem->var;
|
||||||
|
|
||||||
if (emblem->collected)
|
if (gamedata->collected[(emblem-emblemlocations)])
|
||||||
{
|
{
|
||||||
emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE);
|
emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE);
|
||||||
emblemcol[curemb] = R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE);
|
emblemcol[curemb] = R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE);
|
||||||
|
|
|
||||||
|
|
@ -1908,7 +1908,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup)
|
||||||
|
|
||||||
V_DrawFill(0, y, BASEVIDWIDTH, 54, 31);
|
V_DrawFill(0, y, BASEVIDWIDTH, 54, 31);
|
||||||
|
|
||||||
if (cup && (cup->unlockrequired == -1 || unlockables[cup->unlockrequired].unlocked))
|
if (cup && (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired]))
|
||||||
{
|
{
|
||||||
i = (cupgrid.previewanim / 82) % cup->numlevels;
|
i = (cupgrid.previewanim / 82) % cup->numlevels;
|
||||||
while (x < BASEVIDWIDTH + pad)
|
while (x < BASEVIDWIDTH + pad)
|
||||||
|
|
@ -1946,7 +1946,7 @@ static void M_DrawCupTitle(INT16 y, cupheader_t *cup)
|
||||||
|
|
||||||
if (cup)
|
if (cup)
|
||||||
{
|
{
|
||||||
boolean unlocked = (cup->unlockrequired == -1 || unlockables[cup->unlockrequired].unlocked);
|
boolean unlocked = (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired]);
|
||||||
UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE);
|
UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE);
|
||||||
patch_t *icon = W_CachePatchName(cup->icon, PU_CACHE);
|
patch_t *icon = W_CachePatchName(cup->icon, PU_CACHE);
|
||||||
const char *str = (unlocked ? va("%s Cup", cup->name) : "???");
|
const char *str = (unlocked ? va("%s Cup", cup->name) : "???");
|
||||||
|
|
@ -2014,7 +2014,7 @@ void M_DrawCupSelect(void)
|
||||||
|
|
||||||
V_DrawScaledPatch(x, y, 0, patch);
|
V_DrawScaledPatch(x, y, 0, patch);
|
||||||
|
|
||||||
if (iconcup->unlockrequired != -1 && !unlockables[iconcup->unlockrequired].unlocked)
|
if (iconcup->unlockrequired != -1 && !gamedata->unlocked[iconcup->unlockrequired])
|
||||||
{
|
{
|
||||||
patch_t *st = W_CachePatchName(va("ICONST0%d", (cupgrid.previewanim % 4) + 1), PU_CACHE);
|
patch_t *st = W_CachePatchName(va("ICONST0%d", (cupgrid.previewanim % 4) + 1), PU_CACHE);
|
||||||
V_DrawScaledPatch(x + 8, y + icony, 0, st);
|
V_DrawScaledPatch(x + 8, y + icony, 0, st);
|
||||||
|
|
|
||||||
|
|
@ -343,8 +343,8 @@ static void M_EraseDataResponse(INT32 ch)
|
||||||
if (optionsmenu.erasecontext == 2)
|
if (optionsmenu.erasecontext == 2)
|
||||||
{
|
{
|
||||||
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
|
// SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches secrets
|
||||||
totalplaytime = 0;
|
gamedata->totalplaytime = 0;
|
||||||
matchesplayed = 0;
|
gamedata->matchesplayed = 0;
|
||||||
}
|
}
|
||||||
if (optionsmenu.erasecontext != 1)
|
if (optionsmenu.erasecontext != 1)
|
||||||
G_ClearRecords();
|
G_ClearRecords();
|
||||||
|
|
@ -3441,7 +3441,7 @@ static void M_LevelListFromGametype(INT16 gt)
|
||||||
|
|
||||||
while (cup)
|
while (cup)
|
||||||
{
|
{
|
||||||
if (cup->unlockrequired == -1 || unlockables[cup->unlockrequired].unlocked)
|
if (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired])
|
||||||
{
|
{
|
||||||
highestid = cup->id;
|
highestid = cup->id;
|
||||||
if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup)
|
if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup)
|
||||||
|
|
@ -3575,7 +3575,7 @@ void M_CupSelectHandler(INT32 choice)
|
||||||
M_SetMenuDelay(pid);
|
M_SetMenuDelay(pid);
|
||||||
|
|
||||||
if ((!newcup)
|
if ((!newcup)
|
||||||
|| (newcup && newcup->unlockrequired != -1 && !unlockables[newcup->unlockrequired].unlocked)
|
|| (newcup && newcup->unlockrequired != -1 && !gamedata->unlocked[newcup->unlockrequired])
|
||||||
|| (newcup->cachedlevels[0] == NEXTMAP_INVALID))
|
|| (newcup->cachedlevels[0] == NEXTMAP_INVALID))
|
||||||
{
|
{
|
||||||
S_StartSound(NULL, sfx_s3kb2);
|
S_StartSound(NULL, sfx_s3kb2);
|
||||||
|
|
|
||||||
|
|
@ -418,7 +418,7 @@ void K_CashInPowerLevels(void)
|
||||||
{
|
{
|
||||||
pr->powerlevels[powerType] = clientpowerlevels[i][powerType];
|
pr->powerlevels[powerType] = clientpowerlevels[i][powerType];
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
{
|
{
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
}
|
}
|
||||||
|
|
@ -642,7 +642,7 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
|
||||||
{
|
{
|
||||||
pr->powerlevels[powerType] = yourPower + inc;
|
pr->powerlevels[powerType] = yourPower + inc;
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
{
|
{
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,16 +76,16 @@ static UINT8 cheatf_warp(void)
|
||||||
{
|
{
|
||||||
if (!unlockables[i].conditionset)
|
if (!unlockables[i].conditionset)
|
||||||
continue;
|
continue;
|
||||||
if (!unlockables[i].unlocked)
|
if (!gamedata->unlocked[i])
|
||||||
{
|
{
|
||||||
unlockables[i].unlocked = true;
|
gamedata->unlocked[i] = true;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
G_SaveGameData(); //G_SetUsedCheats();
|
G_SetUsedCheats();
|
||||||
S_StartSound(0, sfx_kc42);
|
S_StartSound(0, sfx_kc42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ static UINT8 cheatf_devmode(void)
|
||||||
// Just unlock all the things and turn on -debug and console devmode.
|
// Just unlock all the things and turn on -debug and console devmode.
|
||||||
G_SetUsedCheats();
|
G_SetUsedCheats();
|
||||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||||
unlockables[i].unlocked = true;
|
gamedata->unlocked[i] = true;
|
||||||
devparm = true;
|
devparm = true;
|
||||||
cht_debug |= 0x8000;
|
cht_debug |= 0x8000;
|
||||||
|
|
||||||
|
|
|
||||||
160
src/m_cond.c
160
src/m_cond.c
|
|
@ -24,6 +24,8 @@
|
||||||
#include "k_pwrlv.h"
|
#include "k_pwrlv.h"
|
||||||
#include "k_profiles.h"
|
#include "k_profiles.h"
|
||||||
|
|
||||||
|
gamedata_t *gamedata = NULL;
|
||||||
|
|
||||||
// Map triggers for linedef executors
|
// Map triggers for linedef executors
|
||||||
// 32 triggers, one bit each
|
// 32 triggers, one bit each
|
||||||
UINT32 unlocktriggers;
|
UINT32 unlocktriggers;
|
||||||
|
|
@ -44,6 +46,14 @@ unlockable_t unlockables[MAXUNLOCKABLES];
|
||||||
INT32 numemblems = 0;
|
INT32 numemblems = 0;
|
||||||
INT32 numextraemblems = 0;
|
INT32 numextraemblems = 0;
|
||||||
|
|
||||||
|
// Create a new gamedata_t, for start-up
|
||||||
|
void M_NewGameDataStruct(void)
|
||||||
|
{
|
||||||
|
gamedata = Z_Calloc(sizeof (gamedata_t), PU_STATIC, NULL);
|
||||||
|
M_ClearSecrets();
|
||||||
|
G_ClearRecords();
|
||||||
|
}
|
||||||
|
|
||||||
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)
|
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)
|
||||||
{
|
{
|
||||||
condition_t *cond;
|
condition_t *cond;
|
||||||
|
|
@ -73,7 +83,7 @@ void M_ClearConditionSet(UINT8 set)
|
||||||
conditionSets[set - 1].condition = NULL;
|
conditionSets[set - 1].condition = NULL;
|
||||||
conditionSets[set - 1].numconditions = 0;
|
conditionSets[set - 1].numconditions = 0;
|
||||||
}
|
}
|
||||||
conditionSets[set - 1].achieved = false;
|
gamedata->achieved[set - 1] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear ALL secrets.
|
// Clear ALL secrets.
|
||||||
|
|
@ -87,18 +97,18 @@ void M_ClearSecrets(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAXEMBLEMS; ++i)
|
for (i = 0; i < MAXEMBLEMS; ++i)
|
||||||
emblemlocations[i].collected = false;
|
gamedata->collected[i] = false;
|
||||||
for (i = 0; i < MAXEXTRAEMBLEMS; ++i)
|
for (i = 0; i < MAXEXTRAEMBLEMS; ++i)
|
||||||
extraemblems[i].collected = false;
|
gamedata->extraCollected[i] = false;
|
||||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||||
unlockables[i].unlocked = false;
|
gamedata->unlocked[i] = false;
|
||||||
for (i = 0; i < MAXCONDITIONSETS; ++i)
|
for (i = 0; i < MAXCONDITIONSETS; ++i)
|
||||||
conditionSets[i].achieved = false;
|
gamedata->achieved[i] = false;
|
||||||
|
|
||||||
timesBeaten = 0;
|
gamedata->timesBeaten = 0;
|
||||||
|
|
||||||
// Re-unlock any always unlocked things
|
// Re-unlock any always unlocked things
|
||||||
M_SilentUpdateUnlockablesAndEmblems();
|
M_UpdateUnlockablesAndExtraEmblems(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------
|
// ----------------------
|
||||||
|
|
@ -109,9 +119,9 @@ UINT8 M_CheckCondition(condition_t *cn)
|
||||||
switch (cn->type)
|
switch (cn->type)
|
||||||
{
|
{
|
||||||
case UC_PLAYTIME: // Requires total playing time >= x
|
case UC_PLAYTIME: // Requires total playing time >= x
|
||||||
return (totalplaytime >= (unsigned)cn->requirement);
|
return (gamedata->totalplaytime >= (unsigned)cn->requirement);
|
||||||
case UC_MATCHESPLAYED: // Requires any level completed >= x times
|
case UC_MATCHESPLAYED: // Requires any level completed >= x times
|
||||||
return (matchesplayed >= (unsigned)cn->requirement);
|
return (gamedata->matchesplayed >= (unsigned)cn->requirement);
|
||||||
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
|
case UC_POWERLEVEL: // Requires power level >= x on a certain gametype
|
||||||
{
|
{
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
@ -128,7 +138,7 @@ UINT8 M_CheckCondition(condition_t *cn)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case UC_GAMECLEAR: // Requires game beaten >= x times
|
case UC_GAMECLEAR: // Requires game beaten >= x times
|
||||||
return (timesBeaten >= (unsigned)cn->requirement);
|
return (gamedata->timesBeaten >= (unsigned)cn->requirement);
|
||||||
case UC_OVERALLTIME: // Requires overall time <= x
|
case UC_OVERALLTIME: // Requires overall time <= x
|
||||||
return (M_GotLowEnoughTime(cn->requirement));
|
return (M_GotLowEnoughTime(cn->requirement));
|
||||||
case UC_MAPVISITED: // Requires map x to be visited
|
case UC_MAPVISITED: // Requires map x to be visited
|
||||||
|
|
@ -152,9 +162,9 @@ UINT8 M_CheckCondition(condition_t *cn)
|
||||||
case UC_TOTALEMBLEMS: // Requires number of emblems >= x
|
case UC_TOTALEMBLEMS: // Requires number of emblems >= x
|
||||||
return (M_GotEnoughEmblems(cn->requirement));
|
return (M_GotEnoughEmblems(cn->requirement));
|
||||||
case UC_EMBLEM: // Requires emblem x to be obtained
|
case UC_EMBLEM: // Requires emblem x to be obtained
|
||||||
return emblemlocations[cn->requirement-1].collected;
|
return gamedata->collected[cn->requirement-1];
|
||||||
case UC_EXTRAEMBLEM: // Requires extra emblem x to be obtained
|
case UC_EXTRAEMBLEM: // Requires extra emblem x to be obtained
|
||||||
return extraemblems[cn->requirement-1].collected;
|
return gamedata->extraCollected[cn->requirement-1];
|
||||||
case UC_CONDITIONSET: // requires condition set x to already be achieved
|
case UC_CONDITIONSET: // requires condition set x to already be achieved
|
||||||
return M_Achieved(cn->requirement-1);
|
return M_Achieved(cn->requirement-1);
|
||||||
}
|
}
|
||||||
|
|
@ -196,14 +206,14 @@ void M_CheckUnlockConditions(void)
|
||||||
for (i = 0; i < MAXCONDITIONSETS; ++i)
|
for (i = 0; i < MAXCONDITIONSETS; ++i)
|
||||||
{
|
{
|
||||||
c = &conditionSets[i];
|
c = &conditionSets[i];
|
||||||
if (!c->numconditions || c->achieved)
|
if (!c->numconditions || gamedata->achieved[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c->achieved = (M_CheckConditionSet(c));
|
gamedata->achieved[i] = (M_CheckConditionSet(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 M_UpdateUnlockablesAndExtraEmblems(void)
|
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
char cechoText[992] = "";
|
char cechoText[992] = "";
|
||||||
|
|
@ -211,16 +221,31 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void)
|
||||||
|
|
||||||
M_CheckUnlockConditions();
|
M_CheckUnlockConditions();
|
||||||
|
|
||||||
|
if (!loud)
|
||||||
|
{
|
||||||
|
// Just in case they aren't to sync
|
||||||
|
M_CheckLevelEmblems();
|
||||||
|
M_CompletionEmblems();
|
||||||
|
}
|
||||||
|
|
||||||
// Go through extra emblems
|
// Go through extra emblems
|
||||||
for (i = 0; i < numextraemblems; ++i)
|
for (i = 0; i < numextraemblems; ++i)
|
||||||
{
|
{
|
||||||
if (extraemblems[i].collected || !extraemblems[i].conditionset)
|
if (gamedata->extraCollected[i] || !extraemblems[i].conditionset)
|
||||||
continue;
|
|
||||||
if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false)
|
|
||||||
{
|
{
|
||||||
strcat(cechoText, va(M_GetText("Got \"%s\" medal!\\"), extraemblems[i].name));
|
continue;
|
||||||
++cechoLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((gamedata->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1)) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loud)
|
||||||
|
{
|
||||||
|
strcat(cechoText, va("Got \"%s\" medal!\n", extraemblems[i].name));
|
||||||
|
}
|
||||||
|
++cechoLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fun part: if any of those unlocked we need to go through the
|
// Fun part: if any of those unlocked we need to go through the
|
||||||
|
|
@ -231,67 +256,40 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void)
|
||||||
// Go through unlockables
|
// Go through unlockables
|
||||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||||
{
|
{
|
||||||
if (unlockables[i].unlocked || !unlockables[i].conditionset)
|
if (gamedata->unlocked[i] || !unlockables[i].conditionset)
|
||||||
continue;
|
|
||||||
if ((unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1)) != false)
|
|
||||||
{
|
{
|
||||||
if (unlockables[i].nocecho)
|
continue;
|
||||||
continue;
|
|
||||||
strcat(cechoText, va(M_GetText("\"%s\" unlocked!\\"), unlockables[i].name));
|
|
||||||
++cechoLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((gamedata->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1)) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlockables[i].nocecho)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loud)
|
||||||
|
{
|
||||||
|
strcat(cechoText, va("\"%s\" unlocked!\n", unlockables[i].name));
|
||||||
|
}
|
||||||
|
++cechoLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce
|
// Announce
|
||||||
if (cechoLines)
|
if (cechoLines && loud)
|
||||||
{
|
{
|
||||||
char slashed[1024] = "";
|
#ifdef DEVELOP
|
||||||
for (i = 0; (i < 19) && (i < 24 - cechoLines); ++i)
|
// todo make debugmode
|
||||||
slashed[i] = '\\';
|
CONS_Printf("%s\n", cechoText);
|
||||||
slashed[i] = 0;
|
#endif
|
||||||
|
|
||||||
strcat(slashed, cechoText);
|
|
||||||
|
|
||||||
HU_SetCEchoFlags(V_YELLOWMAP);
|
|
||||||
HU_SetCEchoDuration(6);
|
|
||||||
HU_DoCEcho(slashed);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used when loading gamedata to make sure all unlocks are synched with conditions
|
|
||||||
void M_SilentUpdateUnlockablesAndEmblems(void)
|
|
||||||
{
|
|
||||||
INT32 i;
|
|
||||||
boolean checkAgain = false;
|
|
||||||
|
|
||||||
// Just in case they aren't to sync
|
|
||||||
M_CheckUnlockConditions();
|
|
||||||
M_CheckLevelEmblems();
|
|
||||||
|
|
||||||
// Go through extra emblems
|
|
||||||
for (i = 0; i < numextraemblems; ++i)
|
|
||||||
{
|
|
||||||
if (extraemblems[i].collected || !extraemblems[i].conditionset)
|
|
||||||
continue;
|
|
||||||
if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false)
|
|
||||||
checkAgain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check again if extra emblems unlocked, blah blah, etc
|
|
||||||
if (checkAgain)
|
|
||||||
M_CheckUnlockConditions();
|
|
||||||
|
|
||||||
// Go through unlockables
|
|
||||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
|
||||||
{
|
|
||||||
if (unlockables[i].unlocked || !unlockables[i].conditionset)
|
|
||||||
continue;
|
|
||||||
unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emblem unlocking shit
|
// Emblem unlocking shit
|
||||||
UINT8 M_CheckLevelEmblems(void)
|
UINT8 M_CheckLevelEmblems(void)
|
||||||
{
|
{
|
||||||
|
|
@ -306,7 +304,7 @@ UINT8 M_CheckLevelEmblems(void)
|
||||||
{
|
{
|
||||||
INT32 checkLevel;
|
INT32 checkLevel;
|
||||||
|
|
||||||
if (emblemlocations[i].type < ET_TIME || emblemlocations[i].collected)
|
if (emblemlocations[i].type < ET_TIME || gamedata->collected[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
checkLevel = G_MapNumber(emblemlocations[i].level);
|
checkLevel = G_MapNumber(emblemlocations[i].level);
|
||||||
|
|
@ -326,7 +324,7 @@ UINT8 M_CheckLevelEmblems(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
emblemlocations[i].collected = res;
|
gamedata->collected[i] = res;
|
||||||
if (res)
|
if (res)
|
||||||
++somethingUnlocked;
|
++somethingUnlocked;
|
||||||
}
|
}
|
||||||
|
|
@ -346,7 +344,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
|
||||||
{
|
{
|
||||||
INT32 checkLevel;
|
INT32 checkLevel;
|
||||||
|
|
||||||
if (emblemlocations[i].type < ET_TIME || emblemlocations[i].collected)
|
if (emblemlocations[i].type < ET_TIME || gamedata->collected[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
checkLevel = G_MapNumber(emblemlocations[i].level);
|
checkLevel = G_MapNumber(emblemlocations[i].level);
|
||||||
|
|
@ -363,7 +361,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
|
||||||
|
|
||||||
res = ((mapheaderinfo[levelnum]->mapvisited & flags) == flags);
|
res = ((mapheaderinfo[levelnum]->mapvisited & flags) == flags);
|
||||||
|
|
||||||
emblemlocations[i].collected = res;
|
gamedata->collected[i] = res;
|
||||||
if (res)
|
if (res)
|
||||||
++somethingUnlocked;
|
++somethingUnlocked;
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +383,7 @@ UINT8 M_AnySecretUnlocked(void)
|
||||||
|
|
||||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||||
{
|
{
|
||||||
if (!unlockables[i].nocecho && unlockables[i].unlocked)
|
if (!unlockables[i].nocecho && gamedata->unlocked[i])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -412,7 +410,7 @@ UINT8 M_SecretUnlocked(INT32 type)
|
||||||
|
|
||||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||||
{
|
{
|
||||||
if (unlockables[i].type == type && unlockables[i].unlocked != CHADYES)
|
if (unlockables[i].type == type && gamedata->unlocked[i] != CHADYES)
|
||||||
return !CHADYES;
|
return !CHADYES;
|
||||||
}
|
}
|
||||||
return CHADYES;
|
return CHADYES;
|
||||||
|
|
@ -435,7 +433,7 @@ UINT8 M_MapLocked(INT32 mapnum)
|
||||||
if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0)
|
if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!unlockables[mapheaderinfo[mapnum-1]->unlockrequired].unlocked)
|
if (!gamedata->unlocked[mapheaderinfo[mapnum-1]->unlockrequired])
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -447,12 +445,12 @@ INT32 M_CountEmblems(void)
|
||||||
INT32 found = 0, i;
|
INT32 found = 0, i;
|
||||||
for (i = 0; i < numemblems; ++i)
|
for (i = 0; i < numemblems; ++i)
|
||||||
{
|
{
|
||||||
if (emblemlocations[i].collected)
|
if (gamedata->collected[i])
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < numextraemblems; ++i)
|
for (i = 0; i < numextraemblems; ++i)
|
||||||
{
|
{
|
||||||
if (extraemblems[i].collected)
|
if (gamedata->extraCollected[i])
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
|
|
@ -469,12 +467,12 @@ UINT8 M_GotEnoughEmblems(INT32 number)
|
||||||
INT32 i, gottenemblems = 0;
|
INT32 i, gottenemblems = 0;
|
||||||
for (i = 0; i < numemblems; ++i)
|
for (i = 0; i < numemblems; ++i)
|
||||||
{
|
{
|
||||||
if (emblemlocations[i].collected)
|
if (gamedata->collected[i])
|
||||||
if (++gottenemblems >= number) return true;
|
if (++gottenemblems >= number) return true;
|
||||||
}
|
}
|
||||||
for (i = 0; i < numextraemblems; ++i)
|
for (i = 0; i < numextraemblems; ++i)
|
||||||
{
|
{
|
||||||
if (extraemblems[i].collected)
|
if (gamedata->extraCollected[i])
|
||||||
if (++gottenemblems >= number) return true;
|
if (++gottenemblems >= number) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
41
src/m_cond.h
41
src/m_cond.h
|
|
@ -52,8 +52,6 @@ typedef struct
|
||||||
{
|
{
|
||||||
UINT32 numconditions; /// <- number of conditions.
|
UINT32 numconditions; /// <- number of conditions.
|
||||||
condition_t *condition; /// <- All conditionals to be checked.
|
condition_t *condition; /// <- All conditionals to be checked.
|
||||||
UINT8 achieved; /// <- Whether this conditional has been achieved already or not.
|
|
||||||
/// (Conditional checking is skipped if true -- it's assumed you can't relock an unlockable)
|
|
||||||
} conditionset_t;
|
} conditionset_t;
|
||||||
|
|
||||||
// Emblem information
|
// Emblem information
|
||||||
|
|
@ -79,7 +77,6 @@ typedef struct
|
||||||
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
|
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
|
||||||
char *stringVar; ///< String version
|
char *stringVar; ///< String version
|
||||||
char hint[110]; ///< Hint for emblem hints menu
|
char hint[110]; ///< Hint for emblem hints menu
|
||||||
UINT8 collected; ///< Do you have this emblem?
|
|
||||||
} emblem_t;
|
} emblem_t;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
@ -89,7 +86,6 @@ typedef struct
|
||||||
UINT8 showconditionset; ///< Condition set that shows this emblem.
|
UINT8 showconditionset; ///< Condition set that shows this emblem.
|
||||||
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
||||||
UINT16 color; ///< skincolor to use
|
UINT16 color; ///< skincolor to use
|
||||||
UINT8 collected; ///< Do you have this emblem?
|
|
||||||
} extraemblem_t;
|
} extraemblem_t;
|
||||||
|
|
||||||
// Unlockable information
|
// Unlockable information
|
||||||
|
|
@ -104,7 +100,6 @@ typedef struct
|
||||||
char *stringVar;
|
char *stringVar;
|
||||||
UINT8 nocecho;
|
UINT8 nocecho;
|
||||||
UINT8 nochecklist;
|
UINT8 nochecklist;
|
||||||
UINT8 unlocked;
|
|
||||||
} unlockable_t;
|
} unlockable_t;
|
||||||
|
|
||||||
#define SECRET_NONE 0 // Does nil. Use with levels locked by UnlockRequired
|
#define SECRET_NONE 0 // Does nil. Use with levels locked by UnlockRequired
|
||||||
|
|
@ -135,6 +130,35 @@ typedef struct
|
||||||
#define MAXEXTRAEMBLEMS 16
|
#define MAXEXTRAEMBLEMS 16
|
||||||
#define MAXUNLOCKABLES 32
|
#define MAXUNLOCKABLES 32
|
||||||
|
|
||||||
|
// GAMEDATA STRUCTURE
|
||||||
|
// Everything that would get saved in gamedata.dat
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// WHENEVER OR NOT WE'RE READY TO SAVE
|
||||||
|
boolean loaded;
|
||||||
|
|
||||||
|
// CONDITION SETS ACHIEVED
|
||||||
|
boolean achieved[MAXCONDITIONSETS];
|
||||||
|
|
||||||
|
// EMBLEMS COLLECTED
|
||||||
|
boolean collected[MAXEMBLEMS];
|
||||||
|
|
||||||
|
// EXTRA EMBLEMS COLLECTED
|
||||||
|
boolean extraCollected[MAXEXTRAEMBLEMS];
|
||||||
|
|
||||||
|
// UNLOCKABLES UNLOCKED
|
||||||
|
boolean unlocked[MAXUNLOCKABLES];
|
||||||
|
|
||||||
|
// # OF TIMES THE GAME HAS BEEN BEATEN
|
||||||
|
UINT32 timesBeaten;
|
||||||
|
|
||||||
|
// PLAY TIME
|
||||||
|
UINT32 totalplaytime;
|
||||||
|
UINT32 matchesplayed;
|
||||||
|
} gamedata_t;
|
||||||
|
|
||||||
|
extern gamedata_t *gamedata;
|
||||||
|
|
||||||
extern conditionset_t conditionSets[MAXCONDITIONSETS];
|
extern conditionset_t conditionSets[MAXCONDITIONSETS];
|
||||||
extern emblem_t emblemlocations[MAXEMBLEMS];
|
extern emblem_t emblemlocations[MAXEMBLEMS];
|
||||||
extern extraemblem_t extraemblems[MAXEXTRAEMBLEMS];
|
extern extraemblem_t extraemblems[MAXEXTRAEMBLEMS];
|
||||||
|
|
@ -145,6 +169,8 @@ extern INT32 numextraemblems;
|
||||||
|
|
||||||
extern UINT32 unlocktriggers;
|
extern UINT32 unlocktriggers;
|
||||||
|
|
||||||
|
void M_NewGameDataStruct(void);
|
||||||
|
|
||||||
// Condition set setup
|
// Condition set setup
|
||||||
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2);
|
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2);
|
||||||
|
|
||||||
|
|
@ -155,8 +181,7 @@ void M_ClearSecrets(void);
|
||||||
// Updating conditions and unlockables
|
// Updating conditions and unlockables
|
||||||
void M_CheckUnlockConditions(void);
|
void M_CheckUnlockConditions(void);
|
||||||
UINT8 M_CheckCondition(condition_t *cn);
|
UINT8 M_CheckCondition(condition_t *cn);
|
||||||
UINT8 M_UpdateUnlockablesAndExtraEmblems(void);
|
boolean M_UpdateUnlockablesAndExtraEmblems(boolean silent);
|
||||||
void M_SilentUpdateUnlockablesAndEmblems(void);
|
|
||||||
UINT8 M_CheckLevelEmblems(void);
|
UINT8 M_CheckLevelEmblems(void);
|
||||||
UINT8 M_CompletionEmblems(void);
|
UINT8 M_CompletionEmblems(void);
|
||||||
|
|
||||||
|
|
@ -182,4 +207,4 @@ UINT8 M_GotLowEnoughTime(INT32 tictime);
|
||||||
INT32 M_UnlockableSkinNum(unlockable_t *unlock);
|
INT32 M_UnlockableSkinNum(unlockable_t *unlock);
|
||||||
INT32 M_EmblemSkinNum(emblem_t *emblem);
|
INT32 M_EmblemSkinNum(emblem_t *emblem);
|
||||||
|
|
||||||
#define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved)
|
#define M_Achieved(a) ((a) >= MAXCONDITIONSETS || gamedata->achieved[a])
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
#include "doomstat.h" // totalplaytime
|
#include "m_cond.h" // gamedata->totalplaytime
|
||||||
|
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "m_fixed.h"
|
#include "m_fixed.h"
|
||||||
|
|
@ -372,5 +372,5 @@ void P_ClearRandom(UINT32 seed)
|
||||||
*/
|
*/
|
||||||
UINT32 M_RandomizedSeed(void)
|
UINT32 M_RandomizedSeed(void)
|
||||||
{
|
{
|
||||||
return ((totalplaytime & 0xFFFF) << 16) | M_RandomFixed();
|
return ((gamedata->totalplaytime & 0xFFFF) << 16) | M_RandomFixed();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -504,8 +504,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
||||||
if (demo.playback || special->health > MAXEMBLEMS)
|
if (demo.playback || special->health > MAXEMBLEMS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
emblemlocations[special->health-1].collected = true;
|
gamedata->collected[special->health-1] = true;
|
||||||
M_UpdateUnlockablesAndExtraEmblems();
|
M_UpdateUnlockablesAndExtraEmblems(true);
|
||||||
G_SaveGameData();
|
G_SaveGameData();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11969,7 +11969,7 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj)
|
||||||
emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
|
emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting
|
||||||
mobj->color = (UINT16)emcolor;
|
mobj->color = (UINT16)emcolor;
|
||||||
|
|
||||||
if (emblemlocations[j].collected)
|
if (gamedata->collected[j])
|
||||||
{
|
{
|
||||||
P_UnsetThingPosition(mobj);
|
P_UnsetThingPosition(mobj);
|
||||||
mobj->flags |= MF_NOCLIP;
|
mobj->flags |= MF_NOCLIP;
|
||||||
|
|
|
||||||
|
|
@ -7567,7 +7567,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||||
{
|
{
|
||||||
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
|
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
|
||||||
|
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
S_StartSound(NULL, sfx_ncitem);
|
S_StartSound(NULL, sfx_ncitem);
|
||||||
G_SaveGameData();
|
G_SaveGameData();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1502,7 +1502,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
||||||
CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid);
|
CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!(unlockables[unlockid].unlocked))
|
else if (!(gamedata->unlocked[unlockid]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2763,7 +2763,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
||||||
unlocktriggers |= 1 << trigid;
|
unlocktriggers |= 1 << trigid;
|
||||||
|
|
||||||
// Unlocked something?
|
// Unlocked something?
|
||||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
if (M_UpdateUnlockablesAndExtraEmblems(true))
|
||||||
{
|
{
|
||||||
S_StartSound(NULL, sfx_s3k68);
|
S_StartSound(NULL, sfx_s3k68);
|
||||||
G_SaveGameData(); // only save if unlocked something
|
G_SaveGameData(); // only save if unlocked something
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "st_stuff.h"
|
#include "st_stuff.h"
|
||||||
#include "p_polyobj.h"
|
#include "p_polyobj.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
|
#include "m_cond.h" // gamedata->playtime
|
||||||
#include "lua_script.h"
|
#include "lua_script.h"
|
||||||
#include "lua_hook.h"
|
#include "lua_hook.h"
|
||||||
#include "m_perfstats.h"
|
#include "m_perfstats.h"
|
||||||
|
|
@ -628,7 +629,7 @@ void P_Ticker(boolean run)
|
||||||
|
|
||||||
// Keep track of how long they've been playing!
|
// Keep track of how long they've been playing!
|
||||||
if (!demo.playback) // Don't increment if a demo is playing.
|
if (!demo.playback) // Don't increment if a demo is playing.
|
||||||
totalplaytime++;
|
gamedata->totalplaytime++;
|
||||||
|
|
||||||
// formality so kitemcap gets updated properly each frame.
|
// formality so kitemcap gets updated properly each frame.
|
||||||
P_RunKartItems();
|
P_RunKartItems();
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ UINT8 *R_GetSkinAvailabilities(boolean demolock)
|
||||||
if (unlockables[i].type != SECRET_SKIN)
|
if (unlockables[i].type != SECRET_SKIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (unlockables[i].unlocked != true && !demolock)
|
if (gamedata->unlocked[i] != true && !demolock)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
skinid = M_UnlockableSkinNum(&unlockables[i]);
|
skinid = M_UnlockableSkinNum(&unlockables[i]);
|
||||||
|
|
@ -250,7 +250,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the unlockables table directly
|
// Use the unlockables table directly
|
||||||
return (boolean)(unlockables[i].unlocked);
|
return (boolean)(gamedata->unlocked[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the skin name is found (loaded from pwad)
|
// returns true if the skin name is found (loaded from pwad)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue