mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Sealed Star re-ordering (resolves #606)
- If emerald not yet collected on that cup, pick the first uncollected emerald, then get the cup's CUPCACHE_SPECIAL with that ID to pick the stage - Already collected emeralds retain their swappage across gamedata saves - Returns to normal order if you get all 7 OR Special Mode is unlocked (chao key? debug? password in modded games? sky's the limit) - Pops up a Message from the Stars telling you the gems have been returned to their natural place - Add-ons will always use their dedicated sealed star, since it's unordered material If it weren't so last minute I could have a better solution for GP Backups, but right now what I've gone for is it always trusts whatever G_GPCupIntoRoundQueue does AS LONG AS THE COURSE ISN'T THE ONE YOU'RE RELOADING INTO. If it IS, then it checks to see if it's exactly what's been saved, and complains (with the generic error message, unfortunately) if it isn't.
This commit is contained in:
parent
b00255e333
commit
e8523b69f0
13 changed files with 333 additions and 43 deletions
69
src/g_game.c
69
src/g_game.c
|
|
@ -3932,15 +3932,68 @@ void G_GPCupIntoRoundQueue(cupheader_t *cup, UINT8 setgametype, boolean setencor
|
|||
// At the end of the Cup is a Rank-restricted treat.
|
||||
// So we append it to the end of the roundqueue.
|
||||
// (as long as it exists, of course!)
|
||||
cupLevelNum = cup->cachedlevels[CUPCACHE_SPECIAL];
|
||||
if (cupLevelNum < nummapheaders)
|
||||
{
|
||||
G_MapIntoRoundQueue(
|
||||
cupLevelNum,
|
||||
G_GuessGametypeByTOL(mapheaderinfo[cupLevelNum]->typeoflevel),
|
||||
setencore, // if this isn't correct, Got_Mapcmd will fix it
|
||||
true // Rank-restricted!
|
||||
);
|
||||
// Of course, this last minute game design tweak
|
||||
// has to make things a little complicated. We
|
||||
// basically just make sure they're dispensed
|
||||
// at the intended difficulty sequence until
|
||||
// you've got them all, at which point they
|
||||
// become their intended order permanently.
|
||||
// ~toast 010324
|
||||
cupheader_t *emeraldcup = NULL;
|
||||
|
||||
if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found
|
||||
|| cup->id >= basenumkartcupheaders // custom content
|
||||
|| M_SecretUnlocked(SECRET_SPECIALATTACK, false)) // true order
|
||||
{
|
||||
// Standard order.
|
||||
emeraldcup = cup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine order from sealedswaps.
|
||||
for (i = 0; (i < GDMAX_SEALEDSWAPS && gamedata->sealedswaps[i]); i++)
|
||||
{
|
||||
if (gamedata->sealedswaps[i] != grandprixinfo.cup)
|
||||
continue;
|
||||
|
||||
// Repeat visit, grab the same ID.
|
||||
break;
|
||||
}
|
||||
|
||||
// If there's pending stars, get them from the associated cup order.
|
||||
if (i < GDMAX_SEALEDSWAPS)
|
||||
{
|
||||
emeraldcup = kartcupheaders;
|
||||
while (emeraldcup)
|
||||
{
|
||||
if (emeraldcup->id >= basenumkartcupheaders)
|
||||
{
|
||||
emeraldcup = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (emeraldcup->emeraldnum == i+1)
|
||||
break;
|
||||
|
||||
emeraldcup = emeraldcup->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (emeraldcup)
|
||||
{
|
||||
cupLevelNum = emeraldcup->cachedlevels[CUPCACHE_SPECIAL];
|
||||
if (cupLevelNum < nummapheaders)
|
||||
{
|
||||
G_MapIntoRoundQueue(
|
||||
cupLevelNum,
|
||||
G_GuessGametypeByTOL(mapheaderinfo[cupLevelNum]->typeoflevel),
|
||||
setencore, // if this isn't correct, Got_Mapcmd will fix it
|
||||
true // Rank-restricted!
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (roundqueue.size == 0)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ void srb2::save_ng_gamedata()
|
|||
ng.milestones.majorkeyskipattempted = gamedata->majorkeyskipattempted;
|
||||
ng.milestones.finishedtutorialchallenge = gamedata->finishedtutorialchallenge;
|
||||
ng.milestones.enteredtutorialchallenge = gamedata->enteredtutorialchallenge;
|
||||
ng.milestones.sealedswapalerted = gamedata->sealedswapalerted;
|
||||
ng.milestones.gonerlevel = gamedata->gonerlevel;
|
||||
ng.prisons.thisprisoneggpickup = gamedata->thisprisoneggpickup;
|
||||
ng.prisons.prisoneggstothispickup = gamedata->prisoneggstothispickup;
|
||||
|
|
@ -176,7 +177,7 @@ void srb2::save_ng_gamedata()
|
|||
}
|
||||
for (auto cup = kartcupheaders; cup; cup = cup->next)
|
||||
{
|
||||
if (cup->windata[0].best_placement == 0)
|
||||
if (cup->windata[0].best_placement == 0 && cup->windata[1].got_emerald == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -229,6 +230,17 @@ void srb2::save_ng_gamedata()
|
|||
ng.cups[cupdata.name] = std::move(cupdata);
|
||||
}
|
||||
|
||||
for (int i = 0; (i < GDMAX_SEALEDSWAPS && gamedata->sealedswaps[i]); i++)
|
||||
{
|
||||
srb2::GamedataSealedSwapJson sealedswap {};
|
||||
|
||||
cupheader_t* cup = gamedata->sealedswaps[i];
|
||||
|
||||
sealedswap.name = std::string(cup->name);
|
||||
|
||||
ng.sealedswaps.emplace_back(std::move(sealedswap));
|
||||
}
|
||||
|
||||
std::string gamedataname_s {gamedatafilename};
|
||||
fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)};
|
||||
fs::path tmpsavepath {fmt::format("{}/{}.tmp", srb2home, gamedataname_s)};
|
||||
|
|
@ -418,6 +430,7 @@ void srb2::load_ng_gamedata()
|
|||
gamedata->majorkeyskipattempted = js.milestones.majorkeyskipattempted;
|
||||
gamedata->finishedtutorialchallenge = js.milestones.finishedtutorialchallenge;
|
||||
gamedata->enteredtutorialchallenge = js.milestones.enteredtutorialchallenge;
|
||||
gamedata->sealedswapalerted = js.milestones.sealedswapalerted;
|
||||
gamedata->gonerlevel = js.milestones.gonerlevel;
|
||||
gamedata->thisprisoneggpickup = js.prisons.thisprisoneggpickup;
|
||||
gamedata->prisoneggstothispickup = js.prisons.prisoneggstothispickup;
|
||||
|
|
@ -720,6 +733,33 @@ void srb2::load_ng_gamedata()
|
|||
}
|
||||
}
|
||||
|
||||
size_t sealedswaps_size = js.sealedswaps.size();
|
||||
for (size_t i = 0; i < std::min((size_t)GDMAX_SEALEDSWAPS, sealedswaps_size); i++)
|
||||
{
|
||||
cupheader_t* cup = nullptr;
|
||||
|
||||
// Find BASE cups only
|
||||
for (cup = kartcupheaders; cup; cup = cup->next)
|
||||
{
|
||||
if (cup->id >= basenumkartcupheaders)
|
||||
{
|
||||
cup = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
std::string cupname = std::string(cup->name);
|
||||
if (cupname == js.sealedswaps[i].name)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cup)
|
||||
{
|
||||
gamedata->sealedswaps[i] = cup;
|
||||
}
|
||||
}
|
||||
|
||||
M_FinaliseGameData();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ struct GamedataMilestonesJson final
|
|||
bool majorkeyskipattempted;
|
||||
bool finishedtutorialchallenge;
|
||||
bool enteredtutorialchallenge;
|
||||
bool sealedswapalerted;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataMilestonesJson,
|
||||
|
|
@ -81,7 +82,8 @@ struct GamedataMilestonesJson final
|
|||
chaokeytutorial,
|
||||
majorkeyskipattempted,
|
||||
finishedtutorialchallenge,
|
||||
enteredtutorialchallenge
|
||||
enteredtutorialchallenge,
|
||||
sealedswapalerted
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -184,6 +186,13 @@ struct GamedataCupJson final
|
|||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records)
|
||||
};
|
||||
|
||||
struct GamedataSealedSwapJson final
|
||||
{
|
||||
std::string name;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataSealedSwapJson, name)
|
||||
};
|
||||
|
||||
struct GamedataJson final
|
||||
{
|
||||
GamedataPlaytimeJson playtime;
|
||||
|
|
@ -203,6 +212,7 @@ struct GamedataJson final
|
|||
std::unordered_map<std::string, GamedataMapJson> maps;
|
||||
std::vector<GamedataSprayCanJson> spraycans;
|
||||
std::unordered_map<std::string, GamedataCupJson> cups;
|
||||
std::vector<GamedataSealedSwapJson> sealedswaps;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||
GamedataJson,
|
||||
|
|
@ -222,7 +232,8 @@ struct GamedataJson final
|
|||
skins,
|
||||
maps,
|
||||
spraycans,
|
||||
cups
|
||||
cups,
|
||||
sealedswaps
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -680,6 +680,8 @@ void M_Init(void);
|
|||
|
||||
void M_PlayMenuJam(void);
|
||||
|
||||
boolean M_ConsiderSealedSwapAlert(void);
|
||||
|
||||
void M_OpenVirtualKeyboard(boolean gamepad);
|
||||
void M_MenuTypingInput(INT32 key);
|
||||
|
||||
|
|
@ -1347,6 +1349,8 @@ extern struct challengesmenu_s {
|
|||
boolean chaokeyadd, keywasadded;
|
||||
UINT8 chaokeyhold;
|
||||
|
||||
boolean considersealedswapalert;
|
||||
|
||||
boolean requestflip;
|
||||
|
||||
UINT16 unlockcount[CMC_MAX];
|
||||
|
|
|
|||
|
|
@ -2823,6 +2823,57 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
|||
rankx += 19 - (rankw / 2);
|
||||
|
||||
cupwindata_t *windata = &(cup->windata[difficulty]);
|
||||
UINT8 emeraldnum = UINT8_MAX;
|
||||
|
||||
if (!noemerald)
|
||||
{
|
||||
if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found
|
||||
|| cup->id >= basenumkartcupheaders // custom content
|
||||
|| M_SecretUnlocked(SECRET_SPECIALATTACK, true)) // true order
|
||||
{
|
||||
// Standard order.
|
||||
if (windata->got_emerald == true)
|
||||
{
|
||||
emeraldnum = cup->emeraldnum;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine order from sealedswaps.
|
||||
UINT8 i;
|
||||
for (i = 0; (i < GDMAX_SEALEDSWAPS && gamedata->sealedswaps[i]); i++)
|
||||
{
|
||||
if (gamedata->sealedswaps[i] != cup)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// If there's pending stars, get them from the associated cup order.
|
||||
if (i < GDMAX_SEALEDSWAPS)
|
||||
{
|
||||
cupheader_t *emeraldcup = kartcupheaders;
|
||||
while (emeraldcup)
|
||||
{
|
||||
if (emeraldcup->id >= basenumkartcupheaders)
|
||||
{
|
||||
emeraldcup = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (emeraldcup->emeraldnum == i+1)
|
||||
{
|
||||
if (emeraldcup->windata[difficulty].got_emerald == true)
|
||||
emeraldnum = i+1;
|
||||
break;
|
||||
}
|
||||
|
||||
emeraldcup = emeraldcup->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (windata->best_placement == 0)
|
||||
{
|
||||
if (statsmode)
|
||||
|
|
@ -2832,14 +2883,13 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
|||
V_DrawCharacter((14-4)/2 + rankx, ranky, '.' | V_GRAYMAP, false);
|
||||
rankx += 14 + 1;
|
||||
V_DrawCharacter((12-4)/2 + rankx, ranky, '.' | V_GRAYMAP, false);
|
||||
|
||||
if (!noemerald)
|
||||
{
|
||||
rankx += 12 + 1;
|
||||
V_DrawCharacter((12-4)/2 + rankx, ranky, '.' | V_GRAYMAP, false);
|
||||
}
|
||||
}
|
||||
return rankw;
|
||||
else
|
||||
{
|
||||
rankx += 14 + 1;
|
||||
}
|
||||
|
||||
goto windataemeraldmaybe;
|
||||
}
|
||||
|
||||
UINT8 *colormap = NULL;
|
||||
|
|
@ -2934,13 +2984,15 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
|||
if (charPat)
|
||||
V_DrawFixedPatch((rankx)*FRACUNIT, (ranky)*FRACUNIT, FRACUNIT, 0, charPat, colormap);
|
||||
|
||||
windataemeraldmaybe:
|
||||
|
||||
rankx += 12 + 1;
|
||||
|
||||
if (noemerald)
|
||||
;
|
||||
else if (windata->got_emerald == true)
|
||||
else if (emeraldnum != UINT8_MAX)
|
||||
{
|
||||
if (cup->emeraldnum == 0)
|
||||
if (emeraldnum == 0)
|
||||
V_DrawCharacter(rankx+2, ranky+2, '+', false);
|
||||
else
|
||||
{
|
||||
|
|
@ -2948,14 +3000,14 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
|||
|
||||
if (!flash)
|
||||
{
|
||||
UINT16 col = SKINCOLOR_CHAOSEMERALD1 + (cup->emeraldnum-1) % 7;
|
||||
UINT16 col = SKINCOLOR_CHAOSEMERALD1 + (emeraldnum-1) % 7;
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
}
|
||||
|
||||
const char *emname = va(
|
||||
"%sMAP%c",
|
||||
(cup->emeraldnum > 7) ? "SUP" : "EME",
|
||||
(emeraldnum > 7) ? "SUP" : "EME",
|
||||
colormap ? '\0' : 'B'
|
||||
);
|
||||
|
||||
|
|
@ -3116,7 +3168,7 @@ void M_DrawCupSelect(void)
|
|||
y += 44; //(8 + 100) - (20 + 44)
|
||||
}
|
||||
|
||||
if (windata && windata->best_placement != 0)
|
||||
if (windata)
|
||||
{
|
||||
M_DrawCupWinData(
|
||||
x,
|
||||
|
|
|
|||
|
|
@ -560,6 +560,35 @@ void M_PlayMenuJam(void)
|
|||
|
||||
#undef IsCurrentlyPlaying
|
||||
|
||||
boolean M_ConsiderSealedSwapAlert(void)
|
||||
{
|
||||
if (gamedata->sealedswapalerted == true)
|
||||
return false;
|
||||
|
||||
if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found
|
||||
|| M_SecretUnlocked(SECRET_SPECIALATTACK, true)) // true order
|
||||
{
|
||||
gamedata->sealedswapalerted = true;
|
||||
|
||||
// Don't make a message if no Sealed Stars have yet been found.
|
||||
if (gamedata->everseenspecial == false)
|
||||
return false;
|
||||
|
||||
M_StartMessage(
|
||||
"Message from the Stars",
|
||||
"As if called by fate, the Emeralds you've\n"
|
||||
"collected return to their rightful places...\n"
|
||||
"\n"
|
||||
"The Sealed Stars are now ordered via Cups!\n",
|
||||
NULL, MM_NOTHING, NULL, NULL
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void M_ValidateRestoreMenu(void)
|
||||
{
|
||||
if (restoreMenu == NULL || restoreMenu == &MAIN_GonerDef)
|
||||
|
|
@ -629,6 +658,11 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore)
|
|||
M_SetupPlayMenu(-1);
|
||||
PLAY_CharSelectDef.prevMenu = &MainDef;
|
||||
|
||||
if (torestore != &MISC_ChallengesDef)
|
||||
{
|
||||
M_ConsiderSealedSwapAlert();
|
||||
}
|
||||
|
||||
return torestore;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ static struct podiumData_s
|
|||
sfxenum_t gradeVoice;
|
||||
|
||||
cupheader_t *cup;
|
||||
UINT8 emeraldnum;
|
||||
|
||||
boolean fastForward;
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ void podiumData_s::Init(void)
|
|||
{
|
||||
rank = grandprixinfo.rank;
|
||||
cup = grandprixinfo.cup;
|
||||
emeraldnum = cup->emeraldnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -119,6 +121,7 @@ void podiumData_s::Init(void)
|
|||
|
||||
cup = cup->next;
|
||||
}
|
||||
emeraldnum = 0;
|
||||
|
||||
memset(&rank, 0, sizeof(gpRank_t));
|
||||
rank.skin = players[consoleplayer].skin;
|
||||
|
|
@ -628,12 +631,7 @@ void podiumData_s::Draw(void)
|
|||
case GPEVENT_SPECIAL:
|
||||
{
|
||||
srb2::Draw drawer_emerald = drawer_gametype;
|
||||
UINT8 emeraldNum = 0;
|
||||
|
||||
if (cup != nullptr)
|
||||
{
|
||||
emeraldNum = cup->emeraldnum;
|
||||
}
|
||||
UINT8 emeraldNum = g_podiumData.emeraldnum;
|
||||
|
||||
boolean useWhiteFrame = ((leveltime & 1) || !dta->gotSpecialPrize);
|
||||
patch_t *emeraldPatch = nullptr;
|
||||
|
|
@ -844,12 +842,7 @@ void podiumData_s::Draw(void)
|
|||
|
||||
if (rank.specialWon == true)
|
||||
{
|
||||
UINT8 emeraldNum = 0;
|
||||
|
||||
if (cup != nullptr)
|
||||
{
|
||||
emeraldNum = cup->emeraldnum;
|
||||
}
|
||||
UINT8 emeraldNum = g_podiumData.emeraldnum;
|
||||
|
||||
const boolean emeraldBlink = (leveltime & 1);
|
||||
patch_t *emeraldOverlay = nullptr;
|
||||
|
|
@ -1263,6 +1256,60 @@ void K_ResetCeremony(void)
|
|||
return;
|
||||
}
|
||||
|
||||
cupheader_t *emeraldcup = NULL;
|
||||
|
||||
if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found
|
||||
|| grandprixinfo.cup->id >= basenumkartcupheaders // custom content
|
||||
|| M_SecretUnlocked(SECRET_SPECIALATTACK, false)) // true order
|
||||
{
|
||||
// Standard order.
|
||||
emeraldcup = grandprixinfo.cup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine order from sealedswaps.
|
||||
for (i = 0; i < GDMAX_SEALEDSWAPS; i++)
|
||||
{
|
||||
if (gamedata->sealedswaps[i] == NULL)
|
||||
{
|
||||
if (g_podiumData.rank.specialWon == true)
|
||||
{
|
||||
// First visit! Mark it off.
|
||||
gamedata->sealedswaps[i] = grandprixinfo.cup;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (gamedata->sealedswaps[i] != grandprixinfo.cup)
|
||||
continue;
|
||||
|
||||
// Repeat visit, grab the same ID.
|
||||
break;
|
||||
}
|
||||
|
||||
// If there's pending stars, apply them to the new cup order.
|
||||
if (i < GDMAX_SEALEDSWAPS)
|
||||
{
|
||||
emeraldcup = kartcupheaders;
|
||||
while (emeraldcup)
|
||||
{
|
||||
if (emeraldcup->id >= basenumkartcupheaders)
|
||||
{
|
||||
emeraldcup = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (emeraldcup->emeraldnum == i+1)
|
||||
break;
|
||||
|
||||
emeraldcup = emeraldcup->next;
|
||||
}
|
||||
|
||||
g_podiumData.emeraldnum = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
// Write grade, position, and emerald-having-ness for later sessions!
|
||||
i = (grandprixinfo.masterbots) ? KARTGP_MASTER : grandprixinfo.gamespeed;
|
||||
|
||||
|
|
@ -1292,9 +1339,9 @@ void K_ResetCeremony(void)
|
|||
anymerit = true;
|
||||
}
|
||||
|
||||
if (g_podiumData.rank.specialWon == true)
|
||||
if (g_podiumData.rank.specialWon == true && emeraldcup)
|
||||
{
|
||||
grandprixinfo.cup->windata[i].got_emerald = true;
|
||||
emeraldcup->windata[i].got_emerald = true;
|
||||
anymerit = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ static UINT8 cheatf_warp(void)
|
|||
if (success)
|
||||
{
|
||||
gamedata->gonerlevel = GDGONER_DONE;
|
||||
gamedata->sealedswapalerted = true;
|
||||
G_SetUsedCheats();
|
||||
}
|
||||
|
||||
|
|
@ -231,6 +232,7 @@ static UINT8 cheatf_devmode(void)
|
|||
}
|
||||
|
||||
gamedata->gonerlevel = GDGONER_DONE;
|
||||
gamedata->sealedswapalerted = true;
|
||||
|
||||
M_ClearMenus(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -666,6 +666,7 @@ void M_ClearStats(void)
|
|||
gamedata->majorkeyskipattempted = false;
|
||||
gamedata->enteredtutorialchallenge = false;
|
||||
gamedata->finishedtutorialchallenge = false;
|
||||
gamedata->sealedswapalerted = false;
|
||||
gamedata->musicstate = GDMUSIC_NONE;
|
||||
|
||||
gamedata->importprofilewins = false;
|
||||
|
|
@ -720,6 +721,8 @@ void M_ClearSecrets(void)
|
|||
skincolors[i].cache_spraycan = UINT16_MAX;
|
||||
}
|
||||
|
||||
memset(gamedata->sealedswaps, 0, sizeof(gamedata->sealedswaps));
|
||||
|
||||
Z_Free(gamedata->challengegrid);
|
||||
gamedata->challengegrid = NULL;
|
||||
gamedata->challengegridwidth = 0;
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ typedef enum {
|
|||
// This is the largest number of 9s that will fit in UINT32 and UINT16 respectively.
|
||||
#define GDMAX_RINGS 999999999
|
||||
#define GDMAX_CHAOKEYS 9999
|
||||
#define GDMAX_SEALEDSWAPS 7
|
||||
|
||||
#define GDCONVERT_ROUNDSTOKEY 14
|
||||
|
||||
|
|
@ -371,12 +372,15 @@ struct gamedata_t
|
|||
UINT32 totalrings;
|
||||
UINT32 totaltumbletime;
|
||||
|
||||
// Chao Key condition bypass
|
||||
// CHAO KEYS AND THEIR GENERATION
|
||||
UINT32 pendingkeyrounds;
|
||||
UINT8 pendingkeyroundoffset;
|
||||
UINT16 keyspending;
|
||||
UINT16 chaokeys;
|
||||
|
||||
// EMERALD REMAPPING
|
||||
cupheader_t *sealedswaps[GDMAX_SEALEDSWAPS];
|
||||
|
||||
// SPECIFIC SPECIAL EVENTS
|
||||
boolean everloadedaddon;
|
||||
boolean everfinishedcredits;
|
||||
|
|
@ -387,6 +391,7 @@ struct gamedata_t
|
|||
boolean majorkeyskipattempted;
|
||||
boolean enteredtutorialchallenge;
|
||||
boolean finishedtutorialchallenge;
|
||||
boolean sealedswapalerted;
|
||||
gdmusic_t musicstate;
|
||||
|
||||
UINT8 gonerlevel;
|
||||
|
|
|
|||
|
|
@ -335,6 +335,7 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
|
|||
challengesmenu.requestnew = false;
|
||||
challengesmenu.chaokeyadd = false;
|
||||
challengesmenu.keywasadded = false;
|
||||
challengesmenu.considersealedswapalert = false;
|
||||
challengesmenu.chaokeyhold = 0;
|
||||
challengesmenu.currentunlock = MAXUNLOCKABLES;
|
||||
challengesmenu.unlockcondition = NULL;
|
||||
|
|
@ -668,10 +669,15 @@ void M_ChallengesTick(void)
|
|||
if (challengesmenu.currentunlock < MAXUNLOCKABLES
|
||||
&& challengesmenu.unlockanim == UNLOCKTIME)
|
||||
{
|
||||
unlockable_t *ref = &unlockables[challengesmenu.currentunlock];
|
||||
|
||||
// Unlock animation... also tied directly to the actual unlock!
|
||||
gamedata->unlocked[challengesmenu.currentunlock] = true;
|
||||
M_UpdateUnlockablesAndExtraEmblems(true, true);
|
||||
|
||||
if (ref->type == SECRET_SPECIALATTACK)
|
||||
challengesmenu.considersealedswapalert = true;
|
||||
|
||||
// Update shown description just in case..?
|
||||
if (challengesmenu.unlockcondition)
|
||||
Z_Free(challengesmenu.unlockcondition);
|
||||
|
|
@ -682,12 +688,10 @@ void M_ChallengesTick(void)
|
|||
|
||||
if (challengesmenu.extradata)
|
||||
{
|
||||
unlockable_t *ref;
|
||||
UINT16 bombcolor;
|
||||
|
||||
M_UpdateChallengeGridExtraData(challengesmenu.extradata);
|
||||
|
||||
ref = &unlockables[challengesmenu.currentunlock];
|
||||
bombcolor = SKINCOLOR_NONE;
|
||||
|
||||
if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors)
|
||||
|
|
@ -747,7 +751,14 @@ void M_ChallengesTick(void)
|
|||
// Play music the moment control returns.
|
||||
M_PlayMenuJam();
|
||||
|
||||
if (gamedata->chaokeytutorial == false
|
||||
if (challengesmenu.considersealedswapalert == true
|
||||
&& M_ConsiderSealedSwapAlert() == true)
|
||||
{
|
||||
// No keygen tutorial in this case...
|
||||
// not ideal but at least unlikely to
|
||||
// get at same time?? :V
|
||||
}
|
||||
else if (gamedata->chaokeytutorial == false
|
||||
&& challengesmenu.keywasadded == true)
|
||||
{
|
||||
M_ChallengesTutorial(CCTUTORIAL_KEYGEN);
|
||||
|
|
|
|||
|
|
@ -6280,6 +6280,14 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
|
|||
{
|
||||
UINT32 val = READUINT32(save->p);
|
||||
|
||||
if (roundqueue.entries[i].rankrestricted && roundqueue.position != i+1)
|
||||
{
|
||||
// If this is a Sealed Star that hasn't yet been
|
||||
// reached, don't be picky about divergance. Just
|
||||
// use the base game without question. ~toast 010324
|
||||
continue;
|
||||
}
|
||||
|
||||
mapnum = roundqueue.entries[i].mapnum;
|
||||
if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL)
|
||||
{
|
||||
|
|
|
|||
24
src/p_user.c
24
src/p_user.c
|
|
@ -296,9 +296,29 @@ UINT8 P_GetNextEmerald(void)
|
|||
{
|
||||
cupheader_t *cup = NULL;
|
||||
|
||||
if (grandprixinfo.gp == true)
|
||||
if (grandprixinfo.gp == true && grandprixinfo.cup)
|
||||
{
|
||||
cup = grandprixinfo.cup;
|
||||
if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found
|
||||
|| grandprixinfo.cup->id >= basenumkartcupheaders // custom content
|
||||
|| M_SecretUnlocked(SECRET_SPECIALATTACK, false)) // true order
|
||||
{
|
||||
cup = grandprixinfo.cup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine order from sealedswaps.
|
||||
UINT8 i;
|
||||
for (i = 0; (i < GDMAX_SEALEDSWAPS && gamedata->sealedswaps[i]); i++)
|
||||
{
|
||||
if (gamedata->sealedswaps[i] != grandprixinfo.cup)
|
||||
continue;
|
||||
|
||||
// Repeat visit, grab the same ID.
|
||||
break;
|
||||
}
|
||||
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cup == NULL)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue