mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'seal-a-carte' into 'master'
Sealed Star re-ordering (resolves #606) Closes #606 See merge request KartKrew/Kart!1980
This commit is contained in:
commit
b136df4d41
14 changed files with 336 additions and 43 deletions
69
src/g_game.c
69
src/g_game.c
|
|
@ -3933,15 +3933,68 @@ void G_GPCupIntoRoundQueue(cupheader_t *cup, UINT8 setgametype, boolean setencor
|
||||||
// At the end of the Cup is a Rank-restricted treat.
|
// At the end of the Cup is a Rank-restricted treat.
|
||||||
// So we append it to the end of the roundqueue.
|
// So we append it to the end of the roundqueue.
|
||||||
// (as long as it exists, of course!)
|
// (as long as it exists, of course!)
|
||||||
cupLevelNum = cup->cachedlevels[CUPCACHE_SPECIAL];
|
|
||||||
if (cupLevelNum < nummapheaders)
|
|
||||||
{
|
{
|
||||||
G_MapIntoRoundQueue(
|
// Of course, this last minute game design tweak
|
||||||
cupLevelNum,
|
// has to make things a little complicated. We
|
||||||
G_GuessGametypeByTOL(mapheaderinfo[cupLevelNum]->typeoflevel),
|
// basically just make sure they're dispensed
|
||||||
setencore, // if this isn't correct, Got_Mapcmd will fix it
|
// at the intended difficulty sequence until
|
||||||
true // Rank-restricted!
|
// 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)
|
if (roundqueue.size == 0)
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ void srb2::save_ng_gamedata()
|
||||||
ng.milestones.majorkeyskipattempted = gamedata->majorkeyskipattempted;
|
ng.milestones.majorkeyskipattempted = gamedata->majorkeyskipattempted;
|
||||||
ng.milestones.finishedtutorialchallenge = gamedata->finishedtutorialchallenge;
|
ng.milestones.finishedtutorialchallenge = gamedata->finishedtutorialchallenge;
|
||||||
ng.milestones.enteredtutorialchallenge = gamedata->enteredtutorialchallenge;
|
ng.milestones.enteredtutorialchallenge = gamedata->enteredtutorialchallenge;
|
||||||
|
ng.milestones.sealedswapalerted = gamedata->sealedswapalerted;
|
||||||
ng.milestones.gonerlevel = gamedata->gonerlevel;
|
ng.milestones.gonerlevel = gamedata->gonerlevel;
|
||||||
ng.prisons.thisprisoneggpickup = gamedata->thisprisoneggpickup;
|
ng.prisons.thisprisoneggpickup = gamedata->thisprisoneggpickup;
|
||||||
ng.prisons.prisoneggstothispickup = gamedata->prisoneggstothispickup;
|
ng.prisons.prisoneggstothispickup = gamedata->prisoneggstothispickup;
|
||||||
|
|
@ -176,7 +177,7 @@ void srb2::save_ng_gamedata()
|
||||||
}
|
}
|
||||||
for (auto cup = kartcupheaders; cup; cup = cup->next)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -229,6 +230,17 @@ void srb2::save_ng_gamedata()
|
||||||
ng.cups[cupdata.name] = std::move(cupdata);
|
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};
|
std::string gamedataname_s {gamedatafilename};
|
||||||
fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)};
|
fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)};
|
||||||
fs::path tmpsavepath {fmt::format("{}/{}.tmp", 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->majorkeyskipattempted = js.milestones.majorkeyskipattempted;
|
||||||
gamedata->finishedtutorialchallenge = js.milestones.finishedtutorialchallenge;
|
gamedata->finishedtutorialchallenge = js.milestones.finishedtutorialchallenge;
|
||||||
gamedata->enteredtutorialchallenge = js.milestones.enteredtutorialchallenge;
|
gamedata->enteredtutorialchallenge = js.milestones.enteredtutorialchallenge;
|
||||||
|
gamedata->sealedswapalerted = js.milestones.sealedswapalerted;
|
||||||
gamedata->gonerlevel = js.milestones.gonerlevel;
|
gamedata->gonerlevel = js.milestones.gonerlevel;
|
||||||
gamedata->thisprisoneggpickup = js.prisons.thisprisoneggpickup;
|
gamedata->thisprisoneggpickup = js.prisons.thisprisoneggpickup;
|
||||||
gamedata->prisoneggstothispickup = js.prisons.prisoneggstothispickup;
|
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();
|
M_FinaliseGameData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ struct GamedataMilestonesJson final
|
||||||
bool majorkeyskipattempted;
|
bool majorkeyskipattempted;
|
||||||
bool finishedtutorialchallenge;
|
bool finishedtutorialchallenge;
|
||||||
bool enteredtutorialchallenge;
|
bool enteredtutorialchallenge;
|
||||||
|
bool sealedswapalerted;
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||||
GamedataMilestonesJson,
|
GamedataMilestonesJson,
|
||||||
|
|
@ -81,7 +82,8 @@ struct GamedataMilestonesJson final
|
||||||
chaokeytutorial,
|
chaokeytutorial,
|
||||||
majorkeyskipattempted,
|
majorkeyskipattempted,
|
||||||
finishedtutorialchallenge,
|
finishedtutorialchallenge,
|
||||||
enteredtutorialchallenge
|
enteredtutorialchallenge,
|
||||||
|
sealedswapalerted
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -184,6 +186,13 @@ struct GamedataCupJson final
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(GamedataCupJson, name, records)
|
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
|
struct GamedataJson final
|
||||||
{
|
{
|
||||||
GamedataPlaytimeJson playtime;
|
GamedataPlaytimeJson playtime;
|
||||||
|
|
@ -203,6 +212,7 @@ struct GamedataJson final
|
||||||
std::unordered_map<std::string, GamedataMapJson> maps;
|
std::unordered_map<std::string, GamedataMapJson> maps;
|
||||||
std::vector<GamedataSprayCanJson> spraycans;
|
std::vector<GamedataSprayCanJson> spraycans;
|
||||||
std::unordered_map<std::string, GamedataCupJson> cups;
|
std::unordered_map<std::string, GamedataCupJson> cups;
|
||||||
|
std::vector<GamedataSealedSwapJson> sealedswaps;
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||||
GamedataJson,
|
GamedataJson,
|
||||||
|
|
@ -222,7 +232,8 @@ struct GamedataJson final
|
||||||
skins,
|
skins,
|
||||||
maps,
|
maps,
|
||||||
spraycans,
|
spraycans,
|
||||||
cups
|
cups,
|
||||||
|
sealedswaps
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -680,6 +680,8 @@ void M_Init(void);
|
||||||
|
|
||||||
void M_PlayMenuJam(void);
|
void M_PlayMenuJam(void);
|
||||||
|
|
||||||
|
boolean M_ConsiderSealedSwapAlert(void);
|
||||||
|
|
||||||
void M_OpenVirtualKeyboard(boolean gamepad);
|
void M_OpenVirtualKeyboard(boolean gamepad);
|
||||||
void M_MenuTypingInput(INT32 key);
|
void M_MenuTypingInput(INT32 key);
|
||||||
|
|
||||||
|
|
@ -1347,6 +1349,8 @@ extern struct challengesmenu_s {
|
||||||
boolean chaokeyadd, keywasadded;
|
boolean chaokeyadd, keywasadded;
|
||||||
UINT8 chaokeyhold;
|
UINT8 chaokeyhold;
|
||||||
|
|
||||||
|
boolean considersealedswapalert;
|
||||||
|
|
||||||
boolean requestflip;
|
boolean requestflip;
|
||||||
|
|
||||||
UINT16 unlockcount[CMC_MAX];
|
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);
|
rankx += 19 - (rankw / 2);
|
||||||
|
|
||||||
cupwindata_t *windata = &(cup->windata[difficulty]);
|
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 (windata->best_placement == 0)
|
||||||
{
|
{
|
||||||
if (statsmode)
|
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);
|
V_DrawCharacter((14-4)/2 + rankx, ranky, '.' | V_GRAYMAP, false);
|
||||||
rankx += 14 + 1;
|
rankx += 14 + 1;
|
||||||
V_DrawCharacter((12-4)/2 + rankx, ranky, '.' | V_GRAYMAP, false);
|
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;
|
UINT8 *colormap = NULL;
|
||||||
|
|
@ -2934,13 +2984,15 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
||||||
if (charPat)
|
if (charPat)
|
||||||
V_DrawFixedPatch((rankx)*FRACUNIT, (ranky)*FRACUNIT, FRACUNIT, 0, charPat, colormap);
|
V_DrawFixedPatch((rankx)*FRACUNIT, (ranky)*FRACUNIT, FRACUNIT, 0, charPat, colormap);
|
||||||
|
|
||||||
|
windataemeraldmaybe:
|
||||||
|
|
||||||
rankx += 12 + 1;
|
rankx += 12 + 1;
|
||||||
|
|
||||||
if (noemerald)
|
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);
|
V_DrawCharacter(rankx+2, ranky+2, '+', false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2948,14 +3000,14 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
||||||
|
|
||||||
if (!flash)
|
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);
|
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *emname = va(
|
const char *emname = va(
|
||||||
"%sMAP%c",
|
"%sMAP%c",
|
||||||
(cup->emeraldnum > 7) ? "SUP" : "EME",
|
(emeraldnum > 7) ? "SUP" : "EME",
|
||||||
colormap ? '\0' : 'B'
|
colormap ? '\0' : 'B'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -3116,7 +3168,7 @@ void M_DrawCupSelect(void)
|
||||||
y += 44; //(8 + 100) - (20 + 44)
|
y += 44; //(8 + 100) - (20 + 44)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windata && windata->best_placement != 0)
|
if (windata)
|
||||||
{
|
{
|
||||||
M_DrawCupWinData(
|
M_DrawCupWinData(
|
||||||
x,
|
x,
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,35 @@ void M_PlayMenuJam(void)
|
||||||
|
|
||||||
#undef IsCurrentlyPlaying
|
#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)
|
void M_ValidateRestoreMenu(void)
|
||||||
{
|
{
|
||||||
if (restoreMenu == NULL || restoreMenu == &MAIN_GonerDef)
|
if (restoreMenu == NULL || restoreMenu == &MAIN_GonerDef)
|
||||||
|
|
@ -629,6 +658,11 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore)
|
||||||
M_SetupPlayMenu(-1);
|
M_SetupPlayMenu(-1);
|
||||||
PLAY_CharSelectDef.prevMenu = &MainDef;
|
PLAY_CharSelectDef.prevMenu = &MainDef;
|
||||||
|
|
||||||
|
if (torestore != &MISC_ChallengesDef)
|
||||||
|
{
|
||||||
|
M_ConsiderSealedSwapAlert();
|
||||||
|
}
|
||||||
|
|
||||||
return torestore;
|
return torestore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ static struct podiumData_s
|
||||||
sfxenum_t gradeVoice;
|
sfxenum_t gradeVoice;
|
||||||
|
|
||||||
cupheader_t *cup;
|
cupheader_t *cup;
|
||||||
|
UINT8 emeraldnum;
|
||||||
|
|
||||||
boolean fastForward;
|
boolean fastForward;
|
||||||
|
|
||||||
|
|
@ -102,6 +103,7 @@ void podiumData_s::Init(void)
|
||||||
{
|
{
|
||||||
rank = grandprixinfo.rank;
|
rank = grandprixinfo.rank;
|
||||||
cup = grandprixinfo.cup;
|
cup = grandprixinfo.cup;
|
||||||
|
emeraldnum = cup->emeraldnum;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -119,6 +121,7 @@ void podiumData_s::Init(void)
|
||||||
|
|
||||||
cup = cup->next;
|
cup = cup->next;
|
||||||
}
|
}
|
||||||
|
emeraldnum = 0;
|
||||||
|
|
||||||
memset(&rank, 0, sizeof(gpRank_t));
|
memset(&rank, 0, sizeof(gpRank_t));
|
||||||
rank.skin = players[consoleplayer].skin;
|
rank.skin = players[consoleplayer].skin;
|
||||||
|
|
@ -628,12 +631,7 @@ void podiumData_s::Draw(void)
|
||||||
case GPEVENT_SPECIAL:
|
case GPEVENT_SPECIAL:
|
||||||
{
|
{
|
||||||
srb2::Draw drawer_emerald = drawer_gametype;
|
srb2::Draw drawer_emerald = drawer_gametype;
|
||||||
UINT8 emeraldNum = 0;
|
UINT8 emeraldNum = g_podiumData.emeraldnum;
|
||||||
|
|
||||||
if (cup != nullptr)
|
|
||||||
{
|
|
||||||
emeraldNum = cup->emeraldnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean useWhiteFrame = ((leveltime & 1) || !dta->gotSpecialPrize);
|
boolean useWhiteFrame = ((leveltime & 1) || !dta->gotSpecialPrize);
|
||||||
patch_t *emeraldPatch = nullptr;
|
patch_t *emeraldPatch = nullptr;
|
||||||
|
|
@ -844,12 +842,7 @@ void podiumData_s::Draw(void)
|
||||||
|
|
||||||
if (rank.specialWon == true)
|
if (rank.specialWon == true)
|
||||||
{
|
{
|
||||||
UINT8 emeraldNum = 0;
|
UINT8 emeraldNum = g_podiumData.emeraldnum;
|
||||||
|
|
||||||
if (cup != nullptr)
|
|
||||||
{
|
|
||||||
emeraldNum = cup->emeraldnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boolean emeraldBlink = (leveltime & 1);
|
const boolean emeraldBlink = (leveltime & 1);
|
||||||
patch_t *emeraldOverlay = nullptr;
|
patch_t *emeraldOverlay = nullptr;
|
||||||
|
|
@ -1263,6 +1256,60 @@ void K_ResetCeremony(void)
|
||||||
return;
|
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!
|
// Write grade, position, and emerald-having-ness for later sessions!
|
||||||
i = (grandprixinfo.masterbots) ? KARTGP_MASTER : grandprixinfo.gamespeed;
|
i = (grandprixinfo.masterbots) ? KARTGP_MASTER : grandprixinfo.gamespeed;
|
||||||
|
|
||||||
|
|
@ -1292,9 +1339,9 @@ void K_ResetCeremony(void)
|
||||||
anymerit = true;
|
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;
|
anymerit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ static UINT8 cheatf_warp(void)
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
gamedata->gonerlevel = GDGONER_DONE;
|
gamedata->gonerlevel = GDGONER_DONE;
|
||||||
|
gamedata->sealedswapalerted = true;
|
||||||
G_SetUsedCheats();
|
G_SetUsedCheats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,6 +232,7 @@ static UINT8 cheatf_devmode(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
gamedata->gonerlevel = GDGONER_DONE;
|
gamedata->gonerlevel = GDGONER_DONE;
|
||||||
|
gamedata->sealedswapalerted = true;
|
||||||
|
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -666,6 +666,7 @@ void M_ClearStats(void)
|
||||||
gamedata->majorkeyskipattempted = false;
|
gamedata->majorkeyskipattempted = false;
|
||||||
gamedata->enteredtutorialchallenge = false;
|
gamedata->enteredtutorialchallenge = false;
|
||||||
gamedata->finishedtutorialchallenge = false;
|
gamedata->finishedtutorialchallenge = false;
|
||||||
|
gamedata->sealedswapalerted = false;
|
||||||
gamedata->musicstate = GDMUSIC_NONE;
|
gamedata->musicstate = GDMUSIC_NONE;
|
||||||
|
|
||||||
gamedata->importprofilewins = false;
|
gamedata->importprofilewins = false;
|
||||||
|
|
@ -720,6 +721,8 @@ void M_ClearSecrets(void)
|
||||||
skincolors[i].cache_spraycan = UINT16_MAX;
|
skincolors[i].cache_spraycan = UINT16_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(gamedata->sealedswaps, 0, sizeof(gamedata->sealedswaps));
|
||||||
|
|
||||||
Z_Free(gamedata->challengegrid);
|
Z_Free(gamedata->challengegrid);
|
||||||
gamedata->challengegrid = NULL;
|
gamedata->challengegrid = NULL;
|
||||||
gamedata->challengegridwidth = 0;
|
gamedata->challengegridwidth = 0;
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,7 @@ typedef enum {
|
||||||
// This is the largest number of 9s that will fit in UINT32 and UINT16 respectively.
|
// This is the largest number of 9s that will fit in UINT32 and UINT16 respectively.
|
||||||
#define GDMAX_RINGS 999999999
|
#define GDMAX_RINGS 999999999
|
||||||
#define GDMAX_CHAOKEYS 9999
|
#define GDMAX_CHAOKEYS 9999
|
||||||
|
#define GDMAX_SEALEDSWAPS 7
|
||||||
|
|
||||||
#define GDCONVERT_ROUNDSTOKEY 14
|
#define GDCONVERT_ROUNDSTOKEY 14
|
||||||
|
|
||||||
|
|
@ -371,12 +372,15 @@ struct gamedata_t
|
||||||
UINT32 totalrings;
|
UINT32 totalrings;
|
||||||
UINT32 totaltumbletime;
|
UINT32 totaltumbletime;
|
||||||
|
|
||||||
// Chao Key condition bypass
|
// CHAO KEYS AND THEIR GENERATION
|
||||||
UINT32 pendingkeyrounds;
|
UINT32 pendingkeyrounds;
|
||||||
UINT8 pendingkeyroundoffset;
|
UINT8 pendingkeyroundoffset;
|
||||||
UINT16 keyspending;
|
UINT16 keyspending;
|
||||||
UINT16 chaokeys;
|
UINT16 chaokeys;
|
||||||
|
|
||||||
|
// EMERALD REMAPPING
|
||||||
|
cupheader_t *sealedswaps[GDMAX_SEALEDSWAPS];
|
||||||
|
|
||||||
// SPECIFIC SPECIAL EVENTS
|
// SPECIFIC SPECIAL EVENTS
|
||||||
boolean everloadedaddon;
|
boolean everloadedaddon;
|
||||||
boolean everfinishedcredits;
|
boolean everfinishedcredits;
|
||||||
|
|
@ -387,6 +391,7 @@ struct gamedata_t
|
||||||
boolean majorkeyskipattempted;
|
boolean majorkeyskipattempted;
|
||||||
boolean enteredtutorialchallenge;
|
boolean enteredtutorialchallenge;
|
||||||
boolean finishedtutorialchallenge;
|
boolean finishedtutorialchallenge;
|
||||||
|
boolean sealedswapalerted;
|
||||||
gdmusic_t musicstate;
|
gdmusic_t musicstate;
|
||||||
|
|
||||||
UINT8 gonerlevel;
|
UINT8 gonerlevel;
|
||||||
|
|
|
||||||
|
|
@ -335,6 +335,7 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
|
||||||
challengesmenu.requestnew = false;
|
challengesmenu.requestnew = false;
|
||||||
challengesmenu.chaokeyadd = false;
|
challengesmenu.chaokeyadd = false;
|
||||||
challengesmenu.keywasadded = false;
|
challengesmenu.keywasadded = false;
|
||||||
|
challengesmenu.considersealedswapalert = false;
|
||||||
challengesmenu.chaokeyhold = 0;
|
challengesmenu.chaokeyhold = 0;
|
||||||
challengesmenu.currentunlock = MAXUNLOCKABLES;
|
challengesmenu.currentunlock = MAXUNLOCKABLES;
|
||||||
challengesmenu.unlockcondition = NULL;
|
challengesmenu.unlockcondition = NULL;
|
||||||
|
|
@ -668,10 +669,15 @@ void M_ChallengesTick(void)
|
||||||
if (challengesmenu.currentunlock < MAXUNLOCKABLES
|
if (challengesmenu.currentunlock < MAXUNLOCKABLES
|
||||||
&& challengesmenu.unlockanim == UNLOCKTIME)
|
&& challengesmenu.unlockanim == UNLOCKTIME)
|
||||||
{
|
{
|
||||||
|
unlockable_t *ref = &unlockables[challengesmenu.currentunlock];
|
||||||
|
|
||||||
// Unlock animation... also tied directly to the actual unlock!
|
// Unlock animation... also tied directly to the actual unlock!
|
||||||
gamedata->unlocked[challengesmenu.currentunlock] = true;
|
gamedata->unlocked[challengesmenu.currentunlock] = true;
|
||||||
M_UpdateUnlockablesAndExtraEmblems(true, true);
|
M_UpdateUnlockablesAndExtraEmblems(true, true);
|
||||||
|
|
||||||
|
if (ref->type == SECRET_SPECIALATTACK)
|
||||||
|
challengesmenu.considersealedswapalert = true;
|
||||||
|
|
||||||
// Update shown description just in case..?
|
// Update shown description just in case..?
|
||||||
if (challengesmenu.unlockcondition)
|
if (challengesmenu.unlockcondition)
|
||||||
Z_Free(challengesmenu.unlockcondition);
|
Z_Free(challengesmenu.unlockcondition);
|
||||||
|
|
@ -682,12 +688,10 @@ void M_ChallengesTick(void)
|
||||||
|
|
||||||
if (challengesmenu.extradata)
|
if (challengesmenu.extradata)
|
||||||
{
|
{
|
||||||
unlockable_t *ref;
|
|
||||||
UINT16 bombcolor;
|
UINT16 bombcolor;
|
||||||
|
|
||||||
M_UpdateChallengeGridExtraData(challengesmenu.extradata);
|
M_UpdateChallengeGridExtraData(challengesmenu.extradata);
|
||||||
|
|
||||||
ref = &unlockables[challengesmenu.currentunlock];
|
|
||||||
bombcolor = SKINCOLOR_NONE;
|
bombcolor = SKINCOLOR_NONE;
|
||||||
|
|
||||||
if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors)
|
if (ref->color != SKINCOLOR_NONE && ref->color < numskincolors)
|
||||||
|
|
@ -747,7 +751,14 @@ void M_ChallengesTick(void)
|
||||||
// Play music the moment control returns.
|
// Play music the moment control returns.
|
||||||
M_PlayMenuJam();
|
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)
|
&& challengesmenu.keywasadded == true)
|
||||||
{
|
{
|
||||||
M_ChallengesTutorial(CCTUTORIAL_KEYGEN);
|
M_ChallengesTutorial(CCTUTORIAL_KEYGEN);
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,9 @@ void M_StopMessage(INT32 choice)
|
||||||
|
|
||||||
boolean M_MenuMessageTick(void)
|
boolean M_MenuMessageTick(void)
|
||||||
{
|
{
|
||||||
|
if (menuwipe)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (menumessage.closing)
|
if (menumessage.closing)
|
||||||
{
|
{
|
||||||
if (menumessage.closing > MENUMESSAGECLOSE)
|
if (menumessage.closing > MENUMESSAGECLOSE)
|
||||||
|
|
|
||||||
|
|
@ -6284,6 +6284,14 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
|
||||||
{
|
{
|
||||||
UINT32 val = READUINT32(save->p);
|
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;
|
mapnum = roundqueue.entries[i].mapnum;
|
||||||
if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL)
|
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;
|
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)
|
if (cup == NULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue