mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 04:21:47 +00:00
Add Goner Choice
- Selection between Tails' Way (existing Tutorial) and Eggman's Way (Playground)
- Semi-passable UI
- Characterful descriptions
- Add "PlaygroundRoute" condition to Challenges
- Fires if you select Eggman's Way
- 0 Chao Keys unless you go back to Goner for the outro (which Playground skips)
This commit is contained in:
parent
c06fc9cccf
commit
295e8dd0ce
10 changed files with 305 additions and 32 deletions
|
|
@ -2965,7 +2965,8 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
|
||||||
|| (++offset && fastcmp(params[0], "REPLAY"))
|
|| (++offset && fastcmp(params[0], "REPLAY"))
|
||||||
|| (++offset && fastcmp(params[0], "CRASH"))
|
|| (++offset && fastcmp(params[0], "CRASH"))
|
||||||
|| (++offset && fastcmp(params[0], "TUTORIALSKIP"))
|
|| (++offset && fastcmp(params[0], "TUTORIALSKIP"))
|
||||||
|| (++offset && fastcmp(params[0], "TUTORIALDONE")))
|
|| (++offset && fastcmp(params[0], "TUTORIALDONE"))
|
||||||
|
|| (++offset && fastcmp(params[0], "PLAYGROUNDROUTE")))
|
||||||
{
|
{
|
||||||
//PARAMCHECK(1);
|
//PARAMCHECK(1);
|
||||||
ty = UC_ADDON + offset;
|
ty = UC_ADDON + offset;
|
||||||
|
|
@ -3633,6 +3634,11 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
||||||
titlemap = Z_StrDup(word2);
|
titlemap = Z_StrDup(word2);
|
||||||
titlechanged = true;
|
titlechanged = true;
|
||||||
}
|
}
|
||||||
|
else if (fastcmp(word, "TUTORIALPLAYGROUNDMAP"))
|
||||||
|
{
|
||||||
|
Z_Free(tutorialplaygroundmap);
|
||||||
|
tutorialplaygroundmap = Z_StrDup(word2);
|
||||||
|
}
|
||||||
else if (fastcmp(word, "TUTORIALCHALLENGEMAP"))
|
else if (fastcmp(word, "TUTORIALCHALLENGEMAP"))
|
||||||
{
|
{
|
||||||
Z_Free(tutorialchallengemap);
|
Z_Free(tutorialchallengemap);
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,7 @@ extern boolean looptitle;
|
||||||
extern char * bootmap; //bootmap for loading a map on startup
|
extern char * bootmap; //bootmap for loading a map on startup
|
||||||
extern char * podiummap; // map to load for podium
|
extern char * podiummap; // map to load for podium
|
||||||
|
|
||||||
|
extern char * tutorialplaygroundmap; // map to load for playground
|
||||||
extern char * tutorialchallengemap; // map to load for tutorial skip
|
extern char * tutorialchallengemap; // map to load for tutorial skip
|
||||||
extern UINT8 tutorialchallenge;
|
extern UINT8 tutorialchallenge;
|
||||||
#define TUTORIALSKIP_NONE 0
|
#define TUTORIALSKIP_NONE 0
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,7 @@ boolean looptitle = true;
|
||||||
char * bootmap = NULL; //bootmap for loading a map on startup
|
char * bootmap = NULL; //bootmap for loading a map on startup
|
||||||
char * podiummap = NULL; // map to load for podium
|
char * podiummap = NULL; // map to load for podium
|
||||||
|
|
||||||
|
char * tutorialplaygroundmap = NULL; // map to load for playground
|
||||||
char * tutorialchallengemap = NULL; // map to load for tutorial skip
|
char * tutorialchallengemap = NULL; // map to load for tutorial skip
|
||||||
UINT8 tutorialchallenge = TUTORIALSKIP_NONE;
|
UINT8 tutorialchallenge = TUTORIALSKIP_NONE;
|
||||||
|
|
||||||
|
|
@ -5076,7 +5077,7 @@ void G_EndGame(void)
|
||||||
// Only do evaluation and credits in singleplayer contexts
|
// Only do evaluation and credits in singleplayer contexts
|
||||||
if (!netgame)
|
if (!netgame)
|
||||||
{
|
{
|
||||||
if (gametype == GT_TUTORIAL)
|
if (gametype == GT_TUTORIAL && gamedata->gonerlevel < GDGONER_DONE)
|
||||||
{
|
{
|
||||||
// Tutorial was finished
|
// Tutorial was finished
|
||||||
gamedata->tutorialdone = true;
|
gamedata->tutorialdone = true;
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ void srb2::save_ng_gamedata()
|
||||||
ng.milestones.enteredtutorialchallenge = gamedata->enteredtutorialchallenge;
|
ng.milestones.enteredtutorialchallenge = gamedata->enteredtutorialchallenge;
|
||||||
ng.milestones.sealedswapalerted = gamedata->sealedswapalerted;
|
ng.milestones.sealedswapalerted = gamedata->sealedswapalerted;
|
||||||
ng.milestones.tutorialdone = gamedata->tutorialdone;
|
ng.milestones.tutorialdone = gamedata->tutorialdone;
|
||||||
|
ng.milestones.playgroundroute = gamedata->playgroundroute;
|
||||||
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;
|
||||||
|
|
@ -471,6 +472,7 @@ void srb2::load_ng_gamedata()
|
||||||
gamedata->enteredtutorialchallenge = js.milestones.enteredtutorialchallenge;
|
gamedata->enteredtutorialchallenge = js.milestones.enteredtutorialchallenge;
|
||||||
gamedata->sealedswapalerted = js.milestones.sealedswapalerted;
|
gamedata->sealedswapalerted = js.milestones.sealedswapalerted;
|
||||||
gamedata->tutorialdone = js.milestones.tutorialdone;
|
gamedata->tutorialdone = js.milestones.tutorialdone;
|
||||||
|
gamedata->playgroundroute = js.milestones.playgroundroute;
|
||||||
gamedata->gonerlevel = js.milestones.gonerlevel;
|
gamedata->gonerlevel = js.milestones.gonerlevel;
|
||||||
gamedata->thisprisoneggpickup = js.prisons.thisprisoneggpickup;
|
gamedata->thisprisoneggpickup = js.prisons.thisprisoneggpickup;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ struct GamedataMilestonesJson final
|
||||||
bool enteredtutorialchallenge;
|
bool enteredtutorialchallenge;
|
||||||
bool sealedswapalerted;
|
bool sealedswapalerted;
|
||||||
bool tutorialdone;
|
bool tutorialdone;
|
||||||
|
bool playgroundroute;
|
||||||
|
|
||||||
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
SRB2_JSON_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
|
||||||
GamedataMilestonesJson,
|
GamedataMilestonesJson,
|
||||||
|
|
@ -109,7 +110,8 @@ struct GamedataMilestonesJson final
|
||||||
finishedtutorialchallenge,
|
finishedtutorialchallenge,
|
||||||
enteredtutorialchallenge,
|
enteredtutorialchallenge,
|
||||||
sealedswapalerted,
|
sealedswapalerted,
|
||||||
tutorialdone
|
tutorialdone,
|
||||||
|
playgroundroute
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,12 @@ void M_GonerBGTick(void);
|
||||||
void M_GonerBGImplyPassageOfTime(void);
|
void M_GonerBGImplyPassageOfTime(void);
|
||||||
void M_DrawGonerBack(void);
|
void M_DrawGonerBack(void);
|
||||||
void M_GonerProfile(INT32 choice);
|
void M_GonerProfile(INT32 choice);
|
||||||
|
void M_GonerChoice(INT32 choice);
|
||||||
void M_GonerTutorial(INT32 choice);
|
void M_GonerTutorial(INT32 choice);
|
||||||
|
void M_GonerPlayground(INT32 choice);
|
||||||
void M_GonerResetLooking(int type);
|
void M_GonerResetLooking(int type);
|
||||||
void M_GonerCheckLooking(void);
|
void M_GonerCheckLooking(void);
|
||||||
|
void M_GonerResetText(void);
|
||||||
void M_GonerGDQ(boolean opinion);
|
void M_GonerGDQ(boolean opinion);
|
||||||
boolean M_GonerMusicPlayable(void);
|
boolean M_GonerMusicPlayable(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,9 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
||||||
} else if (fastcmp(word,"podiummap")) {
|
} else if (fastcmp(word,"podiummap")) {
|
||||||
lua_pushstring(L, podiummap);
|
lua_pushstring(L, podiummap);
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (fastcmp(word,"tutorialplaygroundmap")) {
|
||||||
|
lua_pushstring(L, tutorialplaygroundmap);
|
||||||
|
return 1;
|
||||||
} else if (fastcmp(word,"tutorialchallengemap")) {
|
} else if (fastcmp(word,"tutorialchallengemap")) {
|
||||||
lua_pushstring(L, tutorialchallengemap);
|
lua_pushstring(L, tutorialchallengemap);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,7 @@ void M_ClearStats(void)
|
||||||
gamedata->finishedtutorialchallenge = false;
|
gamedata->finishedtutorialchallenge = false;
|
||||||
gamedata->sealedswapalerted = false;
|
gamedata->sealedswapalerted = false;
|
||||||
gamedata->tutorialdone = false;
|
gamedata->tutorialdone = false;
|
||||||
|
gamedata->playgroundroute = false;
|
||||||
gamedata->musicstate = GDMUSIC_NONE;
|
gamedata->musicstate = GDMUSIC_NONE;
|
||||||
|
|
||||||
gamedata->importprofilewins = false;
|
gamedata->importprofilewins = false;
|
||||||
|
|
@ -1755,6 +1756,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
|
||||||
return (gamedata->finishedtutorialchallenge == true);
|
return (gamedata->finishedtutorialchallenge == true);
|
||||||
case UC_TUTORIALDONE:
|
case UC_TUTORIALDONE:
|
||||||
return (gamedata->tutorialdone == true);
|
return (gamedata->tutorialdone == true);
|
||||||
|
case UC_PLAYGROUND:
|
||||||
|
return (gamedata->playgroundroute == true);
|
||||||
case UC_PASSWORD:
|
case UC_PASSWORD:
|
||||||
return (cn->stringvar == NULL);
|
return (cn->stringvar == NULL);
|
||||||
|
|
||||||
|
|
@ -2641,6 +2644,8 @@ static const char *M_GetConditionString(condition_t *cn)
|
||||||
return "successfully skip the Tutorial";
|
return "successfully skip the Tutorial";
|
||||||
case UC_TUTORIALDONE:
|
case UC_TUTORIALDONE:
|
||||||
return "complete the Tutorial";
|
return "complete the Tutorial";
|
||||||
|
case UC_PLAYGROUND:
|
||||||
|
return "pick the Playground";
|
||||||
case UC_PASSWORD:
|
case UC_PASSWORD:
|
||||||
return "enter a secret password";
|
return "enter a secret password";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ typedef enum
|
||||||
UC_CRASH, // Hee ho !
|
UC_CRASH, // Hee ho !
|
||||||
UC_TUTORIALSKIP, // Complete the Tutorial Challenge
|
UC_TUTORIALSKIP, // Complete the Tutorial Challenge
|
||||||
UC_TUTORIALDONE, // Complete the Tutorial at all
|
UC_TUTORIALDONE, // Complete the Tutorial at all
|
||||||
|
UC_PLAYGROUND, // Go to the playground instead..?
|
||||||
|
|
||||||
UC_PASSWORD, // Type in something funny
|
UC_PASSWORD, // Type in something funny
|
||||||
|
|
||||||
|
|
@ -301,7 +302,7 @@ typedef enum {
|
||||||
|
|
||||||
#define GDCONVERT_ROUNDSTOKEY 5
|
#define GDCONVERT_ROUNDSTOKEY 5
|
||||||
|
|
||||||
#define GDINIT_CHAOKEYS 10 // Start with 10 Chao Keys !!
|
#define GDINIT_CHAOKEYS 0 // Start with ZERO Chao Keys. You get NONE. fizzy lifting dink
|
||||||
#define GDINIT_PRISONSTOPRIZE 15 // 15 Prison Eggs to your [Wild Prize] !!
|
#define GDINIT_PRISONSTOPRIZE 15 // 15 Prison Eggs to your [Wild Prize] !!
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -395,6 +396,7 @@ struct gamedata_t
|
||||||
boolean finishedtutorialchallenge;
|
boolean finishedtutorialchallenge;
|
||||||
boolean sealedswapalerted;
|
boolean sealedswapalerted;
|
||||||
boolean tutorialdone;
|
boolean tutorialdone;
|
||||||
|
boolean playgroundroute;
|
||||||
gdmusic_t musicstate;
|
gdmusic_t musicstate;
|
||||||
|
|
||||||
UINT8 gonerlevel;
|
UINT8 gonerlevel;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "../core/string.h"
|
#include "../core/string.h"
|
||||||
|
|
||||||
static void M_GonerDrawer(void);
|
static void M_GonerDrawer(void);
|
||||||
|
static void M_GonerChoiceDrawer(void);
|
||||||
static void M_GonerConclude(INT32 choice);
|
static void M_GonerConclude(INT32 choice);
|
||||||
static boolean M_GonerInputs(INT32 ch);
|
static boolean M_GonerInputs(INT32 ch);
|
||||||
|
|
||||||
|
|
@ -55,9 +56,9 @@ menuitem_t MAIN_Goner[] =
|
||||||
"ASSIGN VEHICLE INPUTS.", NULL,
|
"ASSIGN VEHICLE INPUTS.", NULL,
|
||||||
{.routine = M_GonerProfile}, 0, 0},
|
{.routine = M_GonerProfile}, 0, 0},
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "BEGIN TUTORIAL",
|
{IT_STRING | IT_CALL, "MAKE CHOICE",
|
||||||
"PREPARE FOR INTEGRATION.", NULL,
|
"PREPARE FOR INTEGRATION?", NULL,
|
||||||
{.routine = M_GonerTutorial}, 0, 0},
|
{.routine = M_GonerChoice}, 0, 0},
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "START GAME",
|
{IT_STRING | IT_CALL, "START GAME",
|
||||||
"I WILL SUCCEED.", NULL,
|
"I WILL SUCCEED.", NULL,
|
||||||
|
|
@ -82,9 +83,57 @@ menu_t MAIN_GonerDef = {
|
||||||
M_GonerInputs,
|
M_GonerInputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
menuitem_t MAIN_GonerChoice[] =
|
||||||
|
{
|
||||||
|
{IT_STRING | IT_CALL, "Tails' way",
|
||||||
|
"As a child scientist, Tails has recorded bits\n"
|
||||||
|
"and pieces of an adventure he and Eggman went\n"
|
||||||
|
"on while trying out their new Ring Racers.\n"
|
||||||
|
"\n"
|
||||||
|
"This is a structured, back-to-basics session\n"
|
||||||
|
"that will likely take ""\x88""10-20 minutes""\x80"" of your time.",
|
||||||
|
NULL, {.routine = M_GonerTutorial}, 0, 0},
|
||||||
|
|
||||||
|
//{IT_STRING, NULL, NULL, NULL, {.routine = M_QuitSRB2}, 0, 0}, // will be replaced
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "Eggman's way",
|
||||||
|
"As a childlike scientist, Eggman has turned the\n"
|
||||||
|
"wrecked Egg Carrier into a giant skatepark,\n"
|
||||||
|
"dotted with fun collectables to test drivers.\n"
|
||||||
|
"\n"
|
||||||
|
"You can ""\x88""exit immediately""\x80"" and get to racing...\n"
|
||||||
|
"or spend ""\x88""as long as you want""\x80"" in the playground!",
|
||||||
|
NULL, {.routine = M_GonerPlayground}, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_t MAIN_GonerChoiceDef = {
|
||||||
|
sizeof (MAIN_GonerChoice) / sizeof (menuitem_t),
|
||||||
|
&MAIN_GonerDef,
|
||||||
|
0,
|
||||||
|
MAIN_GonerChoice,
|
||||||
|
26, 160,
|
||||||
|
0, 0,
|
||||||
|
MBF_UD_LR_FLIPPED,
|
||||||
|
"_GONER",
|
||||||
|
0, 0,
|
||||||
|
M_GonerChoiceDrawer,
|
||||||
|
M_DrawGonerBack,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GONERCHOICE_TAILS = 0,
|
||||||
|
//GONERCHOICE_NONEBINEY,
|
||||||
|
GONERCHOICE_EGGMAN
|
||||||
|
} gonerchoices_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GONERSPEAKER_EGGMAN = 0,
|
GONERSPEAKER_EGGMAN = 0,
|
||||||
|
|
@ -429,16 +478,6 @@ void Miles_Electric_Lower()
|
||||||
int goner_levelworking = GDGONER_INIT;
|
int goner_levelworking = GDGONER_INIT;
|
||||||
bool goner_gdq = false;
|
bool goner_gdq = false;
|
||||||
|
|
||||||
void M_GonerResetText(void)
|
|
||||||
{
|
|
||||||
goner_typewriter.ClearText();
|
|
||||||
LinesToDigest.clear();
|
|
||||||
LinesOutput.clear();
|
|
||||||
|
|
||||||
goner_scroll = 0;
|
|
||||||
goner_scrollend = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Initial_Control_Info(void)
|
static void Initial_Control_Info(void)
|
||||||
{
|
{
|
||||||
if (cv_currprofile.value != -1)
|
if (cv_currprofile.value != -1)
|
||||||
|
|
@ -669,11 +708,22 @@ void M_AddGonerLines(void)
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
|
||||||
"Now, Metal... it's important you pay attention.");
|
"Now, Metal... it's important you pay attention.");
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
|
||||||
"It's time to ""\x87""begin your Tutorial""\x80""!");
|
"We have a ""\x88""choice""\x80"" ready for you.");
|
||||||
|
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
|
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
|
||||||
"Remember, MS-1. Even when you move on from this setup, you "\
|
"You can play back our testing data as a sort of ""\x82""tutorial""\x80"\
|
||||||
"can always change your ""\x87""Options""\x80"" at any time from the menu.");
|
" and learn the core parts of driving in a safe environment...");
|
||||||
|
|
||||||
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
|
||||||
|
"...or if you're too headstrong and want to figure things out"\
|
||||||
|
" for yourself, we can let you loose in our ""\x85""playground""\x80""!");
|
||||||
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
||||||
|
"If you do run into trouble, the ""\x82""tutorial""\x80"" can"\
|
||||||
|
" always be found in the ""\x87""Extras""\x80"" menu later on.");
|
||||||
|
|
||||||
|
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
|
||||||
|
"Either way, MS-1. Even when you move on from this setup,"\
|
||||||
|
" you can always change your ""\x87""Options""\x80"" at any time.");
|
||||||
LinesToDigest.emplace_front(0, Miles_Look_Electric);
|
LinesToDigest.emplace_front(0, Miles_Look_Electric);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -704,8 +754,6 @@ void M_AddGonerLines(void)
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
||||||
"But yes. Perhaps now you have a better appreciation of what "\
|
"But yes. Perhaps now you have a better appreciation of what "\
|
||||||
"we're building here, Metal.");
|
"we're building here, Metal.");
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
|
||||||
"If you need to learn more, you can always come back to the Tutorial later in the ""\x87""Extras""\x80"" menu.");
|
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
|
||||||
"Now, I'm willing to let bygones be bygones.");
|
"Now, I'm willing to let bygones be bygones.");
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
||||||
|
|
@ -1218,6 +1266,123 @@ static void M_GonerDrawer(void)
|
||||||
M_DrawHorizontalMenu();
|
M_DrawHorizontalMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void M_GonerChoiceDrawer(void)
|
||||||
|
{
|
||||||
|
srb2::Draw drawer = srb2::Draw();
|
||||||
|
|
||||||
|
const INT32 lex = (24 + BASEVIDWIDTH/2)/2;
|
||||||
|
|
||||||
|
if (itemOn == GONERCHOICE_TAILS)
|
||||||
|
{
|
||||||
|
drawer
|
||||||
|
.size((BASEVIDWIDTH/2) + 25, BASEVIDHEIGHT)
|
||||||
|
.fill(60);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy((BASEVIDWIDTH/2) + 40 + 1, 28+3)
|
||||||
|
.colormap(SKINCOLOR_ORANGE)
|
||||||
|
.flags(V_FLIP)
|
||||||
|
.patch("MENUPLTR");
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(lex, 28)
|
||||||
|
.font(srb2::Draw::Font::kGamemode)
|
||||||
|
.align(srb2::Draw::Align::kCenter)
|
||||||
|
.text(currentMenu->menuitems[itemOn].text);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(8, 72)
|
||||||
|
.font(srb2::Draw::Font::kThin)
|
||||||
|
.align(srb2::Draw::Align::kLeft)
|
||||||
|
.text(currentMenu->menuitems[itemOn].tooltip);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(lex, 154)
|
||||||
|
.font(srb2::Draw::Font::kFreeplay)
|
||||||
|
.align(srb2::Draw::Align::kCenter)
|
||||||
|
.text("(unlocks 20 )");
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(lex, 154+14)
|
||||||
|
.font(srb2::Draw::Font::kThin)
|
||||||
|
.align(srb2::Draw::Align::kCenter)
|
||||||
|
.flags(V_TRANSLUCENT)
|
||||||
|
.text("+ more surprises to find");
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(lex + 26, 154-4)
|
||||||
|
.patch("UN_CHA00");
|
||||||
|
}
|
||||||
|
else if (itemOn == GONERCHOICE_EGGMAN)
|
||||||
|
{
|
||||||
|
drawer
|
||||||
|
.x((BASEVIDWIDTH/2) - 24)
|
||||||
|
.size((BASEVIDWIDTH/2) + 24, BASEVIDHEIGHT)
|
||||||
|
.fill(44);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy((BASEVIDWIDTH/2) - 40, 28+3)
|
||||||
|
.colormap(SKINCOLOR_RED)
|
||||||
|
.patch("MENUPLTR");
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(BASEVIDWIDTH - lex, 28)
|
||||||
|
.font(srb2::Draw::Font::kGamemode)
|
||||||
|
.align(srb2::Draw::Align::kCenter)
|
||||||
|
.text(currentMenu->menuitems[itemOn].text);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(BASEVIDWIDTH - 8, 72)
|
||||||
|
.font(srb2::Draw::Font::kThin)
|
||||||
|
.align(srb2::Draw::Align::kRight)
|
||||||
|
.text(currentMenu->menuitems[itemOn].tooltip);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(BASEVIDWIDTH - lex, 154)
|
||||||
|
.font(srb2::Draw::Font::kFreeplay)
|
||||||
|
.align(srb2::Draw::Align::kCenter)
|
||||||
|
.text("(unlocks Addons/Online)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Un-highlighteds done this weird way because of GONERCHOICE_NONEBINEY
|
||||||
|
|
||||||
|
if (itemOn != GONERCHOICE_TAILS)
|
||||||
|
{
|
||||||
|
drawer
|
||||||
|
.size(20, BASEVIDHEIGHT)
|
||||||
|
.fill(60);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(25, 39)
|
||||||
|
.font(srb2::Draw::Font::kFreeplay)
|
||||||
|
.align(srb2::Draw::Align::kLeft)
|
||||||
|
.text(currentMenu->menuitems[GONERCHOICE_TAILS].text);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(20 - 3 - (skullAnimCounter/5), 39+6)
|
||||||
|
.patch("CUPARROW");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemOn != GONERCHOICE_EGGMAN)
|
||||||
|
{
|
||||||
|
drawer
|
||||||
|
.x(BASEVIDWIDTH - 20)
|
||||||
|
.size(20, BASEVIDHEIGHT)
|
||||||
|
.fill(44);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy(BASEVIDWIDTH - 25, 39)
|
||||||
|
.font(srb2::Draw::Font::kFreeplay)
|
||||||
|
.align(srb2::Draw::Align::kRight)
|
||||||
|
.text(currentMenu->menuitems[GONERCHOICE_EGGMAN].text);
|
||||||
|
|
||||||
|
drawer
|
||||||
|
.xy((BASEVIDWIDTH - 20 + 3) + (skullAnimCounter/5), 39+6)
|
||||||
|
.flags(V_FLIP)
|
||||||
|
.patch("CUPARROW");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
void M_GonerProfile(INT32 choice)
|
void M_GonerProfile(INT32 choice)
|
||||||
|
|
@ -1245,19 +1410,16 @@ void M_GonerProfile(INT32 choice)
|
||||||
M_GonerResetLooking(GDGONER_PROFILE);
|
M_GonerResetLooking(GDGONER_PROFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void M_GonerSurveyResponse(INT32 ch)
|
static void M_GonerTutorialResponse(INT32 ch)
|
||||||
{
|
{
|
||||||
if (ch != MA_YES)
|
if (ch != MA_YES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gamedata->gonerlevel < GDGONER_OUTRO)
|
M_GonerTutorial(0);
|
||||||
gamedata->gonerlevel = GDGONER_OUTRO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_GonerTutorial(INT32 choice)
|
void M_GonerChoice(INT32 choice)
|
||||||
{
|
{
|
||||||
(void)choice;
|
|
||||||
|
|
||||||
if (cv_currprofile.value == -1)
|
if (cv_currprofile.value == -1)
|
||||||
{
|
{
|
||||||
const INT32 maxp = PR_GetNumProfiles();
|
const INT32 maxp = PR_GetNumProfiles();
|
||||||
|
|
@ -1270,6 +1432,43 @@ void M_GonerTutorial(INT32 choice)
|
||||||
PR_ApplyProfile(profilen, 0);
|
PR_ApplyProfile(profilen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gamedata->gonerlevel >= GDGONER_OUTRO)
|
||||||
|
{
|
||||||
|
M_StartMessage("First Boot Tutorial",
|
||||||
|
"You've already played the Tutorial! Do you want to see it again?",
|
||||||
|
&M_GonerTutorialResponse, MM_YESNO, "I'd love to", "Not right now");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
M_SetupNextMenu(&MAIN_GonerChoiceDef, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void M_GonerSurveyResponse(INT32 ch)
|
||||||
|
{
|
||||||
|
if (ch != MA_YES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gamedata->gonerlevel < GDGONER_OUTRO)
|
||||||
|
gamedata->gonerlevel = GDGONER_OUTRO;
|
||||||
|
|
||||||
|
if (currentMenu == &MAIN_GonerChoiceDef)
|
||||||
|
M_GoBack(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void M_GonerSurvey(INT32 choice)
|
||||||
|
{
|
||||||
|
(void)choice;
|
||||||
|
|
||||||
|
// The game is incapable of progression, but I can't bring myself to put an I_Error here.
|
||||||
|
M_StartMessage("First Boot Error",
|
||||||
|
"YOU ACCEPT EVERYTHING THAT\nWILL HAPPEN FROM NOW ON.",
|
||||||
|
&M_GonerSurveyResponse, MM_YESNO, "I agree", "Cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_GonerTutorial(INT32 choice)
|
||||||
|
{
|
||||||
|
(void)choice;
|
||||||
|
|
||||||
// Please also see M_LevelSelectInit as called in extras-1.c
|
// Please also see M_LevelSelectInit as called in extras-1.c
|
||||||
levellist.netgame = false;
|
levellist.netgame = false;
|
||||||
levellist.canqueue = false;
|
levellist.canqueue = false;
|
||||||
|
|
@ -1279,19 +1478,58 @@ void M_GonerTutorial(INT32 choice)
|
||||||
|
|
||||||
if (!M_LevelListFromGametype(GT_TUTORIAL) && gamedata->gonerlevel < GDGONER_OUTRO)
|
if (!M_LevelListFromGametype(GT_TUTORIAL) && gamedata->gonerlevel < GDGONER_OUTRO)
|
||||||
{
|
{
|
||||||
// The game is incapable of progression, but I can't bring myself to put an I_Error here.
|
M_GonerSurvey(0);
|
||||||
M_StartMessage("Agreement",
|
return;
|
||||||
"YOU ACCEPT EVERYTHING THAT WILL HAPPEN FROM NOW ON.",
|
|
||||||
&M_GonerSurveyResponse, MM_YESNO, "I agree", "Cancel");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M_GonerPlayground(INT32 choice)
|
||||||
|
{
|
||||||
|
(void)choice;
|
||||||
|
|
||||||
|
UINT16 playgroundmap = NEXTMAP_INVALID;
|
||||||
|
if (tutorialplaygroundmap)
|
||||||
|
playgroundmap = G_MapNumber(tutorialplaygroundmap);
|
||||||
|
|
||||||
|
if (playgroundmap >= nummapheaders)
|
||||||
|
{
|
||||||
|
M_GonerSurvey(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplayer = true;
|
||||||
|
|
||||||
|
M_MenuToLevelPreamble(0, false);
|
||||||
|
|
||||||
|
D_MapChange(
|
||||||
|
playgroundmap+1,
|
||||||
|
GT_TUTORIAL,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
M_ClearMenus(true);
|
||||||
|
restoreMenu = NULL; // Playground Hack
|
||||||
|
|
||||||
|
// need to do all this here because it will skip returning to goner and there are circumstances (game close) where DoCompleted won't be called
|
||||||
|
M_GonerResetText();
|
||||||
|
gamedata->gonerlevel = GDGONER_DONE;
|
||||||
|
gamedata->playgroundroute = true;
|
||||||
|
gamedata->deferredsave = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void M_GonerConclude(INT32 choice)
|
static void M_GonerConclude(INT32 choice)
|
||||||
{
|
{
|
||||||
(void)choice;
|
(void)choice;
|
||||||
|
|
||||||
gamedata->gonerlevel = GDGONER_DONE;
|
gamedata->gonerlevel = GDGONER_DONE;
|
||||||
|
|
||||||
|
if (gamedata->chaokeys < 20)
|
||||||
|
gamedata->chaokeys = 20;
|
||||||
|
|
||||||
F_StartIntro();
|
F_StartIntro();
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
M_GonerResetText();
|
M_GonerResetText();
|
||||||
|
|
@ -1380,3 +1618,13 @@ static boolean M_GonerInputs(INT32 ch)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M_GonerResetText(void)
|
||||||
|
{
|
||||||
|
goner_typewriter.ClearText();
|
||||||
|
LinesToDigest.clear();
|
||||||
|
LinesOutput.clear();
|
||||||
|
|
||||||
|
goner_scroll = 0;
|
||||||
|
goner_scrollend = -1;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue