Goner Setup: Cook 2

- More dialogue
- Restrict access to your choices based on your progress through the Goner Setup.
- Save progress through the setup to gamedata
    - Resets to beginning when Challenges is cleared
- Passwords
    - Only permit the password entry in like the first two seconds
        - Preemptively disarms potentially annoying people in stream chats
    - Make wrongwarp also quit the game on exit instead of returning to the title screen
    - Add GDQ cheats
        - `savetheanimals`
        - `savetheframes`
        - Both do practically the same thing, with slightly modified dialogue.
            - Skips all of the normal dialogue.
            - Performing a social experiment on anyone who might stream this game at a charity event. :)
This commit is contained in:
toaster 2023-12-03 22:31:45 +00:00
parent f5566ff8c4
commit e91115a8fa
9 changed files with 423 additions and 76 deletions

View file

@ -4553,6 +4553,8 @@ typedef enum
GDEVER_KEYMAJORSKIP = 1<<5,
GDEVER_TUTORIALSKIP = 1<<6,
GDEVER_ENTERTUTSKIP = 1<<7,
// --- Free up to 1<<23 --- //
GDEVER_GONERSHIFT = 24, // nothing above this
} gdeverdone_t;
static const char *G_GameDataFolder(void)
@ -4694,6 +4696,8 @@ void G_LoadGameData(void)
gamedata->majorkeyskipattempted = !!(everflags & GDEVER_KEYMAJORSKIP);
gamedata->finishedtutorialchallenge = !!(everflags & GDEVER_TUTORIALSKIP);
gamedata->enteredtutorialchallenge = !!(everflags & GDEVER_ENTERTUTSKIP);
gamedata->gonerlevel = everflags>>GDEVER_GONERSHIFT;
}
else
{
@ -5371,7 +5375,7 @@ void G_SaveGameData(void)
WRITEUINT16(save.p, gamedata->chaokeys); // 2
{
UINT32 everflags = 0;
UINT32 everflags = (gamedata->gonerlevel<<GDEVER_GONERSHIFT);
if (gamedata->everloadedaddon)
everflags |= GDEVER_ADDON;

View file

@ -206,6 +206,9 @@ extern menu_t MAIN_GonerDef;
void M_GonerTick(void);
void M_GonerProfile(INT32 choice);
void M_GonerTutorial(INT32 choice);
void M_GonerResetLooking(int type);
void M_GonerCheckLooking(void);
void M_GonerGDQ(boolean opinion);
extern menuitem_t PLAY_CharSelect[];
extern menu_t PLAY_CharSelectDef;

View file

@ -1156,8 +1156,8 @@ void M_DrawHorizontalMenu(void)
V_DrawCharacter((BASEVIDWIDTH + width)/2 - 10 + (skullAnimCounter/5), y,
'\x1D' | highlightflags, false); // right arrow
x = (BASEVIDWIDTH - 8*(currentMenu->numitems-1))/2;
for (i = 0; i < currentMenu->numitems; i++, x += 8)
x = (BASEVIDWIDTH - 8*(currentMenu->extra2-1))/2;
for (i = 0; i < currentMenu->extra2; i++, x += 8)
{
if (i == itemOn)
{
@ -1165,7 +1165,9 @@ void M_DrawHorizontalMenu(void)
}
else
{
V_DrawFill(x-1, y + 16, 2, 2, 16);
V_DrawFill(x-1, y + 16, 2, 2,
(i >= currentMenu->numitems) ? 20 : 10
);
}
}
}

View file

@ -741,8 +741,10 @@ void M_GoBack(INT32 choice)
M_SetupNextMenu(currentMenu->prevMenu, false);
}
else
else if (M_GameTrulyStarted())
M_ClearMenus(true);
else // No returning to the title screen.
M_QuitSRB2(-1);
S_StartSound(NULL, sfx_s3k5b);
}

View file

@ -134,6 +134,20 @@ static UINT8 cheatf_wrongwarp(void)
return 1;
}
static UINT8 cheatf_savetheanimals(void)
{
M_GonerGDQ(true);
return 1;
}
static UINT8 cheatf_savetheframes(void)
{
M_GonerGDQ(false);
return 1;
}
#ifdef DEVELOP
static UINT8 cheatf_devmode(void)
{
@ -179,6 +193,16 @@ static cheatseq_t cheat_wrongwarp = {
(UINT8[]){ SCRAMBLE('b'), SCRAMBLE('a'), SCRAMBLE('n'), SCRAMBLE('a'), SCRAMBLE('n'), SCRAMBLE('a'), 0xff }
};
static cheatseq_t cheat_savetheanimals = {
NULL, cheatf_savetheanimals,
(UINT8[]){ SCRAMBLE('s'), SCRAMBLE('a'), SCRAMBLE('v'), SCRAMBLE('e'), SCRAMBLE('t'), SCRAMBLE('h'), SCRAMBLE('e'), SCRAMBLE('a'), SCRAMBLE('n'), SCRAMBLE('i'), SCRAMBLE('m'), SCRAMBLE('a'), SCRAMBLE('l'), SCRAMBLE('s'), 0xff }
};
static cheatseq_t cheat_savetheframes = {
NULL, cheatf_savetheframes,
(UINT8[]){ SCRAMBLE('s'), SCRAMBLE('a'), SCRAMBLE('v'), SCRAMBLE('e'), SCRAMBLE('t'), SCRAMBLE('h'), SCRAMBLE('e'), SCRAMBLE('f'), SCRAMBLE('r'), SCRAMBLE('a'), SCRAMBLE('m'), SCRAMBLE('e'), SCRAMBLE('s'), 0xff }
};
#ifdef DEVELOP
static cheatseq_t cheat_devmode = {
NULL, cheatf_devmode,
@ -190,6 +214,8 @@ cheatseq_t *cheatseqlist[] =
{
&cheat_warp,
&cheat_wrongwarp,
&cheat_savetheanimals,
&cheat_savetheframes,
#ifdef DEVELOP
&cheat_devmode,
#endif

View file

@ -730,6 +730,8 @@ void M_ClearSecrets(void)
gamedata->chaokeys = GDINIT_CHAOKEYS;
gamedata->prisoneggstothispickup = GDINIT_PRISONSTOPRIZE;
gamedata->gonerlevel = GDGONER_INIT;
}
// For lack of a better idea on where to put this

View file

@ -289,6 +289,16 @@ typedef enum {
#define GDINIT_CHAOKEYS 3 // Start with 3 Chao Keys !!
#define GDINIT_PRISONSTOPRIZE 30 // 30 Prison Eggs to your [Wild Prize] !!
typedef enum {
GDGONER_INIT = 0,
GDGONER_INTRO,
GDGONER_VIDEO,
GDGONER_SOUND,
GDGONER_PROFILE,
GDGONER_TUTORIAL,
GDGONER_DONE,
} gdgoner_t;
typedef enum {
GDGT_RACE,
GDGT_BATTLE,
@ -370,6 +380,8 @@ struct gamedata_t
boolean finishedtutorialchallenge;
gdmusic_t musicstate;
UINT8 gonerlevel;
// BACKWARDS COMPAT ASSIST
boolean importprofilewins;
};

View file

@ -2,7 +2,10 @@
/// \brief The Goner Setup.
#include "../k_menu.h"
#include "../m_cond.h"
#include "../r_skins.h"
#include "../s_sound.h"
#include "../p_local.h" // P_AutoPause
#include "../st_stuff.h" // faceprefix
#include "../v_draw.hpp"
#include "../k_dialogue.hpp"
@ -11,41 +14,36 @@
menuitem_t MAIN_Goner[] =
{
{IT_STRING | IT_CVAR | IT_CV_STRING, "Password",
{IT_STRING | IT_CVAR | IT_CV_STRING, ". . .",
"ATTEMPT ADMINISTRATOR ACCESS.", NULL,
{.cvar = &cv_dummyextraspassword}, 0, 0},
{IT_STRING | IT_CALL, "Quit",
"CONCLUDE OBSERVATIONS NOW.", NULL,
{.routine = M_QuitSRB2}, 0, 0},
{IT_STRING | IT_CALL, "Video Options",
{IT_STRING | IT_CALL, "VIDEO OPTIONS",
"CONFIGURE OCULAR PATHWAYS.", NULL,
{.routine = M_VideoOptions}, 0, 0},
{IT_STRING | IT_CALL, "Sound Options",
{IT_STRING | IT_CALL, "SOUND OPTIONS",
"CALIBRATE AURAL DATASTREAM.", NULL,
{.routine = M_SoundOptions}, 0, 0},
{IT_STRING | IT_CALL, "Profile Setup",
{IT_STRING | IT_CALL, "PROFILE SETUP",
"ASSIGN VEHICLE INPUTS.", NULL,
{.routine = M_GonerProfile}, 0, 0},
{IT_STRING | IT_CALL, "Begin Tutorial",
{IT_STRING | IT_CALL, "BEGIN TUTORIAL",
"PREPARE FOR INTEGRATION.", NULL,
{.routine = M_GonerTutorial}, 0, 0},
};
static boolean M_GonerInputs(INT32 ch);
static void M_GonerDrawer(void);
menu_t MAIN_GonerDef = {
sizeof (MAIN_Goner) / sizeof (menuitem_t),
1, // Intentionally not the sizeof calc
NULL,
0,
MAIN_Goner,
32, 160,
0, 0,
26, 160,
0, sizeof (MAIN_Goner) / sizeof (menuitem_t), // extra2 is final width
MBF_UD_LR_FLIPPED,
"_GONER",
0, 0,
@ -53,7 +51,7 @@ menu_t MAIN_GonerDef = {
M_GonerTick,
NULL,
NULL,
M_GonerInputs,
NULL,
};
namespace
@ -154,63 +152,310 @@ public:
std::forward_list<GonerChatLine> LinesToDigest;
std::forward_list<GonerChatLine> LinesOutput;
int goner_levelworking = GDGONER_INIT;
bool goner_nicetry = false;
bool goner_gdq = false;
void M_AddGonerLines(void)
{
SRB2_ASSERT(LinesToDigest.empty());
auto _ = srb2::finally([]() { LinesToDigest.reverse(); });
static bool leftoff = false;
goner_delay = TICRATE;
// This one always plays, so it checks the levelworking instead of gamedata.
if (goner_levelworking == GDGONER_INTRO)
{
if (!goner_nicetry)
{
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Metal Sonic. Are you online?");
}
leftoff = (goner_levelworking < gamedata->gonerlevel-1);
if (leftoff)
{
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"It must have run into some sort of error...");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Don't worry, your settings so far are saved. "\
"Let's pick up where we left off.");
// the -1 guarantees that one will be (re)played
goner_levelworking = gamedata->gonerlevel-1;
}
return;
}
switch (gamedata->gonerlevel)
{
case GDGONER_VIDEO:
{
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
"Take a close look, Miles. Moments ago he was at my throat! "\
"Now he's docile as can be on that operating table.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"I don't feel very safe!");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/4,
"But its programming is definitely locked down...");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"You've given me quite the headache, Metal. "\
"Thankfully, Tails caught you in the act.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/5,
"Wait, I'm getting weird readings over the network.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Metal Sonic is the unit labeled \"MS-1\", right?");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE,
"The ""\x87""viewport""\x80"" and ""\x87""audio""\x80"" "\
"config looks like it got messed up.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"So you're right. I wonder if it has anything to do with that outburst.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Alright, Metal! I don't remember your specifications offhand. "\
"First things first, go ahead and set up your "\
"\x87""Video Options""\x80"" yourself.");
break;
}
case GDGONER_SOUND:
{
if (!leftoff)
{
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Ah, you can see us now. Good.");
}
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Now, calibrate your ""\x87""Sound Options""\x80"".");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"You always make your stuff so loud by default, Eggman. It might need a moment.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Not Metal! He always needed to be stealthy. But go on, set your sliders.");
break;
}
case GDGONER_PROFILE:
{
if (!leftoff)
{
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/2,
"Oh! Let's tell Metal about our project!");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Of course. I and my lab assista-");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Lab PARTNER.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Irrelevant!");
}
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/4,
"We made a machine together, Tails and I. "\
"It's called a \"""\x82""Ring Racer""\x80""\".");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
"At its core, it is designed to utilise the boundless potential "\
"of the ""\x83""High Voltage Ring""\x80"".");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE,
"We made this special Ring by combining the power of tens of "\
"thousands of ordinary ""\x82""Rings""\x80"".");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/2,
"We recorded some of our testing for you, MS-1. Maybe your neural "\
"network could train on some less violent data for once.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/4,
"While that's uploading, why don't you set up your ""\x87""Profile Card""\x80""?");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Yes! That's one of my contributions.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"(I'm too used to my systems being designed for me alone...)");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Every racer carries one, to contain their personal settings.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"It helps get your ""\x87""controls""\x80"" set up nice and quickly, "\
"when starting your vehicle.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"And it helps track your wins, too.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
"Bragging rights. My idea!");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/2,
"You can make the name on there anything you want.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/2,
"Mine says \"Nine Tails\". That's the name of my original character! "\
"He's like me if I never met my ""\x84""brother""\x80"". He'd have to become stronger "\
"with robotics, and kind of mean and cool to protect himself...");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
"Mine says \"Robotnik\". You can't beat a classic.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Go on, do your ""\x87""Profile Setup""\x80""!");
break;
}
case GDGONER_TUTORIAL:
case GDGONER_DONE: // maybe we could do something different for this eventually
{
if (!leftoff)
{
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
"...right, now that that's sorted. How's the upload going?");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Just finished.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Perfect.");
}
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Now, Metal... it's important you pay attention.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/5,
"It's time to ""\x87""begin your Tutorial""\x80""!");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"That's a lot to get through. Good luck, MS-1!");
break;
}
default:
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"I am error");
}
leftoff = false;
}
gdgoner_t goner_lasttypelooking = GDGONER_INIT;
tic_t goner_youactuallylooked = 0;
void M_GonerRailroad(bool set)
{
INT16 destsize = std::min(
static_cast<INT16>(
(set ? 2 : 1) // Quit + options + maybe 1 for extra access
+ std::max(0, gamedata->gonerlevel - GDGONER_VIDEO)
),
currentMenu->extra2);
currentMenu->numitems = destsize;
if (!set)
return;
itemOn = destsize-1;
S_StartSound(NULL, sfx_s3k5b);
}
void M_GonerHidePassword(void)
{
if (currentMenu->menuitems[0].mvar2)
return;
currentMenu->menuitems[0] =
{IT_STRING | IT_CALL, "EXIT PROGRAM",
"CONCLUDE OBSERVATIONS NOW.", NULL,
{.routine = M_QuitSRB2}, 0, 1};
}
}; // namespace
void M_GonerResetLooking(int type)
{
if (goner_youactuallylooked > 2*TICRATE
&& goner_lasttypelooking == gamedata->gonerlevel)
{
if (goner_levelworking > gamedata->gonerlevel)
goner_levelworking--;
gamedata->gonerlevel++;
LinesToDigest.clear();
}
goner_lasttypelooking = static_cast<gdgoner_t>(type);
goner_youactuallylooked = 0;
}
void M_GonerCheckLooking(void)
{
if (goner_lasttypelooking != gamedata->gonerlevel)
return;
goner_youactuallylooked++;
}
void M_GonerTick(void)
{
static bool speakersinit = false;
if (!speakersinit)
{
goner_delay = TICRATE;
static bool first = true;
if (goner_levelworking == GDGONER_INIT)
{
first = true;
// Init.
goner_speakers[GONERSPEAKER_EGGMAN] = GonerSpeaker("eggman", 0);
goner_speakers[GONERSPEAKER_TAILS] = GonerSpeaker("tails", 12);
}
else if (gamedata->gonerlevel == GDGONER_INIT)
{
first = true; // a lie, but only slightly...
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE,
"Metal Sonic. Are you online?");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
"Take a close look, Miles. Moments ago he was at my throat!\
Now he's docile as can be on that operating table.");
// Handle rewinding if you clear your gamedata.
goner_typewriter.ClearText();
LinesToDigest.clear();
LinesOutput.clear();
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"I don't feel very safe!");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/4,
"But its programming is definitely locked down...");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"You've given me quite the headache, Metal.\
Thankfully, Tails caught you in the act.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/5,
"Wait, I'm getting weird readings over the network.");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Metal Sonic is the unit labeled \"MS1\", right?");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE,
"The ""\x87""viewport""\x80"" and ""\x87""audio""\x80"" config looks like it got messed up.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"So you're right. I wonder if it has anything to do with that outburst.");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"Alright, Metal! I don't remember your specifications offhand. First things first, go ahead and set up your ""\x87""Video Options""\x80"" yourself.");
LinesToDigest.reverse();
speakersinit = true;
goner_levelworking = GDGONER_INIT;
}
if (menutyping.active == false && cv_dummyextraspassword.string[0] != '\0')
{
// Challenges are not interpreted at this stage.
// See M_ExtraTick for the full behaviour.
M_GonerResetLooking(GDGONER_INIT);
cht_Interpret(cv_dummyextraspassword.string);
CV_StealthSet(&cv_dummyextraspassword, "");
if (first)
{
first = false;
if (gamedata->gonerlevel < GDGONER_INTRO)
gamedata->gonerlevel = GDGONER_INTRO;
M_GonerRailroad(false);
}
goner_typewriter.WriteText();
if (menutyping.active || menumessage.active || P_AutoPause())
return;
if (cv_dummyextraspassword.string[0] != '\0')
{
// Challenges are not interpreted at this stage.
// See M_ExtraTick for the full behaviour.
if (!cht_Interpret(cv_dummyextraspassword.string))
{
goner_delay = 0;
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE,
"Aha! Nice try. You're tricky enough WITHOUT admin access, thank you.");
M_GonerHidePassword();
goner_nicetry = true;
}
CV_StealthSet(&cv_dummyextraspassword, "");
}
if (goner_typewriter.textDone)
{
if (!LinesOutput.empty())
M_GonerHidePassword();
if (goner_delay > 0)
goner_delay--;
else if (!LinesToDigest.empty())
@ -223,6 +468,21 @@ void M_GonerTick(void)
LinesOutput.push_front(line);
LinesToDigest.pop_front();
}
else if (goner_levelworking <= gamedata->gonerlevel)
{
if (goner_levelworking == GDGONER_INTRO && gamedata->gonerlevel < GDGONER_VIDEO)
gamedata->gonerlevel = GDGONER_VIDEO;
if (++goner_levelworking > gamedata->gonerlevel)
{
// We've reached the end of the goner text for now.
M_GonerRailroad(true);
}
else if (!goner_gdq)
{
M_AddGonerLines();
}
}
}
}
@ -240,10 +500,15 @@ static void M_GonerDrawer(void)
float newy = BASEVIDHEIGHT/2 + (3*12);
boolean first = true;
int lastspeaker = MAXGONERSPEAKERS;
for (auto & element : LinesOutput)
{
INT32 flags = V_TRANSLUCENT;
std::string text;
if (newy < 0) break;
if (first)
{
text = goner_typewriter.text;
@ -255,9 +520,12 @@ static void M_GonerDrawer(void)
{
text = element.dialogue;
newy -= element.value*12;
if (lastspeaker != element.speaker)
newy -= 2;
}
if (newy < 0) break;
lastspeaker = element.speaker;
//if (newy > BASEVIDHEIGHT) continue; -- not needed yet
@ -267,18 +535,21 @@ static void M_GonerDrawer(void)
.xy(speaker.offset, newy)
.flags(flags);
int skinID = speaker.GetSkinID();
if (skinID != -1)
{
line
.xy(-16, -2)
.colormap(skinID, static_cast<skincolornum_t>(skins[skinID].prefcolor))
.patch(faceprefix[skinID][FACE_MINIMAP]);
}
line
.font(srb2::Draw::Font::kThin)
.text( text.c_str() );
int skinID = speaker.GetSkinID();
if (skinID != -1)
{
line = line
.xy(-16, -2)
.colormap(skinID, static_cast<skincolornum_t>(skins[skinID].prefcolor));
if (gamedata->gonerlevel > GDGONER_VIDEO)
line.patch(faceprefix[skinID][FACE_MINIMAP]);
else
line.patch("HUHMAP");
}
}
M_DrawHorizontalMenu();
@ -307,6 +578,8 @@ void M_GonerProfile(INT32 choice)
// This will create a new profile if necessary.
M_StartEditProfile(MA_YES);
PR_ApplyProfilePretend(optionsmenu.profilen, 0);
M_GonerResetLooking(GDGONER_PROFILE);
}
void M_GonerTutorial(INT32 choice)
@ -338,19 +611,38 @@ void M_GonerTutorial(INT32 choice)
"YOU ACCEPT EVERYTHING THAT WILL HAPPEN FROM NOW ON.",
&M_QuitResponse, MM_YESNO, "I agree", "Cancel");
}
gamedata->gonerlevel = GDGONER_DONE;
}
static boolean M_GonerInputs(INT32 ch)
void M_GonerGDQ(boolean opinion)
{
const UINT8 pid = 0;
(void)ch;
if (currentMenu != &MAIN_GonerDef)
return;
if (M_MenuBackPressed(pid))
LinesToDigest.clear();
goner_delay = TICRATE/2;
goner_gdq = true;
// The mapping of true/false to each opinion is completely
// arbitrary, and is not a comment on the nature of the Metroid run.
if (opinion) // Save The Animals
{
// No returning to the title screen.
M_QuitSRB2(-1);
return true;
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
"Why wouldn't you save the frames..?");
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
"Don't mind him. Good luck on the run!");
}
else // Save The Frames
{
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, TICRATE/2,
"But what about all the little animals...");
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, 0,
"It's just logical. I know you'll conquer this run.");
}
LinesToDigest.reverse();
return false;
goner_levelworking = GDGONER_TUTORIAL;
gamedata->gonerlevel = GDGONER_DONE;
}

View file

@ -197,6 +197,8 @@ void M_OptionsTick(void)
optionsmenu.fade--;
if (optionsmenu.currcolour != currentMenu->extra1)
M_OptionsChangeBGColour(currentMenu->extra1);
M_GonerCheckLooking();
}
// And one last giggle...
@ -213,12 +215,14 @@ void M_VideoOptions(INT32 choice)
{
(void)choice;
M_OptionsMenuGoto(&OPTIONS_VideoDef);
M_GonerResetLooking(GDGONER_VIDEO);
}
void M_SoundOptions(INT32 choice)
{
(void)choice;
M_OptionsMenuGoto(&OPTIONS_SoundDef);
M_GonerResetLooking(GDGONER_SOUND);
}
boolean M_OptionsInputs(INT32 ch)