mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-05-04 07:52:22 +00:00
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:
parent
f5566ff8c4
commit
e91115a8fa
9 changed files with 423 additions and 76 deletions
|
|
@ -4553,6 +4553,8 @@ typedef enum
|
||||||
GDEVER_KEYMAJORSKIP = 1<<5,
|
GDEVER_KEYMAJORSKIP = 1<<5,
|
||||||
GDEVER_TUTORIALSKIP = 1<<6,
|
GDEVER_TUTORIALSKIP = 1<<6,
|
||||||
GDEVER_ENTERTUTSKIP = 1<<7,
|
GDEVER_ENTERTUTSKIP = 1<<7,
|
||||||
|
// --- Free up to 1<<23 --- //
|
||||||
|
GDEVER_GONERSHIFT = 24, // nothing above this
|
||||||
} gdeverdone_t;
|
} gdeverdone_t;
|
||||||
|
|
||||||
static const char *G_GameDataFolder(void)
|
static const char *G_GameDataFolder(void)
|
||||||
|
|
@ -4694,6 +4696,8 @@ void G_LoadGameData(void)
|
||||||
gamedata->majorkeyskipattempted = !!(everflags & GDEVER_KEYMAJORSKIP);
|
gamedata->majorkeyskipattempted = !!(everflags & GDEVER_KEYMAJORSKIP);
|
||||||
gamedata->finishedtutorialchallenge = !!(everflags & GDEVER_TUTORIALSKIP);
|
gamedata->finishedtutorialchallenge = !!(everflags & GDEVER_TUTORIALSKIP);
|
||||||
gamedata->enteredtutorialchallenge = !!(everflags & GDEVER_ENTERTUTSKIP);
|
gamedata->enteredtutorialchallenge = !!(everflags & GDEVER_ENTERTUTSKIP);
|
||||||
|
|
||||||
|
gamedata->gonerlevel = everflags>>GDEVER_GONERSHIFT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -5371,7 +5375,7 @@ void G_SaveGameData(void)
|
||||||
WRITEUINT16(save.p, gamedata->chaokeys); // 2
|
WRITEUINT16(save.p, gamedata->chaokeys); // 2
|
||||||
|
|
||||||
{
|
{
|
||||||
UINT32 everflags = 0;
|
UINT32 everflags = (gamedata->gonerlevel<<GDEVER_GONERSHIFT);
|
||||||
|
|
||||||
if (gamedata->everloadedaddon)
|
if (gamedata->everloadedaddon)
|
||||||
everflags |= GDEVER_ADDON;
|
everflags |= GDEVER_ADDON;
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,9 @@ extern menu_t MAIN_GonerDef;
|
||||||
void M_GonerTick(void);
|
void M_GonerTick(void);
|
||||||
void M_GonerProfile(INT32 choice);
|
void M_GonerProfile(INT32 choice);
|
||||||
void M_GonerTutorial(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 menuitem_t PLAY_CharSelect[];
|
||||||
extern menu_t PLAY_CharSelectDef;
|
extern menu_t PLAY_CharSelectDef;
|
||||||
|
|
|
||||||
|
|
@ -1156,8 +1156,8 @@ void M_DrawHorizontalMenu(void)
|
||||||
V_DrawCharacter((BASEVIDWIDTH + width)/2 - 10 + (skullAnimCounter/5), y,
|
V_DrawCharacter((BASEVIDWIDTH + width)/2 - 10 + (skullAnimCounter/5), y,
|
||||||
'\x1D' | highlightflags, false); // right arrow
|
'\x1D' | highlightflags, false); // right arrow
|
||||||
|
|
||||||
x = (BASEVIDWIDTH - 8*(currentMenu->numitems-1))/2;
|
x = (BASEVIDWIDTH - 8*(currentMenu->extra2-1))/2;
|
||||||
for (i = 0; i < currentMenu->numitems; i++, x += 8)
|
for (i = 0; i < currentMenu->extra2; i++, x += 8)
|
||||||
{
|
{
|
||||||
if (i == itemOn)
|
if (i == itemOn)
|
||||||
{
|
{
|
||||||
|
|
@ -1165,7 +1165,9 @@ void M_DrawHorizontalMenu(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
V_DrawFill(x-1, y + 16, 2, 2, 16);
|
V_DrawFill(x-1, y + 16, 2, 2,
|
||||||
|
(i >= currentMenu->numitems) ? 20 : 10
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -741,8 +741,10 @@ void M_GoBack(INT32 choice)
|
||||||
|
|
||||||
M_SetupNextMenu(currentMenu->prevMenu, false);
|
M_SetupNextMenu(currentMenu->prevMenu, false);
|
||||||
}
|
}
|
||||||
else
|
else if (M_GameTrulyStarted())
|
||||||
M_ClearMenus(true);
|
M_ClearMenus(true);
|
||||||
|
else // No returning to the title screen.
|
||||||
|
M_QuitSRB2(-1);
|
||||||
|
|
||||||
S_StartSound(NULL, sfx_s3k5b);
|
S_StartSound(NULL, sfx_s3k5b);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,20 @@ static UINT8 cheatf_wrongwarp(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT8 cheatf_savetheanimals(void)
|
||||||
|
{
|
||||||
|
M_GonerGDQ(true);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT8 cheatf_savetheframes(void)
|
||||||
|
{
|
||||||
|
M_GonerGDQ(false);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEVELOP
|
#ifdef DEVELOP
|
||||||
static UINT8 cheatf_devmode(void)
|
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 }
|
(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
|
#ifdef DEVELOP
|
||||||
static cheatseq_t cheat_devmode = {
|
static cheatseq_t cheat_devmode = {
|
||||||
NULL, cheatf_devmode,
|
NULL, cheatf_devmode,
|
||||||
|
|
@ -190,6 +214,8 @@ cheatseq_t *cheatseqlist[] =
|
||||||
{
|
{
|
||||||
&cheat_warp,
|
&cheat_warp,
|
||||||
&cheat_wrongwarp,
|
&cheat_wrongwarp,
|
||||||
|
&cheat_savetheanimals,
|
||||||
|
&cheat_savetheframes,
|
||||||
#ifdef DEVELOP
|
#ifdef DEVELOP
|
||||||
&cheat_devmode,
|
&cheat_devmode,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -730,6 +730,8 @@ void M_ClearSecrets(void)
|
||||||
|
|
||||||
gamedata->chaokeys = GDINIT_CHAOKEYS;
|
gamedata->chaokeys = GDINIT_CHAOKEYS;
|
||||||
gamedata->prisoneggstothispickup = GDINIT_PRISONSTOPRIZE;
|
gamedata->prisoneggstothispickup = GDINIT_PRISONSTOPRIZE;
|
||||||
|
|
||||||
|
gamedata->gonerlevel = GDGONER_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For lack of a better idea on where to put this
|
// For lack of a better idea on where to put this
|
||||||
|
|
|
||||||
12
src/m_cond.h
12
src/m_cond.h
|
|
@ -289,6 +289,16 @@ typedef enum {
|
||||||
#define GDINIT_CHAOKEYS 3 // Start with 3 Chao Keys !!
|
#define GDINIT_CHAOKEYS 3 // Start with 3 Chao Keys !!
|
||||||
#define GDINIT_PRISONSTOPRIZE 30 // 30 Prison Eggs to your [Wild Prize] !!
|
#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 {
|
typedef enum {
|
||||||
GDGT_RACE,
|
GDGT_RACE,
|
||||||
GDGT_BATTLE,
|
GDGT_BATTLE,
|
||||||
|
|
@ -370,6 +380,8 @@ struct gamedata_t
|
||||||
boolean finishedtutorialchallenge;
|
boolean finishedtutorialchallenge;
|
||||||
gdmusic_t musicstate;
|
gdmusic_t musicstate;
|
||||||
|
|
||||||
|
UINT8 gonerlevel;
|
||||||
|
|
||||||
// BACKWARDS COMPAT ASSIST
|
// BACKWARDS COMPAT ASSIST
|
||||||
boolean importprofilewins;
|
boolean importprofilewins;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
/// \brief The Goner Setup.
|
/// \brief The Goner Setup.
|
||||||
|
|
||||||
#include "../k_menu.h"
|
#include "../k_menu.h"
|
||||||
|
#include "../m_cond.h"
|
||||||
#include "../r_skins.h"
|
#include "../r_skins.h"
|
||||||
|
#include "../s_sound.h"
|
||||||
|
#include "../p_local.h" // P_AutoPause
|
||||||
#include "../st_stuff.h" // faceprefix
|
#include "../st_stuff.h" // faceprefix
|
||||||
#include "../v_draw.hpp"
|
#include "../v_draw.hpp"
|
||||||
#include "../k_dialogue.hpp"
|
#include "../k_dialogue.hpp"
|
||||||
|
|
@ -11,41 +14,36 @@
|
||||||
|
|
||||||
menuitem_t MAIN_Goner[] =
|
menuitem_t MAIN_Goner[] =
|
||||||
{
|
{
|
||||||
{IT_STRING | IT_CVAR | IT_CV_STRING, "Password",
|
{IT_STRING | IT_CVAR | IT_CV_STRING, ". . .",
|
||||||
"ATTEMPT ADMINISTRATOR ACCESS.", NULL,
|
"ATTEMPT ADMINISTRATOR ACCESS.", NULL,
|
||||||
{.cvar = &cv_dummyextraspassword}, 0, 0},
|
{.cvar = &cv_dummyextraspassword}, 0, 0},
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "Quit",
|
{IT_STRING | IT_CALL, "VIDEO OPTIONS",
|
||||||
"CONCLUDE OBSERVATIONS NOW.", NULL,
|
|
||||||
{.routine = M_QuitSRB2}, 0, 0},
|
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "Video Options",
|
|
||||||
"CONFIGURE OCULAR PATHWAYS.", NULL,
|
"CONFIGURE OCULAR PATHWAYS.", NULL,
|
||||||
{.routine = M_VideoOptions}, 0, 0},
|
{.routine = M_VideoOptions}, 0, 0},
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "Sound Options",
|
{IT_STRING | IT_CALL, "SOUND OPTIONS",
|
||||||
"CALIBRATE AURAL DATASTREAM.", NULL,
|
"CALIBRATE AURAL DATASTREAM.", NULL,
|
||||||
{.routine = M_SoundOptions}, 0, 0},
|
{.routine = M_SoundOptions}, 0, 0},
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, "Profile Setup",
|
{IT_STRING | IT_CALL, "PROFILE SETUP",
|
||||||
"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, "BEGIN TUTORIAL",
|
||||||
"PREPARE FOR INTEGRATION.", NULL,
|
"PREPARE FOR INTEGRATION.", NULL,
|
||||||
{.routine = M_GonerTutorial}, 0, 0},
|
{.routine = M_GonerTutorial}, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static boolean M_GonerInputs(INT32 ch);
|
|
||||||
static void M_GonerDrawer(void);
|
static void M_GonerDrawer(void);
|
||||||
|
|
||||||
menu_t MAIN_GonerDef = {
|
menu_t MAIN_GonerDef = {
|
||||||
sizeof (MAIN_Goner) / sizeof (menuitem_t),
|
1, // Intentionally not the sizeof calc
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
MAIN_Goner,
|
MAIN_Goner,
|
||||||
32, 160,
|
26, 160,
|
||||||
0, 0,
|
0, sizeof (MAIN_Goner) / sizeof (menuitem_t), // extra2 is final width
|
||||||
MBF_UD_LR_FLIPPED,
|
MBF_UD_LR_FLIPPED,
|
||||||
"_GONER",
|
"_GONER",
|
||||||
0, 0,
|
0, 0,
|
||||||
|
|
@ -53,7 +51,7 @@ menu_t MAIN_GonerDef = {
|
||||||
M_GonerTick,
|
M_GonerTick,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
M_GonerInputs,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|
@ -154,63 +152,310 @@ public:
|
||||||
std::forward_list<GonerChatLine> LinesToDigest;
|
std::forward_list<GonerChatLine> LinesToDigest;
|
||||||
std::forward_list<GonerChatLine> LinesOutput;
|
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
|
}; // 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)
|
void M_GonerTick(void)
|
||||||
{
|
{
|
||||||
static bool speakersinit = false;
|
static bool first = true;
|
||||||
if (!speakersinit)
|
|
||||||
{
|
|
||||||
goner_delay = TICRATE;
|
|
||||||
|
|
||||||
|
if (goner_levelworking == GDGONER_INIT)
|
||||||
|
{
|
||||||
|
first = true;
|
||||||
|
|
||||||
|
// Init.
|
||||||
goner_speakers[GONERSPEAKER_EGGMAN] = GonerSpeaker("eggman", 0);
|
goner_speakers[GONERSPEAKER_EGGMAN] = GonerSpeaker("eggman", 0);
|
||||||
goner_speakers[GONERSPEAKER_TAILS] = GonerSpeaker("tails", 12);
|
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,
|
// Handle rewinding if you clear your gamedata.
|
||||||
"Metal Sonic. Are you online?");
|
goner_typewriter.ClearText();
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
LinesToDigest.clear();
|
||||||
"Take a close look, Miles. Moments ago he was at my throat!\
|
LinesOutput.clear();
|
||||||
Now he's docile as can be on that operating table.");
|
|
||||||
|
|
||||||
LinesToDigest.emplace_front(GONERSPEAKER_TAILS, 0,
|
goner_levelworking = GDGONER_INIT;
|
||||||
"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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menutyping.active == false && cv_dummyextraspassword.string[0] != '\0')
|
M_GonerResetLooking(GDGONER_INIT);
|
||||||
{
|
|
||||||
// Challenges are not interpreted at this stage.
|
|
||||||
// See M_ExtraTick for the full behaviour.
|
|
||||||
|
|
||||||
cht_Interpret(cv_dummyextraspassword.string);
|
if (first)
|
||||||
CV_StealthSet(&cv_dummyextraspassword, "");
|
{
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if (gamedata->gonerlevel < GDGONER_INTRO)
|
||||||
|
gamedata->gonerlevel = GDGONER_INTRO;
|
||||||
|
|
||||||
|
M_GonerRailroad(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
goner_typewriter.WriteText();
|
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 (goner_typewriter.textDone)
|
||||||
{
|
{
|
||||||
|
if (!LinesOutput.empty())
|
||||||
|
M_GonerHidePassword();
|
||||||
if (goner_delay > 0)
|
if (goner_delay > 0)
|
||||||
goner_delay--;
|
goner_delay--;
|
||||||
else if (!LinesToDigest.empty())
|
else if (!LinesToDigest.empty())
|
||||||
|
|
@ -223,6 +468,21 @@ void M_GonerTick(void)
|
||||||
LinesOutput.push_front(line);
|
LinesOutput.push_front(line);
|
||||||
LinesToDigest.pop_front();
|
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);
|
float newy = BASEVIDHEIGHT/2 + (3*12);
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
|
||||||
|
int lastspeaker = MAXGONERSPEAKERS;
|
||||||
|
|
||||||
for (auto & element : LinesOutput)
|
for (auto & element : LinesOutput)
|
||||||
{
|
{
|
||||||
INT32 flags = V_TRANSLUCENT;
|
INT32 flags = V_TRANSLUCENT;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
|
if (newy < 0) break;
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
text = goner_typewriter.text;
|
text = goner_typewriter.text;
|
||||||
|
|
@ -255,9 +520,12 @@ static void M_GonerDrawer(void)
|
||||||
{
|
{
|
||||||
text = element.dialogue;
|
text = element.dialogue;
|
||||||
newy -= element.value*12;
|
newy -= element.value*12;
|
||||||
|
|
||||||
|
if (lastspeaker != element.speaker)
|
||||||
|
newy -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newy < 0) break;
|
lastspeaker = element.speaker;
|
||||||
|
|
||||||
//if (newy > BASEVIDHEIGHT) continue; -- not needed yet
|
//if (newy > BASEVIDHEIGHT) continue; -- not needed yet
|
||||||
|
|
||||||
|
|
@ -267,18 +535,21 @@ static void M_GonerDrawer(void)
|
||||||
.xy(speaker.offset, newy)
|
.xy(speaker.offset, newy)
|
||||||
.flags(flags);
|
.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
|
line
|
||||||
.font(srb2::Draw::Font::kThin)
|
.font(srb2::Draw::Font::kThin)
|
||||||
.text( text.c_str() );
|
.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();
|
M_DrawHorizontalMenu();
|
||||||
|
|
@ -307,6 +578,8 @@ void M_GonerProfile(INT32 choice)
|
||||||
// This will create a new profile if necessary.
|
// This will create a new profile if necessary.
|
||||||
M_StartEditProfile(MA_YES);
|
M_StartEditProfile(MA_YES);
|
||||||
PR_ApplyProfilePretend(optionsmenu.profilen, 0);
|
PR_ApplyProfilePretend(optionsmenu.profilen, 0);
|
||||||
|
|
||||||
|
M_GonerResetLooking(GDGONER_PROFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_GonerTutorial(INT32 choice)
|
void M_GonerTutorial(INT32 choice)
|
||||||
|
|
@ -338,19 +611,38 @@ void M_GonerTutorial(INT32 choice)
|
||||||
"YOU ACCEPT EVERYTHING THAT WILL HAPPEN FROM NOW ON.",
|
"YOU ACCEPT EVERYTHING THAT WILL HAPPEN FROM NOW ON.",
|
||||||
&M_QuitResponse, MM_YESNO, "I agree", "Cancel");
|
&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;
|
if (currentMenu != &MAIN_GonerDef)
|
||||||
(void)ch;
|
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.
|
LinesToDigest.emplace_front(GONERSPEAKER_EGGMAN, TICRATE/2,
|
||||||
M_QuitSRB2(-1);
|
"Why wouldn't you save the frames..?");
|
||||||
return true;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,8 @@ void M_OptionsTick(void)
|
||||||
optionsmenu.fade--;
|
optionsmenu.fade--;
|
||||||
if (optionsmenu.currcolour != currentMenu->extra1)
|
if (optionsmenu.currcolour != currentMenu->extra1)
|
||||||
M_OptionsChangeBGColour(currentMenu->extra1);
|
M_OptionsChangeBGColour(currentMenu->extra1);
|
||||||
|
|
||||||
|
M_GonerCheckLooking();
|
||||||
}
|
}
|
||||||
|
|
||||||
// And one last giggle...
|
// And one last giggle...
|
||||||
|
|
@ -213,12 +215,14 @@ void M_VideoOptions(INT32 choice)
|
||||||
{
|
{
|
||||||
(void)choice;
|
(void)choice;
|
||||||
M_OptionsMenuGoto(&OPTIONS_VideoDef);
|
M_OptionsMenuGoto(&OPTIONS_VideoDef);
|
||||||
|
M_GonerResetLooking(GDGONER_VIDEO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_SoundOptions(INT32 choice)
|
void M_SoundOptions(INT32 choice)
|
||||||
{
|
{
|
||||||
(void)choice;
|
(void)choice;
|
||||||
M_OptionsMenuGoto(&OPTIONS_SoundDef);
|
M_OptionsMenuGoto(&OPTIONS_SoundDef);
|
||||||
|
M_GonerResetLooking(GDGONER_SOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean M_OptionsInputs(INT32 ch)
|
boolean M_OptionsInputs(INT32 ch)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue