All playsim-internal distinctions between Race and Battle are now gametype rules.

New:
- GTR_POWERSTONES
    - Handles spawning in Battle Emeralds (currently only works stacked with GTR_PAPERITEMS)
- GTR_ENCORE
    - Codifies that Race can use Encore and Battle can't.
- GTR_CLOSERPLAYERS
    - A gametype where players are encouraged/expected to be closer together. (All of the following was GT_BATTLE specific)
        - Drafting/tether has increased strength/effective distance
        - Spindashing is stronger
        - Invincibility chaining has less effect
        - Grow has a lower total duration
        - Flame shield is more uncontrollable

Extra functionality
- GTR_CAPSULES
    - Prevents usage of lives in Grand Prix (so Race, and the upcoming Special and Boss gametypes, can have 'em)
- GTR_CIRCUIT
    - When not present, Flame Shield has perma-full meter
    - When not present, overrides gamespeed with KARTSPEED_EASY
    - Presence of Best Lap sticker in Time Attack menu
    - Seperation between Time Attack and Break The Capsules modeattacking roulettes
- GTR_POINTLIMIT
    - Handles the switch between a gametype recording/displaying Times and Scores in a few places
    - Handles displaying "WANTED" players on the minimap

Missing simple substitutions
- A whole bunch of cases where player->bumpers was checked with gametype == GT_BATTLE rather than GTR_BUMPER
- GTR_OVERTIME handles the overtime special icon on the minimap
- GTR_BATTLESTARTS is honoured in K_DoIngamerespawn
- The Replay hut is closer to supporting custom gametypes

Removals
- GTR_LIVES
- GTR_SPECIALBOTS
    - Given that grand prix persists between modes, these are special game-controlled features and not gametype-specific.
- GTR_WANTED
    - WANTED as it existed is functionally dead
This commit is contained in:
toaster 2022-12-24 22:43:00 +00:00
parent fbc3af2096
commit 8431e52687
13 changed files with 156 additions and 157 deletions

View file

@ -2595,7 +2595,7 @@ void D_SetupVote(void)
UINT8 secondgt = G_SometimesGetDifferentGametype();
INT16 votebuffer[4] = {-1,-1,-1,0};
if ((cv_kartencore.value == 1) && (gametypedefaultrules[gametype] & GTR_CIRCUIT))
if ((cv_kartencore.value == 1) && (gametypedefaultrules[gametype] & GTR_ENCORE))
WRITEUINT8(p, (gametype|VOTEMODIFIER_ENCORE));
else
WRITEUINT8(p, gametype);
@ -3029,7 +3029,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
else if (gametype != lastgametype)
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
if (!(gametyperules & GTR_CIRCUIT) && !bossinfo.boss)
if (!(gametyperules & GTR_ENCORE) && !bossinfo.boss)
pencoremode = false;
skipprecutscene = ((flags & (1<<2)) != 0);
@ -5308,7 +5308,7 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
// Strip illegal Encore flag.
if ((gt & VOTEMODIFIER_ENCORE)
&& !(gametypedefaultrules[(gt & ~VOTEMODIFIER_ENCORE)] & GTR_CIRCUIT))
&& !(gametypedefaultrules[(gt & ~VOTEMODIFIER_ENCORE)] & GTR_ENCORE))
{
gt &= ~VOTEMODIFIER_ENCORE;
}
@ -5346,11 +5346,11 @@ static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)
// If third entry has an illelegal Encore flag... (illelegal!?)
if ((secondgt & VOTEMODIFIER_ENCORE)
&& !(gametypedefaultrules[(secondgt & ~VOTEMODIFIER_ENCORE)] & GTR_CIRCUIT))
&& !(gametypedefaultrules[(secondgt & ~VOTEMODIFIER_ENCORE)] & GTR_ENCORE))
{
secondgt &= ~VOTEMODIFIER_ENCORE;
// Apply it to the second entry instead, gametype permitting!
if (gametypedefaultrules[gt] & GTR_CIRCUIT)
if (gametypedefaultrules[gt] & GTR_ENCORE)
{
tempvotelevels[1][1] |= VOTEMODIFIER_ENCORE;
}

View file

@ -500,7 +500,7 @@ void DRPC_UpdatePresence(void)
{
snprintf(detailstr, 48, "%s%s%s",
gametype_cons_t[gametype].strvalue,
(gametype == GT_RACE) ? va(" | %s", kartspeed_cons_t[gamespeed].strvalue) : "",
(gametyperules & GTR_CIRCUIT) ? va(" | %s", kartspeed_cons_t[gamespeed].strvalue) : "",
(encoremode == true) ? " | Encore" : ""
);
discordPresence.details = detailstr;

View file

@ -478,10 +478,10 @@ enum GameTypeRules
GTR_BUMPERS = 1<<3, // Enables the bumper health system
GTR_SPHERES = 1<<4, // Replaces rings with blue spheres
GTR_PAPERITEMS = 1<<5, // Replaces item boxes with paper item spawners
GTR_WANTED = 1<<6, // unused
GTR_POWERSTONES = 1<<6, // Battle Emerald collectables.
GTR_KARMA = 1<<7, // Enables the Karma system if you're out of bumpers
GTR_ITEMARROWS = 1<<8, // Show item box arrows above players
GTR_CAPSULES = 1<<9, // Enables the wanted anti-camping system
GTR_CAPSULES = 1<<9, // Can enter Break The Capsules mode
GTR_BATTLESTARTS = 1<<10, // Use Battle Mode start positions.
GTR_POINTLIMIT = 1<<11, // Reaching point limit ends the round
@ -495,10 +495,11 @@ enum GameTypeRules
// Grand Prix rules
GTR_CAMPAIGN = 1<<17, // Handles cup-based progression
GTR_LIVES = 1<<18, // Lives system, players are forced to spectate during Game Over.
GTR_SPECIALBOTS = 1<<19, // Bot difficulty gets stronger between rounds, and the rival system is enabled.
// To be rearranged later
GTR_NOCUPSELECT = 1<<20, // Your maps are not selected via cup. ...mutually exclusive with GTR_CAMPAIGN.
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
// free: to and including 1<<31
};

View file

@ -3016,9 +3016,9 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] =
UINT32 gametypedefaultrules[NUMGAMETYPES] =
{
// Race
GTR_CAMPAIGN|GTR_CIRCUIT|GTR_BOTS,
GTR_CAMPAIGN|GTR_CIRCUIT|GTR_BOTS|GTR_ENCORE,
// Battle
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME
GTR_SPHERES|GTR_BUMPERS|GTR_PAPERITEMS|GTR_POWERSTONES|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME|GTR_CLOSERPLAYERS
};
//
@ -3241,13 +3241,7 @@ boolean G_GametypeUsesLives(void)
return false;
if ((grandprixinfo.gp == true) // In Grand Prix
&& (gametype == GT_RACE) // NOT in bonus round
&& grandprixinfo.eventmode == GPEVENT_NONE) // NOT in bonus
{
return true;
}
if (bossinfo.boss == true) // Fighting a boss?
&& !(gametyperules & GTR_CAPSULES)) // NOT in Break The Capsules
{
return true;
}
@ -3298,7 +3292,7 @@ boolean G_GametypeHasSpectators(void)
INT16 G_SometimesGetDifferentGametype(void)
{
boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE, false) || encorescramble == 1)
&& ((gametyperules|gametypedefaultrules[gametype]) & GTR_CIRCUIT));
&& (gametyperules & GTR_ENCORE));
UINT8 encoremodifier = 0;
// -- the below is only necessary if you want to use randmaps.mapbuffer here

View file

@ -196,6 +196,11 @@ void K_CheckEmeralds(player_t *player)
{
UINT8 i;
if (!(gametyperules & GTR_POWERSTONES))
{
return;
}
if (!ALLCHAOSEMERALDS(player->emeralds))
{
return;
@ -341,7 +346,7 @@ void K_RunPaperItemSpawners(void)
const boolean overtime = (battleovertime.enabled >= 10*TICRATE);
tic_t interval = 8*TICRATE;
const boolean canmakeemeralds = true; //(!(battlecapsules || bossinfo.boss));
const boolean canmakeemeralds = (gametyperules & GTR_POWERSTONES);
UINT32 emeraldsSpawned = 0;
UINT32 firstUnspawnedEmerald = 0;

View file

@ -1863,7 +1863,7 @@ static boolean K_drawKartPositionFaces(void)
ranklines--;
i = ranklines;
if (gametype == GT_BATTLE || strank <= 2) // too close to the top, or playing battle, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2)
if ((gametyperules & GTR_POINTLIMIT) || strank <= 2) // too close to the top, or playing battle, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2)
{
if (i > 4) // could be both...
i = 4;
@ -1951,7 +1951,7 @@ static boolean K_drawKartPositionFaces(void)
if (i == strank)
V_DrawScaledPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_facehighlight[(leveltime / 4) % 8]);
if (gametype == GT_BATTLE && players[rankplayer[i]].bumpers <= 0)
if ((gametyperules & GTR_BUMPERS) && players[rankplayer[i]].bumpers <= 0)
V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_ranknobumpers);
else
{
@ -2265,7 +2265,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap);
/*if (gametype == GT_BATTLE && players[tab[i].num].bumpers > 0) -- not enough space for this
/*if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumpers > 0) -- not enough space for this
{
INT32 bumperx = x+19;
V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap);
@ -2280,7 +2280,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
if (tab[i].num == whiteplayer)
V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]);
if (gametype == GT_BATTLE && players[tab[i].num].bumpers <= 0)
if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumpers <= 0)
V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers);
else
{
@ -2291,7 +2291,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
V_DrawScaledPatch(x-5, y+6, 0, kp_facenum[pos]);
}
if (gametype == GT_RACE)
if ((gametyperules & GTR_CIRCUIT))
{
#define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time))
if (scorelines >= 8)
@ -2801,6 +2801,7 @@ static void K_drawKartBumpersOrKarma(void)
}
}
#if 0
static void K_drawKartWanted(void)
{
UINT8 i, numwanted = 0;
@ -2875,6 +2876,7 @@ static void K_drawKartWanted(void)
}
}
}
#endif //if 0
static void K_drawKartPlayerCheck(void)
{
@ -3810,7 +3812,7 @@ static void K_drawKartMinimap(void)
y -= SHORT(AutomapPic->topoffset);
// Draw the super item in Battle
if (gametype == GT_BATTLE && battleovertime.enabled)
if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled)
{
if (battleovertime.enabled >= 10*TICRATE || (battleovertime.enabled & 1))
{
@ -3920,8 +3922,8 @@ static void K_drawKartMinimap(void)
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic);
// Target reticule
if ((gametype == GT_RACE && players[i].position == spbplace)
|| (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i])))
if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace)
|| ((gametyperules & GTR_POINTLIMIT) && K_IsPlayerWanted(&players[i])))
{
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
}
@ -4047,8 +4049,8 @@ static void K_drawKartMinimap(void)
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic);
// Target reticule
if ((gametype == GT_RACE && players[localplayers[i]].position == spbplace)
|| (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]])))
if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace)
|| ((gametyperules & GTR_POINTLIMIT) && K_IsPlayerWanted(&players[localplayers[i]])))
{
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
}
@ -5043,11 +5045,13 @@ void K_drawKartHUD(void)
K_drawKartNameTags();
// Draw WANTED status
#if 0
if (gametype == GT_BATTLE)
{
if (LUA_HudEnabled(hud_wanted))
K_drawKartWanted();
}
#endif
if (LUA_HudEnabled(hud_minimap))
K_drawKartMinimap();
@ -5098,21 +5102,15 @@ void K_drawKartHUD(void)
{
K_drawBossHealthBar();
}
else if (gametype == GT_RACE) // Race-only elements (not currently gametyperuleable)
else if (freecam)
;
else if ((gametyperules & GTR_POWERSTONES))
{
if (!islonesome)
{
// Draw the numerical position
K_DrawKartPositionNum(stplyr->position);
}
}
else if (gametype == GT_BATTLE) // Battle-only (ditto)
{
if (!freecam && !battlecapsules)
{
if (!battlecapsules)
K_drawKartEmeralds();
}
}
else if (!islonesome)
K_DrawKartPositionNum(stplyr->position);
}
if (LUA_HudEnabled(hud_gametypeinfo))
@ -5172,10 +5170,12 @@ void K_drawKartHUD(void)
}
// Race overlays
if (gametype == GT_RACE && !freecam)
if (!freecam)
{
if (stplyr->exiting)
K_drawKartFinish(true);
else if (!(gametyperules & GTR_CIRCUIT))
;
else if (stplyr->karthud[khud_lapanimation] && !r_splitscreen)
K_drawLapStartAnim();
}
@ -5187,7 +5187,7 @@ void K_drawKartHUD(void)
if (modeattacking || freecam) // everything after here is MP and debug only
return;
if (gametype == GT_BATTLE && !r_splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM *
if ((gametyperules & GTR_KARMA) && !r_splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM *
V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem);
// Draw FREE PLAY.

View file

@ -1270,10 +1270,9 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed
player->draftpower += add;
}
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
{
// TODO: gametyperules
// Double speed in Battle
// Double speed in smaller environments
player->draftpower += add;
}
}
@ -1333,9 +1332,8 @@ static void K_UpdateDraft(player_t *player)
minDist = 640 * player->mo->scale;
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
{
// TODO: gametyperules
minDist /= 4;
draftdistance *= 2;
leniency *= 4;
@ -2452,7 +2450,7 @@ void K_PlayOvertakeSound(mobj_t *source)
{
boolean tasteful = (!source->player || !source->player->karthud[khud_voices]);
if (!gametype == GT_RACE) // Only in race
if (!(gametyperules & GTR_CIRCUIT)) // Only in race
return;
// 4 seconds from before race begins, 10 seconds afterwards
@ -2961,8 +2959,7 @@ fixed_t K_GetSpindashChargeSpeed(player_t *player)
// (can be higher than this value when overcharged)
const fixed_t val = (10*FRACUNIT/277) + (((player->kartspeed + player->kartweight) + 2) * FRACUNIT) / 45;
// TODO: gametyperules
return (gametype == GT_BATTLE) ? (4 * val) : val;
return (gametyperules & GTR_CLOSERPLAYERS) ? (4 * val) : val;
}
// sets boostpower, speedboost, accelboost, and handleboost to whatever we need it to be
@ -3097,9 +3094,8 @@ static void K_GetKartBoostPower(player_t *player)
// 30% - 44%, each point of speed adds 1.75%
fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * ((7*FRACUNIT)/400));
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
{
// TODO: gametyperules
draftspeed *= 2;
}
@ -3222,7 +3218,7 @@ fixed_t K_GetKartAccel(player_t *player)
k_accel += 17 * (9 - player->kartspeed); // 121 - 257
// karma bomb gets 2x acceleration
if (gametype == GT_BATTLE && player->bumpers <= 0)
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
k_accel *= 2;
// Marble Garden Top gets 1200% accel
@ -3236,9 +3232,8 @@ UINT16 K_GetKartFlashing(player_t *player)
{
UINT16 tics = flashingtics;
if (gametype == GT_BATTLE)
if (gametyperules & GTR_BUMPERS)
{
// TODO: gametyperules
return 1;
}
@ -3543,6 +3538,12 @@ void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UIN
UINT8 points = 1;
boolean trapItem = false;
if (!(gametyperules & GTR_POINTLIMIT))
{
// No points in this gametype.
return;
}
if (player == NULL || victim == NULL)
{
// Invalid player or victim
@ -3578,11 +3579,8 @@ void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UIN
}
}
if (gametyperules & GTR_POINTLIMIT)
{
P_AddPlayerScore(player, points);
K_SpawnBattlePoints(player, victim, points);
}
P_AddPlayerScore(player, points);
K_SpawnBattlePoints(player, victim, points);
}
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type)
@ -5054,7 +5052,7 @@ void K_SpawnDraftDust(mobj_t *mo)
{
UINT8 leniency = (3*TICRATE)/4 + ((mo->player->kartweight-1) * (TICRATE/4));
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
leniency *= 4;
ang = mo->player->drawangle;
@ -7470,7 +7468,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_SpawnGrowShrinkParticles(player->mo, player->growshrinktimer);
}
if (gametype == GT_RACE && player->rings <= 0) // spawn ring debt indicator
if (!(gametyperules & GTR_SPHERES) && player->rings <= 0) // spawn ring debt indicator
{
mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy,
player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK);
@ -7788,7 +7786,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->eggmanexplode)
{
if (player->spectator || (gametype == GT_BATTLE && !player->bumpers))
if (player->spectator || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0))
player->eggmanexplode = 0;
else
{
@ -9330,15 +9328,18 @@ static INT32 K_FlameShieldMax(player_t *player)
UINT8 numplayers = 0;
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
if (gametyperules & GTR_CIRCUIT)
{
if (playeringame[i] && !players[i].spectator)
numplayers++;
if (players[i].position == 1)
disttofinish = players[i].distancetofinish;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
numplayers++;
if (players[i].position == 1)
disttofinish = players[i].distancetofinish;
}
}
if (numplayers <= 1 || gametype == GT_BATTLE)
if (numplayers <= 1)
{
return 16; // max when alone, for testing
// and when in battle, for chaos
@ -9592,8 +9593,7 @@ static void K_KartSpindash(player_t *player)
{
fixed_t thrust = FixedMul(player->mo->scale, player->spindash*FRACUNIT/5);
// TODO: gametyperules
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
thrust *= 2;
// Give a bit of a boost depending on charge.
@ -10400,8 +10400,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->mo->destscale = FixedMul(player->mo->destscale, SHRINK_SCALE);
}
// TODO: gametyperules
player->growshrinktimer = max(player->growshrinktimer, (gametype == GT_BATTLE ? 8 : 12) * TICRATE);
player->growshrinktimer = max(player->growshrinktimer, ((gametyperules & GTR_CLOSERPLAYERS) ? 8 : 12) * TICRATE);
if (player->invincibilitytimer > 0)
{
@ -10559,8 +10558,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY))
{
// TODO: gametyperules
const INT32 incr = gametype == GT_BATTLE ? 4 : 2;
const INT32 incr = (gametyperules & GTR_CLOSERPLAYERS) ? 4 : 2;
if (player->flamedash == 0)
{
@ -10596,8 +10594,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
player->pflags |= PF_HOLDREADY;
// TODO: gametyperules
if (gametype != GT_BATTLE || leveltime % 6 == 0)
if (!(gametyperules & GTR_CLOSERPLAYERS) || leveltime % 6 == 0)
{
if (player->flamemeter > 0)
player->flamemeter--;
@ -10719,18 +10716,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->hyudorotimer > 0)
{
INT32 hyu = hyudorotime;
if (gametype == GT_RACE)
hyu *= 2; // double in race
if (leveltime & 1)
{
player->mo->renderflags |= RF_DONTDRAW;
}
else
{
if (player->hyudorotimer >= (TICRATE/2) && player->hyudorotimer <= hyu-(TICRATE/2))
if (player->hyudorotimer >= (TICRATE/2) && player->hyudorotimer <= hyudorotime-(TICRATE/2))
player->mo->renderflags &= ~K_GetPlayerDontDrawFlag(player);
else
player->mo->renderflags &= ~RF_DONTDRAW;
@ -10743,17 +10735,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
player->mo->renderflags &= ~RF_DONTDRAW;
}
if (gametype == GT_BATTLE && player->bumpers <= 0) // dead in match? you da bomb
if (!(gametyperules & GTR_BUMPERS) || player->bumpers > 0)
{
player->mo->renderflags &= ~(RF_TRANSMASK|RF_BRIGHTMASK);
}
else // dead in match? you da bomb
{
K_DropItems(player); //K_StripItems(player);
K_StripOther(player);
player->mo->renderflags |= RF_GHOSTLY;
player->flashing = player->karmadelay;
}
else if (gametype == GT_RACE || player->bumpers > 0)
{
player->mo->renderflags &= ~(RF_TRANSMASK|RF_BRIGHTMASK);
}
if (player->trickpanel == 1)
{
@ -10966,7 +10958,7 @@ void K_CheckSpectateStatus(void)
continue;
if (leveltime > (starttime + 20*TICRATE)) // DON'T allow if the match is 20 seconds in
return;
if (gametype == GT_RACE && players[i].laps >= 2) // DON'T allow if the race is at 2 laps
if ((gametyperules & GTR_CIRCUIT) && players[i].laps >= 2) // DON'T allow if the race is at 2 laps
return;
continue;
}

View file

@ -2261,7 +2261,7 @@ void M_DrawTimeAttack(void)
laprec = mapheaderinfo[map]->mainrecord->lap;
}
if (levellist.newgametype != GT_BATTLE)
if (gametypedefaultrules[levellist.newgametype] & GTR_CIRCUIT)
{
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST LAP:");
K_drawKartTimestamp(laprec, 162+t, timeheight+6, 0, 2);
@ -3964,9 +3964,20 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
if (demoref->numlaps)
V_DrawThinString(x, y+9, V_SNAPTOTOP|V_ALLOWLOWERCASE, va("(%d laps)", demoref->numlaps));
V_DrawString(x, y+20, V_SNAPTOTOP|V_ALLOWLOWERCASE, demoref->gametype == GT_RACE ?
va("Race (%s speed)", kartspeed_cons_t[(demoref->kartspeed & ~DF_ENCORE) + 1].strvalue) :
"Battle Mode");
{
const char *gtstring = "???";
if (demoref->gametype >= gametypecount)
;
else
{
gtstring = Gametype_Names[demoref->gametype];
if ((gametypedefaultrules[demoref->gametype] & GTR_CIRCUIT))
gtstring = va("%s (%s)", gtstring, kartspeed_cons_t[(demoref->kartspeed & ~DF_ENCORE) + 1].strvalue);
}
V_DrawString(x, y+20, V_SNAPTOTOP|V_ALLOWLOWERCASE, gtstring);
}
if (!demoref->standings[0].ranking)
{
@ -3979,30 +3990,33 @@ static void M_DrawReplayHutReplayInfo(menudemo_t *demoref)
V_DrawThinString(x, y+29, V_SNAPTOTOP|highlightflags, "WINNER");
V_DrawString(x+38, y+30, V_SNAPTOTOP|V_ALLOWLOWERCASE, demoref->standings[0].name);
if (demoref->gametype == GT_RACE)
if (demoref->gametype < gametypecount)
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "TIME");
}
else
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
}
if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "SCORE");
}
else
{
V_DrawThinString(x, y+39, V_SNAPTOTOP|highlightflags, "TIME");
}
if (demoref->standings[0].timeorscore == (UINT32_MAX-1))
{
V_DrawThinString(x+32, y+39, V_SNAPTOTOP, "NO CONTEST");
}
else if (demoref->gametype == GT_RACE)
{
V_DrawRightAlignedString(x+84, y+40, V_SNAPTOTOP, va("%d'%02d\"%02d",
G_TicsToMinutes(demoref->standings[0].timeorscore, true),
G_TicsToSeconds(demoref->standings[0].timeorscore),
G_TicsToCentiseconds(demoref->standings[0].timeorscore)
));
}
else
{
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", demoref->standings[0].timeorscore));
if (demoref->standings[0].timeorscore == (UINT32_MAX-1))
{
V_DrawThinString(x+32, y+39, V_SNAPTOTOP, "NO CONTEST");
}
else if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
{
V_DrawString(x+32, y+40, V_SNAPTOTOP, va("%d", demoref->standings[0].timeorscore));
}
else
{
V_DrawRightAlignedString(x+84, y+40, V_SNAPTOTOP, va("%d'%02d\"%02d",
G_TicsToMinutes(demoref->standings[0].timeorscore, true),
G_TicsToSeconds(demoref->standings[0].timeorscore),
G_TicsToCentiseconds(demoref->standings[0].timeorscore)
));
}
}
// Character face!
@ -4197,14 +4211,16 @@ void M_DrawReplayStartMenu(void)
if (demoref->standings[i].timeorscore == UINT32_MAX-1)
V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST");
else if (demoref->gametype == GT_RACE)
else if (demoref->gametype >= gametypecount)
;
else if (gametypedefaultrules[demoref->gametype] & GTR_POINTLIMIT)
V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", demoref->standings[i].timeorscore));
else
V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d",
G_TicsToMinutes(demoref->standings[i].timeorscore, true),
G_TicsToSeconds(demoref->standings[i].timeorscore),
G_TicsToCentiseconds(demoref->standings[i].timeorscore)
));
else
V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", demoref->standings[i].timeorscore));
// Character face!

View file

@ -175,14 +175,14 @@ void K_DoIngameRespawn(player_t *player)
mapthing_t *beststart = NULL;
UINT8 numstarts = 0;
if (gametype == GT_RACE)
{
numstarts = numcoopstarts;
}
else if (gametype == GT_BATTLE)
if (gametyperules & GTR_BATTLESTARTS)
{
numstarts = numdmstarts;
}
else
{
numstarts = numcoopstarts;
}
if (numstarts > 0)
{
@ -193,17 +193,13 @@ void K_DoIngameRespawn(player_t *player)
UINT32 dist = UINT32_MAX;
mapthing_t *checkstart = NULL;
if (gametype == GT_RACE)
{
checkstart = playerstarts[i];
}
else if (gametype == GT_BATTLE)
if (gametyperules & GTR_BATTLESTARTS)
{
checkstart = deathmatchstarts[i];
}
else
{
break;
checkstart = playerstarts[i];
}
dist = (UINT32)P_AproxDistance((player->mo->x >> FRACBITS) - checkstart->x,

View file

@ -1125,27 +1125,23 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
}
else if (K_TimeAttackRules() == true)
{
switch (gametype)
kartitems_t *presetlist = K_KartItemReelTimeAttack;
// If the objective is not to go fast, it's to cause serious damage.
if (!(gametyperules & GTR_CIRCUIT))
{
case GT_RACE:
default:
presetlist = K_KartItemReelBreakTheCapsules;
for (i = 0; K_KartItemReelBreakTheCapsules[i] != KITEM_NONE; i++)
{
for (i = 0; K_KartItemReelTimeAttack[i] != KITEM_NONE; i++)
{
K_PushToRouletteItemList(roulette, K_KartItemReelTimeAttack[i]);
}
break;
}
case GT_BATTLE:
{
for (i = 0; K_KartItemReelBreakTheCapsules[i] != KITEM_NONE; i++)
{
K_PushToRouletteItemList(roulette, K_KartItemReelBreakTheCapsules[i]);
}
break;
K_PushToRouletteItemList(roulette, K_KartItemReelBreakTheCapsules[i]);
}
}
for (i = 0; presetlist[i] != KITEM_NONE; i++)
{
K_PushToRouletteItemList(roulette, presetlist[i]);
}
return;
}

View file

@ -2198,7 +2198,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{
tic_t kinvextend;
if (gametype == GT_BATTLE)
if (gametyperules & GTR_CLOSERPLAYERS)
kinvextend = 2*TICRATE;
else
kinvextend = 5*TICRATE;

View file

@ -6163,7 +6163,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
mobj->color = mobj->target->color;
K_MatchGenericExtraFlags(mobj, mobj->target);
if ((gametype == GT_RACE || mobj->target->player->bumpers <= 0)
if ((!(gametyperules & GTR_BUMPERS) || mobj->target->player->bumpers <= 0)
#if 1 // Set to 0 to test without needing to host
|| (P_IsDisplayPlayer(mobj->target->player))
#endif
@ -8362,7 +8362,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
statenum_t state = (mobj->state-states);
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|| (gametype == GT_RACE || mobj->target->player->bumpers))
|| (!(gametyperules & GTR_BUMPERS) || mobj->target->player->bumpers))
{
P_RemoveMobj(mobj);
return false;
@ -9389,12 +9389,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
// FALLTHRU
case MT_SPHEREBOX:
if (gametype == GT_BATTLE && mobj->threshold == 70)
if (mobj->threshold == 70)
{
mobj->color = K_RainbowColor(leveltime);
mobj->colorized = true;
if (battleovertime.enabled)
if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled)
{
angle_t ang = FixedAngle((leveltime % 360) << FRACBITS);
fixed_t z = battleovertime.z;

View file

@ -6857,7 +6857,7 @@ static void P_InitLevelSettings(void)
// SRB2Kart: map load variables
if (grandprixinfo.gp == true)
{
if ((gametyperules & GTR_BUMPERS))
if (!(gametyperules & GTR_CIRCUIT))
{
gamespeed = KARTSPEED_EASY;
}
@ -6875,8 +6875,7 @@ static void P_InitLevelSettings(void)
}
else if (modeattacking)
{
// Just play it safe and set everything
if ((gametyperules & GTR_BUMPERS))
if (!(gametyperules & GTR_CIRCUIT))
gamespeed = KARTSPEED_EASY;
else
gamespeed = KARTSPEED_HARD;
@ -6884,7 +6883,7 @@ static void P_InitLevelSettings(void)
}
else
{
if ((gametyperules & GTR_BUMPERS))
if (!(gametyperules & GTR_CIRCUIT))
gamespeed = KARTSPEED_EASY;
else
{