More fun rules for Special Stages

- GTR_ROLLINGSTART
    * Initial instathrust, as before
    * Forced MAXPLMOVE forward
    * Disable finish line beam
    * "Super transformation" sound
        - Reference to the previous entry in the series' Perfect Startboost mechanic
- GTR_SPECIALSTART
    * Instant white fade
    * No titlecard (overridden by Boss intro)
    * Starting warp sound
- Match slidein time with no traditional titlecard to the end of the playsim intro fade
- Remove G_IsSpecialStage
This commit is contained in:
toaster 2022-12-27 17:58:35 +00:00
parent f8999bea36
commit 03c8fd543f
12 changed files with 70 additions and 79 deletions

View file

@ -5813,9 +5813,11 @@ const char *const GAMETYPERULE_LIST[] = {
"CATCHER",
"BOSS",
"ROLLINGSTART",
"NOCUPSELECT",
"CLOSERPLAYERS",
"ENCORE",
"SPECIALSTART",
NULL
};

View file

@ -513,10 +513,11 @@ enum GameTypeRules
// To be rearranged later
GTR_CATCHER = 1<<17, // UFO Catcher (only works with GTR_CIRCUIT)
GTR_BOSS = 1<<18, // Boss intro and spawning
GTR_ROLLINGSTART = 1<<19, // Rolling start (only works with GTR_CIRCUIT)
GTR_NOCUPSELECT = 1<<20, // Your maps are not selected via cup.
GTR_CLOSERPLAYERS = 1<<21, // Buffs spindash and draft power to bring everyone together, nerfs invincibility and grow to prevent excessive combos
GTR_ENCORE = 1<<22, // Alternate Encore mirroring, scripting, and texture remapping
GTR_SPECIALSTART = 1<<23, // White fade instant start
// free: to and including 1<<31
};

View file

@ -1412,7 +1412,7 @@ void G_StartTitleCard(void)
{
// The title card has been disabled for this map.
// Oh well.
if (!G_IsTitleCardAvailable() || demo.rewinding)
if (demo.rewinding || !G_IsTitleCardAvailable())
{
WipeStageTitle = false;
return;
@ -1476,11 +1476,17 @@ void G_PreLevelTitleCard(void)
//
boolean G_IsTitleCardAvailable(void)
{
#if 0
// Overwrites all other title card exceptions.
if (K_CheckBossIntro() == true)
return true;
// The current level has no name.
if (!mapheaderinfo[gamemap-1]->lvlttl[0])
return false;
#endif
// Instant white fade.
if (gametyperules & GTR_SPECIALSTART)
return false;
// The title card is available.
return true;
@ -3015,7 +3021,7 @@ static gametype_t defaultgametypes[] =
{
"Special",
"GT_SPECIAL",
GTR_CATCHER|GTR_CIRCUIT,
GTR_CATCHER|GTR_SPECIALSTART|GTR_ROLLINGSTART|GTR_CIRCUIT,
TOL_SPECIAL,
int_time,
0,
@ -3213,25 +3219,6 @@ void G_AddTOL(UINT32 newtol, const char *tolname)
TYPEOFLEVEL[i].flag = newtol;
}
//
// G_IsSpecialStage
//
// Returns TRUE if
// the given map is a special stage.
//
boolean G_IsSpecialStage(INT32 mapnum)
{
mapnum--; // gamemap-based to 0 indexed
if (mapnum > nummapheaders || !mapheaderinfo[mapnum])
return false;
if (!mapheaderinfo[mapnum]->cup || mapheaderinfo[mapnum]->cup->cachedlevels[CUPCACHE_SPECIAL] != mapnum)
return false;
return true;
}
//
// G_GametypeUsesLives
//
@ -3666,7 +3653,6 @@ static void G_HandleSaveLevel(void)
static void G_GetNextMap(void)
{
boolean spec = G_IsSpecialStage(prevmap+1);
INT32 i;
// go to next level
@ -3917,7 +3903,9 @@ static void G_GetNextMap(void)
if (nextmap == NEXTMAP_INVALID || (nextmap < NEXTMAP_SPECIAL && (nextmap >= nummapheaders || !mapheaderinfo[nextmap] || mapheaderinfo[nextmap]->lumpnum == LUMPERROR)))
I_Error("G_GetNextMap: Internal map ID %d not found (nummapheaders = %d)\n", nextmap, nummapheaders);
#if 0 // This is a surprise tool that will help us later.
if (!spec)
#endif //#if 0
lastmap = nextmap;
}

View file

@ -186,7 +186,6 @@ void G_AddTOL(UINT32 newtol, const char *tolname);
INT32 G_GetGametypeByName(const char *gametypestr);
INT32 G_GuessGametypeByTOL(UINT32 tol);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);

View file

@ -109,6 +109,36 @@ void K_TimerInit(void)
boolean domodeattack = ((modeattacking != ATTACKING_NONE)
|| (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE));
// Rooooooolllling staaaaaaart
if ((gametyperules & (GTR_ROLLINGSTART|GTR_CIRCUIT)) == (GTR_ROLLINGSTART|GTR_CIRCUIT))
{
S_StartSound(NULL, sfx_s25f);
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *player = NULL;
if (playeringame[i] == false)
{
continue;
}
player = &players[i];
if (player->spectator == true)
{
continue;
}
if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
{
continue;
}
// Rolling start? lol
P_InstaThrust(player->mo, player->mo->angle, K_GetKartSpeed(player, false, false));
}
}
if ((gametyperules & (GTR_CATCHER|GTR_CIRCUIT)) == (GTR_CATCHER|GTR_CIRCUIT))
{
K_InitSpecialStage();
@ -3298,7 +3328,8 @@ SINT8 K_GetForwardMove(player_t *player)
return 0;
}
if (player->sneakertimer || player->spindashboost)
if (player->sneakertimer || player->spindashboost
|| (((gametyperules & (GTR_ROLLINGSTART|GTR_CIRCUIT)) == (GTR_ROLLINGSTART|GTR_CIRCUIT)) && (leveltime < TICRATE/2)))
{
return MAXPLMOVE;
}

View file

@ -400,7 +400,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *
void K_RunFinishLineBeam(void)
{
if (!(leveltime < starttime || rainbowstartavailable == true))
if ((gametyperules & GTR_ROLLINGSTART) || !(leveltime < starttime || rainbowstartavailable == true))
{
return;
}

View file

@ -42,8 +42,6 @@ void K_ResetSpecialStage(void)
--------------------------------------------------*/
void K_InitSpecialStage(void)
{
INT32 i;
if ((gametyperules & (GTR_CATCHER|GTR_CIRCUIT)) != (GTR_CATCHER|GTR_CIRCUIT))
{
return;
@ -53,30 +51,6 @@ void K_InitSpecialStage(void)
specialstageinfo.beamDist = UINT32_MAX; // TODO: make proper value
P_SetTarget(&specialstageinfo.ufo, Obj_CreateSpecialUFO());
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *player = NULL;
if (playeringame[i] == false)
{
continue;
}
player = &players[i];
if (player->spectator == true)
{
continue;
}
if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
{
continue;
}
// Rolling start? lol
P_InstaThrust(player->mo, player->mo->angle, K_GetKartSpeed(player, false, false));
}
}
/*--------------------------------------------------

View file

@ -3282,15 +3282,6 @@ static int lib_gExitLevel(lua_State *L)
return 0;
}
static int lib_gIsSpecialStage(lua_State *L)
{
INT32 mapnum = luaL_optinteger(L, 1, gamemap);
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_IsSpecialStage(mapnum));
return 1;
}
static int lib_gGametypeUsesLives(lua_State *L)
{
//HUDSAFE
@ -4099,7 +4090,6 @@ static luaL_Reg lib[] = {
{"G_DoReborn",lib_gDoReborn},
{"G_SetCustomExitVars",lib_gSetCustomExitVars},
{"G_ExitLevel",lib_gExitLevel},
{"G_IsSpecialStage",lib_gIsSpecialStage},
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
{"G_GametypeHasTeams",lib_gGametypeHasTeams},
{"G_GametypeHasSpectators",lib_gGametypeHasSpectators},

View file

@ -7326,13 +7326,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
}
G_ClearModeAttackRetryFlag();
}
/*
else if (rendermode != render_none && G_IsSpecialStage(gamemap))
{
P_RunSpecialStageWipe();
ranspecialwipe = 1;
}
*/
// Make sure all sounds are stopped before Z_FreeTags.
S_StopSounds();
@ -7367,7 +7360,20 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
S_Start();
}
levelfadecol = (encoremode ? 0 : 31);
if (gametyperules & GTR_SPECIALSTART)
{
if (ranspecialwipe != 2)
S_StartSound(NULL, sfx_s3kaf);
levelfadecol = 0;
}
else if (encoremode)
{
levelfadecol = 0;
}
else
{
levelfadecol = 31;
}
if (rendermode != render_none)
{

View file

@ -1843,7 +1843,7 @@ static void K_HandleLapIncrement(player_t *player)
{
if (player)
{
if (leveltime < starttime)
if (leveltime < starttime && !(gametyperules & GTR_ROLLINGSTART))
{
// Will fault the player
K_DoIngameRespawn(player);
@ -1902,7 +1902,7 @@ static void K_HandleLapIncrement(player_t *player)
if (P_IsDisplayPlayer(player))
{
if (player->laps == numlaps) // final lap
if (numlaps > 1 && player->laps == numlaps) // final lap
S_StartSound(NULL, sfx_s3k68);
else if ((player->laps > 1) && (player->laps < numlaps)) // non-final lap
S_StartSound(NULL, sfx_s221);

View file

@ -802,7 +802,7 @@ void ST_drawTitleCard(void)
#define HITIME 15
patch_t *localwarn = (encoremode ? twarn2 : twarn);
INT32 transp = (lt_ticker+HITIME) % (LOTIME+HITIME);
boolean encorehack = (encoremode && lt_ticker <= PRELEVELTIME+4);
boolean encorehack = ((levelfadecol == 0) && lt_ticker <= PRELEVELTIME+4);
if ((localwarn->width > 0) && (lt_ticker + (HITIME-transp) <= lt_endtime))
{

View file

@ -585,16 +585,16 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du
}
}
if (options & V_SLIDEIN)
if ((options & V_SLIDEIN))
{
const tic_t length = TICRATE/4;
tic_t timer = lt_exitticker;
if (K_CheckBossIntro() == true)
if (K_CheckBossIntro() == true || G_IsTitleCardAvailable() == false)
{
if (leveltime <= 3)
if (leveltime <= 16)
timer = 0;
else
timer = leveltime-3;
timer = leveltime-16;
}
if (timer < length)