Support alternate gameplay events during GP

- Implementation details:
    - grandprixinfo.eventmode is the reference point
    - All bots have spectator applied and removed at map start depending on eventmode, and I've done my best to guard against side effects of not removing them entirely
    - You shouldn't turn off grandprixinfo.gp when turning on things like specialStage.active or bossinfo.boss when pursuing eventmode behaviour
    - Probably needs to be integrated into XD_MAP for any future netplay support, is currently disabled.
    - You technically don't have to assign a Capsules map to be the bonus and a Special Stage to be the special. A Capsules map can be assigned to a Special Stage too, and a Boss can be assigned to either of them.
    - Special Stages are still just as incomplete as they were before.
- Break the Capsules has special behaviour.
   - Timelimit starts at 20 seconds.
   - Earn 10 seconds (plus a little extra cheaty time) every capsule you destroy.
   - WIN + extra life if you bust all the capsules, COOL if you get some but run out of time, LOSE if you lose your bumper or run out of time without breaking a single capsule.
   - Supposed to also give you rings, but ran into a LOT of difficulty with this and didn't want to commit half-baked stuff, so it'll be a later project.
Also:
- Fix a long standing bug where totalring was reset between maps, preventing the sum from adding up across GP rounds and depriving you of extra lives you were owed.
- Fix an issue where Break the Capsules record attack was KARTSPEED_HARD.
- Send timelimitintics in savegames, since it's handled seperately now.
This commit is contained in:
toaster 2022-10-14 18:34:34 +01:00
parent f926842b30
commit f281f47c6f
16 changed files with 398 additions and 177 deletions

View file

@ -2572,15 +2572,19 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pencoremode, boolean r
if ((netgame || multiplayer) && !((gametype == newgametype) && (gametypedefaultrules[newgametype] & GTR_CAMPAIGN)))
FLS = false;
if (grandprixinfo.gp == true)
{
// Too lazy to change the input value for every instance of this function.......
pencoremode = grandprixinfo.encore;
}
else if (bossinfo.boss == true)
if (bossinfo.boss == true)
{
pencoremode = bossinfo.encore;
}
else if (specialStage.active == true)
{
pencoremode = specialStage.encore;
}
else if (grandprixinfo.gp == true)
{
pencoremode = grandprixinfo.encore;
}
if (delay != 2)
{
@ -4946,6 +4950,8 @@ Lagless_OnChange (void)
}
UINT32 timelimitintics = 0;
UINT32 extratimeintics = 0;
UINT32 secretextratime = 0;
/** Deals with a timelimit change by printing the change to the console.
* If the gametype is single player, cooperative, or race, the timelimit is
@ -5752,6 +5758,10 @@ void Command_Retry_f(void)
{
CONS_Printf(M_GetText("This only works in singleplayer games.\n"));
}
else if (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)
{
CONS_Printf(M_GetText("You can't retry right now!\n"));
}
else
{
M_ClearMenus(true);

View file

@ -55,7 +55,7 @@ extern consvar_t cv_itemrespawn;
extern consvar_t cv_pointlimit;
extern consvar_t cv_timelimit;
extern consvar_t cv_numlaps;
extern UINT32 timelimitintics;
extern UINT32 timelimitintics, extratimeintics, secretextratime;
extern consvar_t cv_allowexitlevel;
extern consvar_t cv_autobalance;

View file

@ -58,6 +58,7 @@
#include "k_respawn.h"
#include "k_grandprix.h"
#include "k_boss.h"
#include "k_specialstage.h"
#include "k_bot.h"
#include "doomstat.h"
@ -2297,6 +2298,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
botdiffincrease = players[player].botvars.diffincrease;
botrival = players[player].botvars.rival;
totalring = players[player].totalring;
xtralife = players[player].xtralife;
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE));
// SRB2kart
@ -2315,13 +2319,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
nocontrol = 0;
laps = 0;
latestlap = 0;
totalring = 0;
roundscore = 0;
exiting = 0;
khudfinish = 0;
khudcardanimation = 0;
starpostnum = 0;
xtralife = 0;
follower = NULL;
}
@ -2358,7 +2360,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
laps = players[player].laps;
latestlap = players[player].latestlap;
totalring = players[player].totalring;
roundscore = players[player].roundscore;
exiting = players[player].exiting;
@ -2375,8 +2376,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
starpostnum = players[player].starpostnum;
xtralife = players[player].xtralife;
follower = players[player].follower;
pflags |= (players[player].pflags & (PF_STASIS|PF_ELIMINATED|PF_NOCONTEST|PF_FAULT|PF_LOSTLIFE));
@ -2919,7 +2918,7 @@ void G_ExitLevel(void)
}
}
}
else if (grandprixinfo.gp == true)
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
{
youlost = (grandprixinfo.wonround != true);
}
@ -3233,14 +3232,14 @@ boolean G_GametypeUsesLives(void)
if (modeattacking || metalrecording) // NOT in Record Attack
return false;
if (bossinfo.boss == true) // Fighting a boss?
if ((grandprixinfo.gp == true) // In Grand Prix
&& (gametype == GT_RACE) // NOT in bonus round
&& grandprixinfo.eventmode == GPEVENT_NONE) // NOT in bonus
{
return true;
}
if ((grandprixinfo.gp == true) // In Grand Prix
&& (gametype == GT_RACE) // NOT in bonus round
&& !G_IsSpecialStage(gamemap)) // NOT in special stage
if (bossinfo.boss == true) // Fighting a boss?
{
return true;
}
@ -3723,14 +3722,94 @@ static void G_GetNextMap(void)
}
else
{
if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map
INT32 lastgametype = gametype;
// If we're in a GP event, don't immediately follow it up with another.
// I also suspect this will not work with online GP so I'm gonna prevent it right now.
// The server might have to communicate eventmode (alongside other GP data) in XD_MAP later.
if (netgame || grandprixinfo.eventmode != GPEVENT_NONE)
{
grandprixinfo.eventmode = GPEVENT_NONE;
G_SetGametype(GT_RACE);
if (gametype != lastgametype)
D_GameTypeChanged(lastgametype);
specialStage.active = false;
bossinfo.boss = false;
}
// Special stage
else if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels)
{
INT16 totaltotalring = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
if (players[i].bot)
continue;
totaltotalring += players[i].totalring;
}
if (totaltotalring >= 50)
{
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_SPECIAL];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum]
&& mapheaderinfo[cupLevelNum]->typeoflevel & (TOL_SPECIAL|TOL_BOSS|TOL_BATTLE))
{
grandprixinfo.eventmode = GPEVENT_SPECIAL;
nextmap = cupLevelNum;
}
}
}
else if (grandprixinfo.roundnum == (grandprixinfo.cup->numlevels+1)/2) // 3 for a 5-map cup
{
// todo any other condition?
{
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_BONUS];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum]
&& mapheaderinfo[cupLevelNum]->typeoflevel & (TOL_BOSS|TOL_BATTLE))
{
grandprixinfo.eventmode = GPEVENT_BONUS;
nextmap = cupLevelNum;
}
}
}
if (grandprixinfo.eventmode != GPEVENT_NONE)
{
// nextmap is set above
const INT32 newtol = mapheaderinfo[nextmap]->typeoflevel;
if (newtol & TOL_SPECIAL)
{
specialStage.active = true;
specialStage.encore = grandprixinfo.encore;
}
else //(if newtol & (TOL_BATTLE|TOL_BOSS)) -- safe to assume??
{
G_SetGametype(GT_BATTLE);
if (gametype != lastgametype)
D_GameTypeChanged(lastgametype);
if (newtol & TOL_BOSS)
{
K_ResetBossInfo();
bossinfo.boss = true;
bossinfo.encore = grandprixinfo.encore;
}
}
}
else if (grandprixinfo.roundnum >= grandprixinfo.cup->numlevels) // On final map
{
nextmap = NEXTMAP_CEREMONY; // ceremonymap
}
else
{
// Proceed to next map
const INT32 cupLevelNum =grandprixinfo.cup->cachedlevels[grandprixinfo.roundnum];
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[grandprixinfo.roundnum];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum])
{

View file

@ -182,7 +182,13 @@ void K_CheckBumpers(void)
K_KartUpdatePosition(&players[i]);
for (i = 0; i < MAXPLAYERS; i++) // and it can't be merged with this loop because it needs to be all updated before exiting... multi-loops suck...
{
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
P_DoPlayerExit(&players[i]);
}
}
void K_CheckEmeralds(player_t *player)

View file

@ -1261,18 +1261,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
INT32 turnamt = 0;
line_t *botController = NULL;
// Can't build a ticcmd if we aren't spawned...
if (!player->mo)
{
return;
}
// Remove any existing controls
memset(cmd, 0, sizeof(ticcmd_t));
if (gamestate != GS_LEVEL)
if (gamestate != GS_LEVEL || !player->mo || player->spectator)
{
// Not in a level.
// Not in the level.
return;
}

View file

@ -332,6 +332,16 @@ void K_UpdateGrandPrixBots(void)
UINT16 newrivalscore = 0;
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || !players[i].bot)
{
continue;
}
players[i].spectator = (grandprixinfo.eventmode != GPEVENT_NONE);
}
// Find the rival.
for (i = 0; i < MAXPLAYERS; i++)
{
@ -518,9 +528,11 @@ void K_RetireBots(void)
UINT8 i;
if (grandprixinfo.gp == true && grandprixinfo.roundnum >= grandprixinfo.cup->numlevels)
if (grandprixinfo.gp == true
&& ((grandprixinfo.roundnum >= grandprixinfo.cup->numlevels)
|| grandprixinfo.eventmode != GPEVENT_NONE))
{
// Was last map, no replacement.
// No replacement.
return;
}
@ -576,18 +588,13 @@ void K_RetireBots(void)
{
player_t *bot = NULL;
if (!playeringame[i] || !players[i].bot)
if (!playeringame[i] || !players[i].bot || players[i].spectator)
{
continue;
}
bot = &players[i];
if (bot->spectator)
{
continue;
}
if (bot->pflags & PF_NOCONTEST)
{
UINT8 skinnum = defaultbotskin;

View file

@ -16,6 +16,10 @@
#include "doomdef.h"
#include "doomstat.h"
#define GPEVENT_NONE 0
#define GPEVENT_BONUS 1
#define GPEVENT_SPECIAL 2
extern struct grandprixinfo
{
boolean gp; ///< If true, then we are in a Grand Prix.
@ -26,6 +30,7 @@ extern struct grandprixinfo
boolean masterbots; ///< If true, all bots should be max difficulty (Master Mode)
boolean initalize; ///< If true, we need to initialize a new session.
boolean wonround; ///< If false, then we retry the map instead of going to the next.
UINT8 eventmode; ///< See GPEVENT_ constants
} grandprixinfo;

View file

@ -12,6 +12,7 @@
#include "k_hud.h"
#include "k_kart.h"
#include "k_battle.h"
#include "k_grandprix.h"
#include "k_boss.h"
#include "k_color.h"
#include "k_director.h"
@ -1406,7 +1407,15 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
else
{
drawtime = timelimitintics - drawtime;
if (drawtime < 5*TICRATE)
if (secretextratime)
;
else if (extratimeintics)
{
jitter = 2;
if (leveltime & 1)
jitter = -jitter;
}
else if (drawtime < 5*TICRATE)
{
jitter = 1;
if (drawtime & 2)
@ -3904,7 +3913,7 @@ static void K_drawBattleFullscreen(void)
if (K_IsPlayerLosing(stplyr))
p = kp_battlelose;
else if (stplyr->position == 1)
else if (stplyr->position == 1 && (!battlecapsules || numtargets >= maptargets))
p = kp_battlewin;
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, p, NULL);
@ -3952,7 +3961,7 @@ static void K_drawBattleFullscreen(void)
}
}
if (netgame && !stplyr->spectator) // FREE PLAY?
// FREE PLAY?
{
UINT8 i;
@ -3961,11 +3970,11 @@ static void K_drawBattleFullscreen(void)
{
if (i == displayplayers[0])
continue;
if (playeringame[i] && !stplyr->spectator)
return;
if (playeringame[i] && !players[i].spectator)
break;
}
if (LUA_HudEnabled(hud_freeplay))
if (i != MAXPLAYERS)
K_drawKartFreePlay();
}
}
@ -4359,8 +4368,13 @@ static void K_drawTrickCool(void)
void K_drawKartFreePlay(void)
{
// no splitscreen support because it's not FREE PLAY if you have more than one player in-game
// (you fool, you can take splitscreen online. :V)
// Doesn't support splitscreens higher than 2 for real estate reasons.
if (!LUA_HudEnabled(hud_freeplay))
return;
if (modeattacking || grandprixinfo.gp || bossinfo.boss || stplyr->spectator)
return;
if (lt_exitticker < TICRATE/2)
return;
@ -4369,7 +4383,7 @@ void K_drawKartFreePlay(void)
return;
V_DrawKartString((BASEVIDWIDTH - (LAPS_X+1)) - 72, // mirror the laps thingy
LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT, "FREE PLAY");
LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_SPLITSCREEN, "FREE PLAY");
}
static void
@ -4733,11 +4747,8 @@ void K_drawKartHUD(void)
V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem);
// Draw FREE PLAY.
if (islonesome && !modeattacking && !bossinfo.boss && !stplyr->spectator)
{
if (LUA_HudEnabled(hud_freeplay))
if (islonesome)
K_drawKartFreePlay();
}
if (r_splitscreen == 0 && (stplyr->pflags & PF_WRONGWAY) && ((leveltime / 8) & 1))
{

View file

@ -40,6 +40,7 @@
#include "k_collide.h"
#include "k_follower.h"
#include "k_objects.h"
#include "k_grandprix.h"
#include "k_specialstage.h"
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
@ -158,6 +159,29 @@ void K_TimerInit(void)
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
K_BattleInit();
timelimitintics = extratimeintics = secretextratime = 0;
if ((gametyperules & GTR_TIMELIMIT) && !bossinfo.boss)
{
if (!K_CanChangeRules())
{
if (grandprixinfo.gp)
{
timelimitintics = (20*TICRATE);
}
else
{
timelimitintics = timelimits[gametype] * (60*TICRATE);
}
}
else
#ifndef TESTOVERTIMEINFREEPLAY
if (!battlecapsules)
#endif
{
timelimitintics = cv_timelimit.value * (60*TICRATE);
}
}
if (inDuel == true)
{
K_SpawnDuelOnlyItems();
@ -331,10 +355,10 @@ boolean K_IsPlayerLosing(player_t *player)
INT32 winningpos = 1;
UINT8 i, pcount = 0;
if (battlecapsules && player->bumpers <= 0)
return true; // DNF in break the capsules
if (battlecapsules && numtargets == 0)
return true; // Didn't even TRY?
if (bossinfo.boss)
if (battlecapsules || bossinfo.boss)
return (player->bumpers <= 0); // anything short of DNF is COOL
if (player->position == 1)

View file

@ -4032,9 +4032,10 @@ void A_AttractChase(mobj_t *actor)
if (
actor->tracer->player && actor->tracer->health
&& actor->tracer->player->itemtype == KITEM_LIGHTNINGSHIELD
&& (gametyperules & GTR_SPHERES)
|| (actor->tracer->player->itemtype == KITEM_LIGHTNINGSHIELD
&& RINGTOTAL(actor->tracer->player) < 20
&& !(actor->tracer->player->pflags & PF_RINGLOCK)
&& !(actor->tracer->player->pflags & PF_RINGLOCK))
//&& P_CheckSight(actor, actor->tracer)
)
{

View file

@ -603,19 +603,37 @@ void P_CheckTimeLimit(void)
{
INT32 i;
if (exitcountdown)
return;
if (!timelimitintics)
return;
#ifndef TESTOVERTIMEINFREEPLAY
if (battlecapsules && (grandprixinfo.gp == false))
return;
#endif
if (!(gametyperules & GTR_TIMELIMIT))
return;
if (bossinfo.boss == true)
return;
if (secretextratime)
{
secretextratime--;
timelimitintics++;
}
else if (extratimeintics)
{
timelimitintics++;
if (leveltime & 1)
;
else
{
if (extratimeintics > 20)
{
extratimeintics -= 20;
timelimitintics += 20;
}
else
{
timelimitintics += extratimeintics;
extratimeintics = 0;
}
S_StartSound(NULL, sfx_ptally);
}
}
if (leveltime < (timelimitintics + starttime))
return;
@ -705,16 +723,19 @@ void P_CheckPointLimit(void)
{
INT32 i;
if (!cv_pointlimit.value)
if (exitcountdown)
return;
if (!(multiplayer || netgame))
if (!K_CanChangeRules())
return;
if (!cv_pointlimit.value)
return;
if (!(gametyperules & GTR_POINTLIMIT))
return;
if (bossinfo.boss == true)
if (battlecapsules)
return;
// pointlimit is nonzero, check if it's been reached by this player
@ -1422,19 +1443,21 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_BATTLECAPSULE:
{
UINT8 i;
mobj_t *cur;
angle_t dir = 0;
numtargets++;
target->fuse = 16;
target->flags |= MF_NOCLIP|MF_NOCLIPTHING;
if (inflictor)
{
P_Thrust(target,
R_PointToAngle2(inflictor->x, inflictor->y, target->x, target->y),
P_AproxDistance(inflictor->momx, inflictor->momy) / 12
);
dir = R_PointToAngle2(inflictor->x, inflictor->y, target->x, target->y);
P_Thrust(target, dir, P_AproxDistance(inflictor->momx, inflictor->momy)/12);
}
else if (source)
dir = R_PointToAngle2(source->x, source->y, target->x, target->y);
target->momz += 8 * target->scale * P_MobjFlip(target);
target->flags &= ~MF_NOGRAVITY;
@ -1467,12 +1490,47 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
S_StartSound(target, sfx_mbs60);
// All targets busted!
if (numtargets >= maptargets)
if ((gametyperules & GTR_POINTLIMIT) && (source && source->player))
{
UINT8 i;
/*mobj_t * ring;
for (i = 0; i < 2; i++)
{
dir += (ANGLE_MAX/3);
ring = P_SpawnMobj(target->x, target->y, target->z, MT_RING);
ring->angle = dir;
P_InstaThrust(ring, dir, 16*ring->scale);
ring->momz = 8 * target->scale * P_MobjFlip(target);
P_SetTarget(&ring->tracer, source);
source->player->pickuprings++;
}*/
P_AddPlayerScore(source->player, 1);
K_SpawnBattlePoints(source->player, NULL, 1);
}
// All targets busted!
if (++numtargets >= maptargets)
{
boolean givelife = false;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
P_DoPlayerExit(&players[i]);
if (!grandprixinfo.gp)
continue;
P_GivePlayerLives(&players[i], 1);
givelife = true;
}
if (givelife)
S_StartSound(NULL, sfx_cdfm73);
}
else if (timelimitintics)
{
S_StartSound(NULL, sfx_s221);
extratimeintics += 10*TICRATE;
secretextratime = TICRATE/2;
}
}
break;

View file

@ -4596,6 +4596,10 @@ static void P_NetArchiveMisc(boolean resending)
WRITEUINT32(save_p, starttime);
WRITEUINT8(save_p, numbulbs);
WRITEUINT32(save_p, timelimitintics);
WRITEUINT32(save_p, extratimeintics);
WRITEUINT32(save_p, secretextratime);
// Is it paused?
if (paused)
WRITEUINT8(save_p, 0x2f);

View file

@ -3565,7 +3565,7 @@ static void P_InitLevelSettings(void)
// SRB2Kart: map load variables
if (grandprixinfo.gp == true)
{
if (gametype == GT_BATTLE)
if ((gametyperules & GTR_BUMPERS))
{
gamespeed = KARTSPEED_EASY;
}
@ -3584,6 +3584,9 @@ static void P_InitLevelSettings(void)
else if (modeattacking)
{
// Just play it safe and set everything
if ((gametyperules & GTR_BUMPERS))
gamespeed = KARTSPEED_EASY;
else
gamespeed = KARTSPEED_HARD;
franticitems = false;
}
@ -3843,7 +3846,6 @@ static void P_InitPlayers(void)
static void P_InitGametype(void)
{
size_t i;
boolean canchangerules = K_CanChangeRules();
spectateGriefed = 0;
K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped
@ -3855,7 +3857,7 @@ static void P_InitGametype(void)
if (gametyperules & GTR_CIRCUIT)
{
if (canchangerules && cv_numlaps.value
if (K_CanChangeRules() && cv_numlaps.value
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_numlaps.value)))
{
@ -3875,22 +3877,6 @@ static void P_InitGametype(void)
numlaps = 0;
}
if ((gametyperules & GTR_TIMELIMIT) && !bossinfo.boss)
{
if (!canchangerules)
{
timelimitintics = timelimits[gametype] * (60*TICRATE);
}
else
{
timelimitintics = cv_timelimit.value * (60*TICRATE);
}
}
else
{
timelimitintics = 0;
}
wantedcalcdelay = wantedfrequency*2;
for (i = 0; i < NUMKARTITEMS-1; i++)

View file

@ -505,7 +505,6 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings)
num_rings -= (test+20);
player->rings += num_rings;
//player->totalring += num_rings; // Used for GP lives later -- maybe you might want to move this earlier to discourage ring debt...
return num_rings;
}
@ -1263,6 +1262,8 @@ void P_DoPlayerExit(player_t *player)
player->exiting = 1;
if (!player->spectator)
{
if ((gametyperules & GTR_CIRCUIT)) // If in Race Mode, allow
{
K_KartUpdatePosition(player);
@ -1336,6 +1337,7 @@ void P_DoPlayerExit(player_t *player)
}
}
}
}
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation

View file

@ -437,6 +437,7 @@ static patch_t *tcol2;
static patch_t *tcroundbar;
static patch_t *tcround;
static patch_t *tcbonus;
static patch_t *tccircletop;
static patch_t *tccirclebottom;
@ -446,6 +447,8 @@ static patch_t *tcbanner;
static patch_t *tcbanner2;
static patch_t *tcroundnum[10];
static patch_t *tcroundbonus;
static patch_t *tcactnum[10];
static patch_t *tcact;
@ -495,6 +498,7 @@ static void ST_cacheLevelTitle(void)
tcroundbar = (patch_t *)W_CachePatchName("TCBB0", PU_HUDGFX);
tcround = (patch_t *)W_CachePatchName("TCROUND", PU_HUDGFX);
tcbonus = (patch_t *)W_CachePatchName("TCBONUS", PU_HUDGFX);
tccircletop = (patch_t *)W_CachePatchName("TCSN1", PU_HUDGFX);
tccirclebottom =(patch_t *)W_CachePatchName("TCSN2", PU_HUDGFX);
@ -514,6 +518,7 @@ static void ST_cacheLevelTitle(void)
sprintf(buf, "TT_RND%d", i);
tcroundnum[i-1] = (patch_t *)W_CachePatchName(buf, PU_HUDGFX);
}
tcroundbonus = (patch_t *)W_CachePatchName("TT_RNDB", PU_HUDGFX);
// Cache act #
for (i=0; i < 10; i++)
@ -579,7 +584,7 @@ void ST_runTitleCard(void)
{
boolean run = !(paused || P_AutoPause());
INT32 auxticker;
boolean gp = (grandprixinfo.gp && grandprixinfo.roundnum); // check whether we're in grandprix
boolean gp = (marathonmode || (grandprixinfo.gp && grandprixinfo.roundnum));
if (!G_IsTitleCardAvailable())
return;
@ -764,7 +769,7 @@ void ST_drawTitleCard(void)
char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
char *zonttl = mapheaderinfo[gamemap-1]->zonttl; // SRB2kart
UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
boolean gp = (grandprixinfo.gp && grandprixinfo.roundnum);
boolean gp = (marathonmode || (grandprixinfo.gp && grandprixinfo.roundnum));
INT32 acttimer;
fixed_t actscale;
@ -895,7 +900,9 @@ void ST_drawTitleCard(void)
V_DrawFixedPatch(roundx*FRACUNIT, ((-32) + (lt_ticker%32))*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, tcroundbar, NULL);
// Draw ROUND text
if (gp)
V_DrawFixedPatch((roundx+10)*FRACUNIT, roundy*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, tcround, NULL);
V_DrawFixedPatch((roundx+10)*FRACUNIT, roundy*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT,
((grandprixinfo.gp && grandprixinfo.eventmode) ? tcbonus : tcround),
NULL);
// round num background
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebg, NULL);
@ -912,9 +919,31 @@ void ST_drawTitleCard(void)
}
}
// If possible, draw round number
if (gp && grandprixinfo.roundnum > 0 && grandprixinfo.roundnum < 11) // Check boundaries JUST IN CASE.
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tcroundnum[grandprixinfo.roundnum-1], NULL);
// If possible, draw round number/icon
if (gp)
{
patch_t *roundico = NULL;
if (marathonmode)
; // TODO: Ruby
else switch (grandprixinfo.eventmode)
{
case GPEVENT_BONUS:
roundico = tcroundbonus;
break;
/*case GPEVENT_SPECIAL:
; // TODO: Emerald/mount
break;*/
case GPEVENT_NONE:
if (grandprixinfo.roundnum > 0 && grandprixinfo.roundnum < 11) // Check boundaries JUST IN CASE.
roundico = tcroundnum[grandprixinfo.roundnum-1];
break;
default:
break;
}
if (roundico)
V_DrawFixedPatch(roundnumx*FRACUNIT, roundnumy*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, roundico, NULL);
}
// Draw both halves of the egg
V_DrawFixedPatch(eggx1*FRACUNIT, eggy1*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccircletop, NULL);

View file

@ -753,11 +753,13 @@ void Y_DetermineIntermissionType(void)
// set to int_none initially
intertype = int_none;
if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
else if (gametype == GT_RACE)
if (gametype == GT_RACE)
intertype = int_race;
else if (gametype == GT_BATTLE)
{
if (grandprixinfo.gp == true && bossinfo.boss == false)
intertype = int_none;
else
{
UINT8 i = 0, nump = 0;
for (i = 0; i < MAXPLAYERS; i++)
@ -768,6 +770,9 @@ void Y_DetermineIntermissionType(void)
}
intertype = (nump < 2 ? int_battletime : int_battle);
}
}
else //if (intermissiontypes[gametype] != int_none)
intertype = intermissiontypes[gametype];
}
//