diff --git a/src/f_finale.c b/src/f_finale.c index ac6312e7f..a6c2c1f00 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -910,7 +910,7 @@ void F_IntroTicker(void) ResetSkipSequences(); CV_StealthSetValue(&cv_kartbot, 9); CV_StealthSetValue(&cv_maxplayers, 8); - D_MapChange(G_RandMap(TOL_RACE, UINT16_MAX-1, true, false, NULL), GT_RACE, (cv_kartencore.value == 1), true, 0, false, false); + D_MapChange(G_RandMap(TOL_RACE, UINT16_MAX-1, true, false, NULL)+1, GT_RACE, (cv_kartencore.value == 1), true, 0, false, false); return; } @@ -1118,7 +1118,7 @@ boolean F_IntroResponder(event_t *event) } // Quick skips for development/testing. See F_IntroTicker. - if (!demo.playback) + if (!demo.playback && skippableallowed) { switch(key) { diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 0098c58b2..16d6eabdc 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -49,6 +49,7 @@ #include "md5.h" // demo checksums #include "p_saveg.h" // savebuffer_t #include "g_party.h" +#include "k_director.h" // K_DirectorIsEnabled #include "core/json.hpp" // SRB2Kart @@ -4315,7 +4316,11 @@ boolean G_CheckDemoTitleEntry(void) if (menuactive || chat_on) return false; - if (!G_PlayerInputDown(0, gc_b, 0) && !G_PlayerInputDown(0, gc_x, 0)) + // Input conflict + if (gamestate == GS_LEVEL && camera[0].freecam) + return false; + + if (!G_PlayerInputDown(0, gc_b, 0)) return false; demo.willsave = true; diff --git a/src/g_game.c b/src/g_game.c index 31cd80b9a..204d6ed84 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3932,7 +3932,11 @@ tryAgain: continue; } - if (numPlayers == 2 && gametype == GT_RACE && ((mapheaderinfo[i]->levelflags & LF_SECTIONRACE) == LF_SECTIONRACE)) + // TODO - We don't have guaranteed access to gametype/rules of TOL. + // If revising in future and willing to break this function open, + // this should be checking for GTR_CIRCUIT and not cooperative + // (but K_Cooperative also won't be correct inside this func). + if (numPlayers == 2 && gametype != GT_SPECIAL && ((mapheaderinfo[i]->levelflags & LF_SECTIONRACE) == LF_SECTIONRACE)) { // Duel doesn't support sprints. continue; diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 9734d8cdc..4f91c412f 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -6448,7 +6448,7 @@ static void K_drawKartMinimap(void) } } - if (gametype == GT_BATTLE && Obj_GetNextUFOSpawner() != NULL) + if ((gametyperules & GTR_PAPERITEMS) && Obj_GetNextUFOSpawner() != NULL) { const INT32 prevsplitflags = splitflags; mobj_t *spawner = Obj_GetNextUFOSpawner(); diff --git a/src/k_kart.c b/src/k_kart.c index 1fe6f4c3c..5c39a687f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3119,7 +3119,7 @@ fixed_t K_PlayerTripwireSpeedThreshold(const player_t *player) UINT32 distance = K_GetItemRouletteDistance(player, 8); - if (gametype == GT_RACE && M_NotFreePlay() && !modeattacking) + if ((gametyperules & GTR_CIRCUIT) && !K_Cooperative() && M_NotFreePlay() && !modeattacking) { if (distance < SCAMDIST) // Players near 1st need more speed! { @@ -3401,58 +3401,64 @@ void K_SpawnWaterRunParticles(mobj_t *mobj) y2 = y2 + P_ReturnThrustY(mobj, forwardangle, playerVisualRadius); // Left - // underlay - water = P_SpawnMobj(x1, y1, - ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; - water->destscale = trailScale; - water->momx = mobj->momx; - water->momy = mobj->momy; - water->momz = mobj->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, curUnderlayFrame); - P_SetTarget(&water->owner, mobj); - water->renderflags |= RF_REDUCEVFX; + if (!mobj->player || mobj->player->aizdriftstrat <= 0) + { + // underlay + water = P_SpawnMobj(x1, y1, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); + water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, curUnderlayFrame); + P_SetTarget(&water->owner, mobj); + water->renderflags |= RF_REDUCEVFX; - // overlay - water = P_SpawnMobj(x1, y1, - ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; - water->destscale = trailScale; - water->momx = mobj->momx; - water->momy = mobj->momy; - water->momz = mobj->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, curOverlayFrame); - P_SetTarget(&water->owner, mobj); - water->renderflags |= RF_REDUCEVFX; + // overlay + water = P_SpawnMobj(x1, y1, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); + water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, curOverlayFrame); + P_SetTarget(&water->owner, mobj); + water->renderflags |= RF_REDUCEVFX; + } // Right - // Underlay - water = P_SpawnMobj(x2, y2, - ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; - water->destscale = trailScale; - water->momx = mobj->momx; - water->momy = mobj->momy; - water->momz = mobj->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, curUnderlayFrame); - P_SetTarget(&water->owner, mobj); - water->renderflags |= RF_REDUCEVFX; + if (!mobj->player || mobj->player->aizdriftstrat >= 0) + { + // Underlay + water = P_SpawnMobj(x2, y2, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, mobj->scale) : mobj->watertop), MT_WATERTRAILUNDERLAY); + water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, curUnderlayFrame); + P_SetTarget(&water->owner, mobj); + water->renderflags |= RF_REDUCEVFX; - // Overlay - water = P_SpawnMobj(x2, y2, - ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; - water->destscale = trailScale; - water->momx = mobj->momx; - water->momy = mobj->momy; - water->momz = mobj->momz; - P_SetScale(water, trailScale); - P_SetMobjState(water, curOverlayFrame); - P_SetTarget(&water->owner, mobj); - water->renderflags |= RF_REDUCEVFX; + // Overlay + water = P_SpawnMobj(x2, y2, + ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, mobj->scale) : mobj->watertop), MT_WATERTRAIL); + water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + water->destscale = trailScale; + water->momx = mobj->momx; + water->momy = mobj->momy; + water->momz = mobj->momz; + P_SetScale(water, trailScale); + P_SetMobjState(water, curOverlayFrame); + P_SetTarget(&water->owner, mobj); + water->renderflags |= RF_REDUCEVFX; + } if (!S_SoundPlaying(mobj, sfx_s3kdbs)) { @@ -4618,7 +4624,7 @@ static void K_HandleRaceSplits(player_t *player, tic_t time, UINT8 checkpoint) void K_CheckpointCrossAward(player_t *player) { - if (gametype != GT_RACE) + if (!(gametyperules & GTR_CIRCUIT) || K_Cooperative()) return; if (!demo.playback && G_TimeAttackStart()) @@ -10578,7 +10584,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->follower && fls >= 0 && fls < numfollowers) { const follower_t *fl = &followers[fls]; - S_StartSound(NULL, fl->hornsound); + S_StartSound(player->follower, fl->hornsound); } S_StartSound(player->mo, sfx_kc33); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index af9187074..a82aaebd7 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2383,7 +2383,9 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) if (p != NULL) { V_DrawFixedPatch((x+30)*FRACUNIT, (y+84)*FRACUNIT, FRACUNIT, 0, pwrlv, colormap); - V_DrawCenteredTimerString(x+30, y+87, 0, va("%d", p->wins)); + K_DrawGameControl(x+30, y+87, 0, va("%d", p->wins), 1, + (p->wins >= 1000 ? TINYTIMER_FONT : TIMER_FONT), + 0); } @@ -6424,11 +6426,11 @@ void M_DrawPause(void) K_DrawGameControl(4, 184 - 60 + offset/2, 0, " Steering", 0, TINY_FONT, 0); K_DrawGameControl(4, 184 - 45 + offset/2, 0, " Accelerate", 0, TINY_FONT, 0); K_DrawGameControl(4, 184 - 30 + offset/2, 0, " Look Back", 0, TINY_FONT, 0); - K_DrawGameControl(4, 184 - 15 + offset/2, 0, " Spindash", 0, TINY_FONT, 0); - K_DrawGameControl(4, 184 - 0 + offset/2, 0, " Item/Rings", 0, TINY_FONT, 0); + K_DrawGameControl(4, 184 - 15 + offset/2, 0, " Spin Dash", 0, TINY_FONT, 0); + K_DrawGameControl(4, 184 - 0 + offset/2, 0, " Item / Rings", 0, TINY_FONT, 0); K_DrawGameControl(90, 184 - 45 + offset/2, 0, " Brake", 0, TINY_FONT, 0); - K_DrawGameControl(90, 184 - 30 + offset/2, 0, " Respawn", 0, TINY_FONT, 0); + K_DrawGameControl(90, 184 - 30 + offset/2, 0, " Bail / Burst", 0, TINY_FONT, 0); K_DrawGameControl(90, 184 - 15 + offset/2, 0, " Dialogue / Action", 0, TINY_FONT, 0); K_DrawGameControl(90, 184 - 0 + offset/2, 0, " Drift", 0, TINY_FONT, 0); } @@ -8763,6 +8765,7 @@ static void M_DrawStatsMaps(void) i = -1; + const boolean allowsealed = M_SecretUnlocked(SECRET_SPECIALATTACK, true); const boolean allowencore = M_SecretUnlocked(SECRET_ENCORE, true); const boolean allowspb = M_SecretUnlocked(SECRET_SPBATTACK, true); boolean allowtime = false; @@ -8790,7 +8793,11 @@ static void M_DrawStatsMaps(void) if (mapheaderinfo[mnum]->typeoflevel & TOL_TUTORIAL) str = "TUTORIAL MODE"; - else if (mapheaderinfo[mnum]->cup) + else if (mapheaderinfo[mnum]->cup + && (!(mapheaderinfo[mnum]->typeoflevel & TOL_SPECIAL) // not special + || gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found + || mapheaderinfo[mnum]->cup->id >= basenumkartcupheaders // custom content + || allowsealed)) // true order str = va("%s CUP", mapheaderinfo[mnum]->cup->realname); else str = "LOST & FOUND"; diff --git a/src/menus/extras-statistics.cpp b/src/menus/extras-statistics.cpp index d5bdf990c..6d2b54d0e 100644 --- a/src/menus/extras-statistics.cpp +++ b/src/menus/extras-statistics.cpp @@ -26,7 +26,20 @@ static boolean M_StatisticsAddMap(UINT16 map, cupheader_t *cup, boolean *headere if (!mapheaderinfo[map]) return false; - if (mapheaderinfo[map]->cup != cup) + if (mapheaderinfo[map]->typeoflevel & TOL_SPECIAL) + { + if (gamedata->sealedswaps[GDMAX_SEALEDSWAPS-1] != NULL // all found + || (mapheaderinfo[map]->cup + && mapheaderinfo[map]->cup->id >= basenumkartcupheaders) // custom content + || M_SecretUnlocked(SECRET_SPECIALATTACK, true)) // true order + { + if (mapheaderinfo[map]->cup != cup) + return false; + } + else if (cup) // Appear under Lost & Found until you've ordered them. + return false; + } + else if (mapheaderinfo[map]->cup != cup) return false; if (((mapheaderinfo[map]->typeoflevel & TOL_TUTORIAL) == TOL_TUTORIAL) != tutorial) diff --git a/src/menus/main-goner.cpp b/src/menus/main-goner.cpp index cea76976c..8074bc8a2 100644 --- a/src/menus/main-goner.cpp +++ b/src/menus/main-goner.cpp @@ -1603,6 +1603,8 @@ void M_GonerPlayground(INT32 choice) multiplayer = true; + levellist.newgametype = GT_TUTORIAL; + levellist.netgame = false; M_MenuToLevelPreamble(0, false); D_MapChange( diff --git a/src/objects/checkpoint.cpp b/src/objects/checkpoint.cpp index 81b93feb0..195e1436a 100644 --- a/src/objects/checkpoint.cpp +++ b/src/objects/checkpoint.cpp @@ -584,7 +584,11 @@ void Obj_CheckpointThink(mobj_t* end) void Obj_CrossCheckpoints(player_t* player, fixed_t old_x, fixed_t old_y) { - if (player->exiting || player->laps == 0) // can't cross checkpoints when exiting, or before the first lap starts + if (player->exiting + || ( + (gametyperules & GTR_CIRCUIT) + && (player->laps == 0) + )) { return; } diff --git a/src/p_inter.c b/src/p_inter.c index 549e61d66..f8d3f162a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1922,6 +1922,44 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget } } + if (target->player->spectator == false) + { + UINT32 skinflags = (demo.playback) + ? demo.skinlist[demo.currentskinid[(target->player-players)]].flags + : skins[target->player->skin]->flags; + + if (skinflags & SF_IRONMAN) + { + target->skin = skins[target->player->skin]; + target->player->charflags = skinflags; + K_SpawnMagicianParticles(target, 5); + S_StartSound(target, sfx_slip); + } + + target->renderflags &= ~RF_DONTDRAW; + } + + K_DropEmeraldsFromPlayer(target->player, target->player->emeralds); + + target->player->carry = CR_NONE; + + K_KartResetPlayerColor(target->player); + + P_ResetPlayer(target->player); + +#define PlayerPointerRemove(field) \ + if (P_MobjWasRemoved(field) == false) \ + { \ + P_RemoveMobj(field); \ + P_SetTarget(&field, NULL); \ + } + + PlayerPointerRemove(target->player->stumbleIndicator); + PlayerPointerRemove(target->player->wavedashIndicator); + PlayerPointerRemove(target->player->trickIndicator); + +#undef PlayerPointerRemove + if (gametyperules & GTR_BUMPERS) { if (battleovertime.enabled >= 10*TICRATE) // Overtime Barrier is armed @@ -2684,7 +2722,6 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, if (modeattacking & ATTACKING_SPB) { - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); return true; } @@ -2700,6 +2737,9 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, // disappearifies, but still gotta put items back in play break; + case DMG_TIMEOVER: + player->pflags |= PF_ELIMINATED; + //FALLTHRU default: // Everything else REALLY kills if (leveltime < starttime) @@ -2709,52 +2749,6 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, break; } - if (player->spectator == false) - { - UINT32 skinflags = (demo.playback) - ? demo.skinlist[demo.currentskinid[(player-players)]].flags - : skins[player->skin]->flags; - - if (skinflags & SF_IRONMAN) - { - player->mo->skin = skins[player->skin]; - player->charflags = skinflags; - K_SpawnMagicianParticles(player->mo, 5); - S_StartSound(player->mo, sfx_slip); - } - - player->mo->renderflags &= ~RF_DONTDRAW; - } - - K_DropEmeraldsFromPlayer(player, player->emeralds); - //K_SetHitLagForObjects(player->mo, inflictor, source, MAXHITLAGTICS, true); - - player->carry = CR_NONE; - - K_KartResetPlayerColor(player); - - P_ResetPlayer(player); - - P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - -#define PlayerPointerRemove(field) \ - if (P_MobjWasRemoved(field) == false) \ - { \ - P_RemoveMobj(field); \ - P_SetTarget(&field, NULL); \ - } - - PlayerPointerRemove(player->stumbleIndicator); - PlayerPointerRemove(player->wavedashIndicator); - PlayerPointerRemove(player->trickIndicator); - -#undef PlayerPointerRemove - - if (type == DMG_TIMEOVER) - { - player->pflags |= PF_ELIMINATED; - } - return true; } diff --git a/src/st_stuff.c b/src/st_stuff.c index 5263c71d8..07f17cb3d 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -34,7 +34,7 @@ #include "p_setup.h" // NiGHTS grading #include "r_fps.h" #include "m_random.h" // random index -#include "m_cond.h" // item finder +#include "k_director.h" // K_DirectorIsEnabled #ifdef HWRENDER #include "hardware/hw_main.h" @@ -1498,11 +1498,22 @@ void ST_DrawServerSplash(boolean timelimited) void ST_DrawSaveReplayHint(INT32 flags) { - K_DrawGameControl( - BASEVIDWIDTH - 2, 2, 0, - (demo.willsave && demo.titlename[0]) ? "Replay will be saved. Change title" : " or Save replay", - 2, TINY_FONT, flags|V_YELLOWMAP - ); + const char *text; + if (gamestate == GS_LEVEL && camera[0].freecam) + { + text = va( + " Disable Freecam to %s replay", + (demo.willsave && demo.titlename[0]) + ? "rename" + : "save" + ); + } + else if (demo.willsave && demo.titlename[0]) + text = "Replay will be saved. Change title"; + else + text = " Save replay"; + + K_DrawGameControl(BASEVIDWIDTH - 2, 2, 0, text, 2, TINY_FONT, flags|V_YELLOWMAP); } static fixed_t ST_CalculateFadeIn(player_t *player) diff --git a/src/v_video.cpp b/src/v_video.cpp index 3255544bd..d47125972 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1070,7 +1070,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) c &= 255; - RGBA_t color = pMasterPalette[c]; + RGBA_t color = pLocalPalette[c]; UINT8 r = (color.rgba & 0xFF); UINT8 g = (color.rgba & 0xFF00) >> 8; UINT8 b = (color.rgba & 0xFF0000) >> 16; @@ -1262,7 +1262,7 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) { auto builder = g_2d.begin_verts(); - const RGBA_t color = pMasterPalette[c]; + const RGBA_t color = pLocalPalette[c]; const float r = ((color.rgba & 0xFF000000) >> 24) / 255.f; const float g = ((color.rgba & 0xFF0000) >> 16) / 255.f; const float b = ((color.rgba & 0xFF00) >> 8) / 255.f;