mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'tutorial-access' into 'master'
Tutorial access See merge request KartKrew/Kart!1102
This commit is contained in:
commit
bbf2fc0b5f
21 changed files with 287 additions and 131 deletions
|
|
@ -1047,9 +1047,6 @@ void D_ClearState(void)
|
|||
if (rendermode != render_none)
|
||||
V_SetPaletteLump("PLAYPAL");
|
||||
|
||||
// The title screen is obviously not a tutorial! (Unless I'm mistaken)
|
||||
tutorialmode = false;
|
||||
|
||||
cursongcredit.def = NULL;
|
||||
S_StopSounds();
|
||||
|
||||
|
|
|
|||
|
|
@ -3014,8 +3014,6 @@ static void Command_Map_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
tutorialmode = false; // warping takes us out of tutorial mode
|
||||
|
||||
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, fromlevelselect);
|
||||
|
||||
Z_Free(realmapname);
|
||||
|
|
|
|||
|
|
@ -1122,6 +1122,11 @@ void readlevelheader(MYFILE *f, char * name)
|
|||
deh_strlcpy(mapheaderinfo[num]->zonttl, word2,
|
||||
sizeof(mapheaderinfo[num]->zonttl), va("Level header %d: zonetitle", num));
|
||||
}
|
||||
else if (fastcmp(word, "RELEVANTSKIN"))
|
||||
{
|
||||
deh_strlcpy(mapheaderinfo[num]->relevantskin, word2,
|
||||
sizeof(mapheaderinfo[num]->relevantskin), va("Level header %d: relevantskin", num));
|
||||
}
|
||||
else if (fastcmp(word, "SCRIPTNAME"))
|
||||
{
|
||||
deh_strlcpy(mapheaderinfo[num]->scriptname, word2,
|
||||
|
|
@ -3211,11 +3216,6 @@ void readmaincfg(MYFILE *f, boolean mainfile)
|
|||
bootmap = Z_StrDup(word2);
|
||||
//titlechanged = true;
|
||||
}
|
||||
else if (fastcmp(word, "TUTORIALMAP"))
|
||||
{
|
||||
Z_Free(tutorialmap);
|
||||
tutorialmap = Z_StrDup(word2);
|
||||
}
|
||||
else if (fastcmp(word, "PODIUMMAP"))
|
||||
{
|
||||
Z_Free(podiummap);
|
||||
|
|
|
|||
|
|
@ -5854,6 +5854,7 @@ const char *const GAMETYPERULE_LIST[] = {
|
|||
|
||||
"NOMP",
|
||||
"NOCUPSELECT",
|
||||
"NOPOSITION",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -222,9 +222,6 @@ extern char * titlemap;
|
|||
extern boolean hidetitlepics;
|
||||
extern char * bootmap; //bootmap for loading a map on startup
|
||||
|
||||
extern char * tutorialmap; // map to load for tutorial
|
||||
extern boolean tutorialmode; // are we in a tutorial right now?
|
||||
|
||||
extern char * podiummap; // map to load for podium
|
||||
|
||||
extern boolean looptitle;
|
||||
|
|
@ -430,6 +427,7 @@ struct mapheader_t
|
|||
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
|
||||
UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden.
|
||||
fixed_t gravity; ///< Map-wide gravity.
|
||||
char relevantskin[SKINNAMESIZE+1]; ///< Skin to use for tutorial (if not provided, uses Eggman.)
|
||||
|
||||
// Music information
|
||||
char musname[MAXMUSNAMES][7]; ///< Music tracks to play. First dimension is the track number, second is the music string. "" for no music.
|
||||
|
|
@ -499,6 +497,7 @@ enum GameType
|
|||
GT_BATTLE,
|
||||
GT_SPECIAL,
|
||||
GT_VERSUS,
|
||||
GT_TUTORIAL,
|
||||
|
||||
GT_FIRSTFREESLOT,
|
||||
GT_LASTFREESLOT = 127, // Previously (GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1) - it would be necessary to rewrite VOTEMODIFIER_ENCORE to go higher than this.
|
||||
|
|
@ -563,6 +562,7 @@ enum GameTypeRules
|
|||
|
||||
GTR_NOMP = 1<<22, // No multiplayer
|
||||
GTR_NOCUPSELECT = 1<<23, // Your maps are not selected via cup.
|
||||
GTR_NOPOSITION = 1<<24, // No POSITION
|
||||
|
||||
// free: to and including 1<<31
|
||||
};
|
||||
|
|
@ -581,6 +581,7 @@ enum TypeOfLevel
|
|||
TOL_BATTLE = 0x0002, ///< Battle
|
||||
TOL_BOSS = 0x0004, ///< Boss (variant of battle, but forbidden)
|
||||
TOL_SPECIAL = 0x0008, ///< Special Stage (variant of race, but forbidden)
|
||||
TOL_TUTORIAL = 0x0010, ///< Tutorial (variant of race, but forbidden)
|
||||
|
||||
// Modifiers
|
||||
TOL_TV = 0x0100 ///< Midnight Channel specific: draw TV like overlay on HUD
|
||||
|
|
|
|||
|
|
@ -2826,7 +2826,7 @@ static boolean F_GetTextPromptTutorialTag(char *tag, INT32 length)
|
|||
INT32 gcs = 0;
|
||||
boolean suffixed = true;
|
||||
|
||||
if (!tag || !tag[0] || !tutorialmode)
|
||||
if (!tag || !tag[0] || gametype == GT_TUTORIAL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -2859,7 +2859,7 @@ static boolean F_GetTextPromptTutorialTag(char *tag, INT32 length)
|
|||
void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum)
|
||||
{
|
||||
INT32 nosuffixpromptnum = INT32_MAX, nosuffixpagenum = INT32_MAX;
|
||||
INT32 tutorialpromptnum = (tutorialmode) ? TUTORIAL_PROMPT-1 : 0;
|
||||
INT32 tutorialpromptnum = (gametype == GT_TUTORIAL) ? TUTORIAL_PROMPT-1 : 0;
|
||||
boolean suffixed = false, found = false;
|
||||
char suffixedtag[33];
|
||||
|
||||
|
|
@ -2871,7 +2871,7 @@ void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum
|
|||
strncpy(suffixedtag, tag, 33);
|
||||
suffixedtag[32] = 0;
|
||||
|
||||
if (tutorialmode)
|
||||
if (gametype == GT_TUTORIAL)
|
||||
suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33);
|
||||
|
||||
for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++)
|
||||
|
|
|
|||
20
src/g_game.c
20
src/g_game.c
|
|
@ -167,9 +167,6 @@ char * titlemap = NULL;
|
|||
boolean hidetitlepics = false;
|
||||
char * bootmap = NULL; //bootmap for loading a map on startup
|
||||
|
||||
char * tutorialmap = NULL; // map to load for tutorial
|
||||
boolean tutorialmode = false; // are we in a tutorial right now?
|
||||
|
||||
char * podiummap = NULL; // map to load for podium
|
||||
|
||||
boolean looptitle = true;
|
||||
|
|
@ -3398,6 +3395,17 @@ static gametype_t defaultgametypes[] =
|
|||
0,
|
||||
0,
|
||||
},
|
||||
|
||||
// GT_TUTORIAL
|
||||
{
|
||||
"Tutorial",
|
||||
"GT_TUTORIAL",
|
||||
GTR_NOMP|GTR_NOCUPSELECT|GTR_NOPOSITION,
|
||||
TOL_TUTORIAL,
|
||||
int_none,
|
||||
0,
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
gametype_t *gametypes[MAXGAMETYPES+1] =
|
||||
|
|
@ -3406,6 +3414,7 @@ gametype_t *gametypes[MAXGAMETYPES+1] =
|
|||
&defaultgametypes[GT_BATTLE],
|
||||
&defaultgametypes[GT_SPECIAL],
|
||||
&defaultgametypes[GT_VERSUS],
|
||||
&defaultgametypes[GT_TUTORIAL],
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -3541,6 +3550,7 @@ tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = {
|
|||
{"BATTLE",TOL_BATTLE},
|
||||
{"BOSS",TOL_BOSS},
|
||||
{"SPECIAL",TOL_SPECIAL},
|
||||
{"TUTORIAL",TOL_TUTORIAL},
|
||||
{"TV",TOL_TV},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
|
@ -3667,6 +3677,7 @@ INT16 G_GetFirstMapOfGametype(UINT8 pgametype)
|
|||
templevelsearch.typeoflevel = G_TOLFlag(pgametype);
|
||||
templevelsearch.cupmode = (!(gametypes[pgametype]->rules & GTR_NOCUPSELECT));
|
||||
templevelsearch.timeattack = false;
|
||||
templevelsearch.tutorial = false;
|
||||
templevelsearch.checklocked = true;
|
||||
|
||||
if (templevelsearch.cupmode)
|
||||
|
|
@ -4245,6 +4256,8 @@ static void G_DoCompleted(void)
|
|||
S_StopSounds();
|
||||
|
||||
if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified)
|
||||
{
|
||||
if (gametype != GT_TUTORIAL)
|
||||
{
|
||||
UINT8 roundtype = GDGT_CUSTOM;
|
||||
|
||||
|
|
@ -4256,6 +4269,7 @@ static void G_DoCompleted(void)
|
|||
roundtype = GDGT_SPECIAL;
|
||||
|
||||
gamedata->roundsplayed[roundtype]++;
|
||||
}
|
||||
gamedata->pendingkeyrounds++;
|
||||
|
||||
// Done before forced addition of PF_NOCONTEST to make UCRP_NOCONTEST harder to achieve
|
||||
|
|
|
|||
|
|
@ -715,6 +715,12 @@ boolean K_CanChangeRules(boolean allowdemos)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Tutorials are locked down.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!allowdemos && demo.playback)
|
||||
{
|
||||
// We've already got our important settings!
|
||||
|
|
|
|||
132
src/k_hud.c
132
src/k_hud.c
|
|
@ -2488,7 +2488,7 @@ static void K_DrawLivesDigits(INT32 x, INT32 y, INT32 width, INT32 flags, patch_
|
|||
V_DrawScaledPatch(x, y, flags, font[stplyr->lives % 10]);
|
||||
}
|
||||
|
||||
static void K_drawRingCounter(void)
|
||||
static void K_drawRingCounter(boolean gametypeinfoshown)
|
||||
{
|
||||
const boolean uselives = G_GametypeUsesLives();
|
||||
SINT8 ringanim_realframe = stplyr->karthud[khud_ringframe];
|
||||
|
|
@ -2547,43 +2547,57 @@ static void K_drawRingCounter(void)
|
|||
|
||||
fr = fx;
|
||||
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 10;
|
||||
}
|
||||
|
||||
// Rings
|
||||
if (!uselives)
|
||||
{
|
||||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy-10, V_HUDTRANS|V_SLIDEIN|splitflags|flipflag, kp_ringstickersplit[1]);
|
||||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[1]->width) - 3) : 0), fy, V_HUDTRANS|V_SLIDEIN|splitflags|flipflag, kp_ringstickersplit[1]);
|
||||
if (flipflag)
|
||||
fr += 15;
|
||||
}
|
||||
else
|
||||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[0]->width) - 3) : 0), fy-10, V_HUDTRANS|V_SLIDEIN|splitflags|flipflag, kp_ringstickersplit[0]);
|
||||
V_DrawScaledPatch(fx-2 + (flipflag ? (SHORT(kp_ringstickersplit[0]->width) - 3) : 0), fy, V_HUDTRANS|V_SLIDEIN|splitflags|flipflag, kp_ringstickersplit[0]);
|
||||
|
||||
V_DrawMappedPatch(fr+ringx, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags|ringflip, kp_smallring[ringanim_realframe], (colorring ? ringmap : NULL));
|
||||
V_DrawMappedPatch(fr+ringx, fy-3, V_HUDTRANS|V_SLIDEIN|splitflags|ringflip, kp_smallring[ringanim_realframe], (colorring ? ringmap : NULL));
|
||||
|
||||
if (stplyr->rings < 0) // Draw the minus for ring debt
|
||||
V_DrawMappedPatch(fr+7, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminussmall, ringmap);
|
||||
V_DrawMappedPatch(fr+7, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminussmall, ringmap);
|
||||
|
||||
V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[rn[0]], ringmap);
|
||||
V_DrawMappedPatch(fr+15, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[rn[1]], ringmap);
|
||||
V_DrawMappedPatch(fr+11, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[rn[0]], ringmap);
|
||||
V_DrawMappedPatch(fr+15, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[rn[1]], ringmap);
|
||||
|
||||
// SPB ring lock
|
||||
if (stplyr->pflags & PF_RINGLOCK)
|
||||
V_DrawScaledPatch(fr-12, fy-23, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]);
|
||||
V_DrawScaledPatch(fr-12, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringspblocksmall[stplyr->karthud[khud_ringspblock]]);
|
||||
|
||||
// Lives
|
||||
if (uselives)
|
||||
{
|
||||
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap);
|
||||
V_DrawMappedPatch(fr+21, fy-3, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap);
|
||||
if (stplyr->lives >= 0)
|
||||
K_DrawLivesDigits(fr+34, fy-10, 4, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font);
|
||||
K_DrawLivesDigits(fr+34, fy, 4, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fy = LAPS_Y-11;
|
||||
fy = LAPS_Y;
|
||||
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 11;
|
||||
|
||||
if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS)
|
||||
fy -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy += 9;
|
||||
}
|
||||
|
||||
// Rings
|
||||
if (!uselives)
|
||||
|
|
@ -2622,9 +2636,9 @@ static void K_drawRingCounter(void)
|
|||
|
||||
#undef RINGANIM_FLIPFRAME
|
||||
|
||||
static void K_drawKartAccessibilityIcons(INT32 fx)
|
||||
static void K_drawKartAccessibilityIcons(boolean gametypeinfoshown, INT32 fx)
|
||||
{
|
||||
INT32 fy = LAPS_Y-25;
|
||||
INT32 fy = LAPS_Y-14;
|
||||
INT32 splitflags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_SPLITSCREEN;
|
||||
//INT32 step = 1; -- if there's ever more than one accessibility icon
|
||||
|
||||
|
|
@ -2632,10 +2646,19 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
|
|||
|
||||
if (r_splitscreen < 2) // adjust to speedometer height
|
||||
{
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 11;
|
||||
|
||||
if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS)
|
||||
fy -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy += 9;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fx = LAPS_X+43;
|
||||
fy = LAPS_Y;
|
||||
|
|
@ -2681,13 +2704,13 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_drawKartSpeedometer(void)
|
||||
static void K_drawKartSpeedometer(boolean gametypeinfoshown)
|
||||
{
|
||||
static fixed_t convSpeed;
|
||||
UINT8 labeln = 0;
|
||||
UINT8 numbers[3];
|
||||
INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN;
|
||||
INT32 battleoffset = 0;
|
||||
INT32 fy = LAPS_Y-14;
|
||||
|
||||
if (!stplyr->exiting) // Keep the same speed value as when you crossed the finish line!
|
||||
{
|
||||
|
|
@ -2722,19 +2745,28 @@ static void K_drawKartSpeedometer(void)
|
|||
numbers[1] = ((convSpeed / 10) % 10);
|
||||
numbers[2] = (convSpeed % 10);
|
||||
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 11;
|
||||
|
||||
if ((gametyperules & (GTR_BUMPERS|GTR_CIRCUIT)) == GTR_BUMPERS)
|
||||
battleoffset = -4;
|
||||
fy -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy += 9;
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometersticker);
|
||||
V_DrawScaledPatch(LAPS_X+7, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[0]]);
|
||||
V_DrawScaledPatch(LAPS_X+13, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[1]]);
|
||||
V_DrawScaledPatch(LAPS_X+19, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]);
|
||||
V_DrawScaledPatch(LAPS_X+29, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]);
|
||||
V_DrawScaledPatch(LAPS_X, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometersticker);
|
||||
V_DrawScaledPatch(LAPS_X+7, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[0]]);
|
||||
V_DrawScaledPatch(LAPS_X+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[1]]);
|
||||
V_DrawScaledPatch(LAPS_X+19, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[numbers[2]]);
|
||||
V_DrawScaledPatch(LAPS_X+29, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometerlabel[labeln]);
|
||||
|
||||
K_drawKartAccessibilityIcons(56);
|
||||
K_drawKartAccessibilityIcons(gametypeinfoshown, 56);
|
||||
}
|
||||
|
||||
static void K_drawBlueSphereMeter(void)
|
||||
static void K_drawBlueSphereMeter(boolean gametypeinfoshown)
|
||||
{
|
||||
const UINT8 maxBars = 4;
|
||||
const UINT8 segColors[] = {73, 64, 52, 54, 55, 35, 34, 33, 202, 180, 181, 182, 164, 165, 166, 153, 152};
|
||||
|
|
@ -2752,7 +2784,17 @@ static void K_drawBlueSphereMeter(void)
|
|||
if (r_splitscreen < 2) // don't change shit for THIS splitscreen.
|
||||
{
|
||||
fx = LAPS_X;
|
||||
fy = LAPS_Y-22;
|
||||
fy = LAPS_Y-7;
|
||||
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 11 + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
fy += 9;
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_spheresticker);
|
||||
}
|
||||
else
|
||||
|
|
@ -2771,7 +2813,12 @@ static void K_drawBlueSphereMeter(void)
|
|||
flipflag = V_FLIP; // make the string right aligned and other shit
|
||||
xstep = -xstep;
|
||||
}
|
||||
|
||||
if (gametypeinfoshown)
|
||||
{
|
||||
fy -= 16;
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(fx, fy, splitflags|flipflag, kp_splitspheresticker);
|
||||
}
|
||||
|
||||
|
|
@ -4294,21 +4341,7 @@ static void K_drawBattleFullscreen(void)
|
|||
}
|
||||
|
||||
// FREE PLAY?
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
// check to see if there's anyone else at all
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (i == displayplayers[0])
|
||||
continue;
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != MAXPLAYERS)
|
||||
K_drawKartFreePlay();
|
||||
}
|
||||
}
|
||||
|
||||
static void K_drawKartFirstPerson(void)
|
||||
|
|
@ -4700,12 +4733,13 @@ static void K_drawTrickCool(void)
|
|||
|
||||
void K_drawKartFreePlay(void)
|
||||
{
|
||||
// Doesn't support splitscreens higher than 2 for real estate reasons.
|
||||
|
||||
if (!LUA_HudEnabled(hud_freeplay))
|
||||
return;
|
||||
|
||||
if (modeattacking || grandprixinfo.gp || bossinfo.valid || stplyr->spectator)
|
||||
if (stplyr->spectator == true)
|
||||
return;
|
||||
|
||||
if (M_NotFreePlay(stplyr) == true)
|
||||
return;
|
||||
|
||||
if (lt_exitticker < TICRATE/2)
|
||||
|
|
@ -5081,6 +5115,8 @@ void K_drawKartHUD(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
boolean gametypeinfoshown = false;
|
||||
|
||||
if (LUA_HudEnabled(hud_position))
|
||||
{
|
||||
if (bossinfo.valid)
|
||||
|
|
@ -5101,32 +5137,37 @@ void K_drawKartHUD(void)
|
|||
if (LUA_HudEnabled(hud_gametypeinfo))
|
||||
{
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if (numlaps > 1)
|
||||
{
|
||||
K_drawKartLaps();
|
||||
gametypeinfoshown = true;
|
||||
}
|
||||
}
|
||||
else if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
K_drawKartBumpersOrKarma();
|
||||
gametypeinfoshown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the speedometer and/or accessibility icons
|
||||
if (cv_kartspeedometer.value && !r_splitscreen && (LUA_HudEnabled(hud_speedometer)))
|
||||
{
|
||||
K_drawKartSpeedometer();
|
||||
K_drawKartSpeedometer(gametypeinfoshown);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_drawKartAccessibilityIcons(0);
|
||||
K_drawKartAccessibilityIcons(gametypeinfoshown, 0);
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
{
|
||||
K_drawBlueSphereMeter();
|
||||
K_drawBlueSphereMeter(gametypeinfoshown);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_drawRingCounter();
|
||||
K_drawRingCounter(gametypeinfoshown);
|
||||
}
|
||||
|
||||
if (modeattacking && !bossinfo.valid)
|
||||
|
|
@ -5180,7 +5221,6 @@ void K_drawKartHUD(void)
|
|||
V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem);
|
||||
|
||||
// Draw FREE PLAY.
|
||||
if (islonesome)
|
||||
K_drawKartFreePlay();
|
||||
|
||||
if (r_splitscreen == 0 && (stplyr->pflags & PF_WRONGWAY) && ((leveltime / 8) & 1))
|
||||
|
|
|
|||
12
src/k_kart.c
12
src/k_kart.c
|
|
@ -187,7 +187,12 @@ void K_TimerInit(void)
|
|||
}
|
||||
}
|
||||
|
||||
starttime = (introtime + (3*TICRATE)) + ((2*TICRATE) + (numbulbs * bulbtime)); // Start countdown time, + buffer time
|
||||
starttime = introtime;
|
||||
if (!(gametyperules & GTR_NOPOSITION))
|
||||
{
|
||||
// Start countdown time + buffer time
|
||||
starttime += ((3*TICRATE) + ((2*TICRATE) + (numbulbs * bulbtime)));
|
||||
}
|
||||
}
|
||||
|
||||
K_BattleInit(domodeattack);
|
||||
|
|
@ -11695,6 +11700,11 @@ boolean K_Cooperative(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (specialstageinfo.valid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -733,6 +733,7 @@ typedef struct levelsearch_s {
|
|||
UINT32 typeoflevel;
|
||||
cupheader_t *cup;
|
||||
boolean timeattack;
|
||||
boolean tutorial;
|
||||
boolean cupmode;
|
||||
boolean checklocked;
|
||||
} levelsearch_t;
|
||||
|
|
@ -1017,8 +1018,8 @@ extern struct extrasmenu_s {
|
|||
typedef enum
|
||||
{
|
||||
extras_addons = 0,
|
||||
extras_tutorial,
|
||||
extras_challenges,
|
||||
//extras_tutorial,
|
||||
extras_statistics,
|
||||
extras_eggtv,
|
||||
extras_stereo,
|
||||
|
|
|
|||
|
|
@ -2411,6 +2411,12 @@ void M_DrawLevelSelect(void)
|
|||
INT16 y = 80 - (12 * levellist.y);
|
||||
boolean tatransition = ((menutransition.startmenu == &PLAY_TimeAttackDef || menutransition.endmenu == &PLAY_TimeAttackDef) && menutransition.tics);
|
||||
|
||||
if (levellist.levelsearch.tutorial)
|
||||
{
|
||||
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
|
||||
}
|
||||
|
||||
if (tatransition)
|
||||
{
|
||||
t = -t;
|
||||
|
|
@ -5183,6 +5189,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
|
|||
templevelsearch.typeoflevel = G_TOLFlag(GT_RACE)|G_TOLFlag(GT_BATTLE);
|
||||
templevelsearch.cupmode = true;
|
||||
templevelsearch.timeattack = false;
|
||||
templevelsearch.tutorial = false;
|
||||
templevelsearch.checklocked = false;
|
||||
|
||||
M_DrawCupPreview(146, &templevelsearch);
|
||||
|
|
|
|||
|
|
@ -216,12 +216,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"bootmap")) {
|
||||
lua_pushstring(L, bootmap);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"tutorialmap")) {
|
||||
lua_pushstring(L, tutorialmap);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"tutorialmode")) {
|
||||
lua_pushboolean(L, tutorialmode);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"podiummap")) {
|
||||
lua_pushstring(L, podiummap);
|
||||
return 1;
|
||||
|
|
|
|||
14
src/m_cond.c
14
src/m_cond.c
|
|
@ -624,10 +624,22 @@ void M_UpdateConditionSetsPending(void)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean M_NotFreePlay(player_t *player)
|
||||
boolean M_NotFreePlay(player_t *player)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
if (K_CanChangeRules(true) == false)
|
||||
{
|
||||
// Rounds with direction are never FREE PLAY.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (battleprisons)
|
||||
{
|
||||
// Prison Break is battle's FREE PLAY.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] == false || players[i].spectator == true)
|
||||
|
|
|
|||
|
|
@ -325,6 +325,8 @@ void M_ClearConditionSet(UINT8 set);
|
|||
void M_ClearSecrets(void);
|
||||
void M_ClearStats(void);
|
||||
|
||||
boolean M_NotFreePlay(player_t *player);
|
||||
|
||||
// Updating conditions and unlockables
|
||||
boolean M_CheckCondition(condition_t *cn, player_t *player);
|
||||
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ menuitem_t EXTRAS_Main[] =
|
|||
{IT_STRING | IT_CALL, NULL, NULL,
|
||||
NULL, {.routine = M_Addons}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "Tutorial", "Help Dr. Eggman and Tails test out their new Ring Racers.",
|
||||
NULL, {.routine = M_LevelSelectInit}, 0, GT_TUTORIAL},
|
||||
|
||||
{IT_STRING | IT_CALL, "Challenges", "View the requirements for some of the secret content you can unlock!",
|
||||
NULL, {.routine = M_Challenges}, 0, 0},
|
||||
|
||||
|
|
@ -79,6 +82,25 @@ void M_InitExtras(INT32 choice)
|
|||
}
|
||||
}
|
||||
|
||||
// Tutorial
|
||||
{
|
||||
levelsearch_t templevelsearch;
|
||||
UINT8 i = 0;
|
||||
INT16 map;
|
||||
|
||||
templevelsearch.cup = NULL;
|
||||
templevelsearch.typeoflevel = G_TOLFlag(GT_TUTORIAL);
|
||||
templevelsearch.cupmode = false;
|
||||
templevelsearch.timeattack = false;
|
||||
templevelsearch.tutorial = true;
|
||||
templevelsearch.checklocked = true;
|
||||
|
||||
map = M_GetFirstLevelInList(&i, &templevelsearch);
|
||||
|
||||
EXTRAS_Main[extras_tutorial].status = (IT_STRING |
|
||||
((map == NEXTMAP_INVALID) ? IT_TRANSTEXT : IT_CALL));
|
||||
}
|
||||
|
||||
// Egg TV
|
||||
if (M_SecretUnlocked(SECRET_EGGTV, true))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ void M_MPSetupNetgameMapSelect(INT32 choice)
|
|||
levellist.netgame = true;
|
||||
// Make sure we reset those
|
||||
levellist.levelsearch.timeattack = false;
|
||||
levellist.levelsearch.tutorial = false;
|
||||
levellist.levelsearch.checklocked = true;
|
||||
cupgrid.grandprix = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch)
|
|||
return false;
|
||||
|
||||
// Check for TOL (permits TEST RUN outside of time attack)
|
||||
if ((levelsearch->timeattack || mapheaderinfo[mapnum]->typeoflevel)
|
||||
if ((levelsearch->timeattack || levelsearch->tutorial || mapheaderinfo[mapnum]->typeoflevel)
|
||||
&& !(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel))
|
||||
return false;
|
||||
|
||||
|
|
@ -214,7 +214,9 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
static boolean first = true;
|
||||
UINT8 temp = 0;
|
||||
|
||||
if (gt != -1 && (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES))
|
||||
if (gt != -1)
|
||||
{
|
||||
if (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
|
|
@ -244,6 +246,12 @@ boolean M_LevelListFromGametype(INT16 gt)
|
|||
CV_SetValue(&cv_dummyspbattack, 0);
|
||||
}
|
||||
|
||||
PLAY_CupSelectDef.music = \
|
||||
PLAY_LevelSelectDef.music = \
|
||||
PLAY_TimeAttackDef.music = \
|
||||
currentMenu->music;
|
||||
}
|
||||
|
||||
// Obviously go to Cup Select in gametypes that have cups.
|
||||
// Use a really long level select in gametypes that don't use cups.
|
||||
|
||||
|
|
@ -427,6 +435,7 @@ void M_LevelSelectInit(INT32 choice)
|
|||
// Make sure this is reset as we'll only be using this function for offline games!
|
||||
levellist.netgame = false;
|
||||
levellist.levelsearch.checklocked = true;
|
||||
levellist.levelsearch.tutorial = (gt == GT_TUTORIAL);
|
||||
|
||||
switch (currentMenu->menuitems[itemOn].mvar1)
|
||||
{
|
||||
|
|
@ -498,7 +507,7 @@ void M_LevelSelected(INT16 add)
|
|||
{
|
||||
if (gamestate == GS_MENU)
|
||||
{
|
||||
UINT8 ssplayers = cv_splitplayers.value-1;
|
||||
UINT8 ssplayers = levellist.levelsearch.tutorial ? 0 : cv_splitplayers.value-1;
|
||||
|
||||
netgame = false;
|
||||
multiplayer = true;
|
||||
|
|
@ -543,7 +552,11 @@ void M_LevelSelected(INT16 add)
|
|||
|
||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
|
||||
if (levellist.netgame == true)
|
||||
if (levellist.levelsearch.tutorial)
|
||||
{
|
||||
restoreMenu = currentMenu;
|
||||
}
|
||||
else if (levellist.netgame == true)
|
||||
{
|
||||
restoreMenu = &PLAY_MP_OptSelectDef;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -389,6 +389,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
|
|||
mapheaderinfo[num]->typeoflevel = 0;
|
||||
mapheaderinfo[num]->gravity = DEFAULT_GRAVITY;
|
||||
mapheaderinfo[num]->keywords[0] = '\0';
|
||||
mapheaderinfo[num]->relevantskin[0] = '\0';
|
||||
mapheaderinfo[num]->musname[0][0] = 0;
|
||||
mapheaderinfo[num]->musname_size = 0;
|
||||
mapheaderinfo[num]->positionmus[0] = '\0';
|
||||
|
|
@ -7392,6 +7393,27 @@ static void P_InitCamera(void)
|
|||
static void P_InitPlayers(void)
|
||||
{
|
||||
UINT8 i;
|
||||
INT32 skin = -1;
|
||||
|
||||
// Are we forcing a character?
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Get skin from name.
|
||||
if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->relevantskin[0])
|
||||
{
|
||||
skin = R_SkinAvailable(mapheaderinfo[gamemap-1]->relevantskin);
|
||||
}
|
||||
else
|
||||
{
|
||||
skin = R_SkinAvailable(DEFAULTSKIN);
|
||||
}
|
||||
|
||||
// Handle invalid case.
|
||||
if (skin == -1)
|
||||
{
|
||||
skin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -7400,6 +7422,15 @@ static void P_InitPlayers(void)
|
|||
|
||||
players[i].mo = NULL;
|
||||
|
||||
// If we're forcing a character, do it now.
|
||||
if (skin != -1)
|
||||
{
|
||||
players[i].skin = skin;
|
||||
players[i].skincolor = skins[skin].prefcolor;
|
||||
players[i].followerskin = -1;
|
||||
// followercolor can be left alone for hopefully obvious reasons
|
||||
}
|
||||
|
||||
if (!(gametyperules & GTR_CIRCUIT) && K_PodiumSequence() == false)
|
||||
{
|
||||
G_DoReborn(i);
|
||||
|
|
|
|||
|
|
@ -1407,7 +1407,7 @@ boolean R_ViewpointHasChasecam(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode)
|
||||
if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN)
|
||||
chasecam = true; // force chasecam on
|
||||
else if (player->spectator) // no spectator chasecam
|
||||
chasecam = false; // force chasecam off
|
||||
|
|
|
|||
|
|
@ -236,6 +236,12 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum, boolean demoskins)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (gametype == GT_TUTORIAL)
|
||||
{
|
||||
// Being forced to play as this character by the tutorial
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if this character is supposed to be unlockable or not
|
||||
if (useplayerstruct && demo.playback)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue