diff --git a/src/doomstat.h b/src/doomstat.h index edf5fe334..0ba0f3b1d 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -821,6 +821,7 @@ extern boolean thwompsactive; extern UINT8 lastLowestLap; extern SINT8 spbplace; extern boolean rainbowstartavailable; +extern tic_t linecrossed; extern boolean inDuel; extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines explode close to you :) diff --git a/src/g_demo.c b/src/g_demo.c index bedbf1e41..9a44db79c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1171,9 +1171,18 @@ void G_GhostTicker(void) demoghost *g,*p; for(g = ghosts, p = NULL; g; g = g->next) { + UINT16 ziptic; + UINT8 xziptic; + + // Pause jhosts that cross until we cross ourself. + if (g->linecrossed && !linecrossed) + continue; + +readghosttic: + // Skip normal demo data. - UINT16 ziptic = READUINT8(g->p); - UINT8 xziptic = 0; + ziptic = READUINT8(g->p); + xziptic = 0; while (ziptic != DW_END) // Get rid of extradata stuff { @@ -1198,6 +1207,8 @@ void G_GhostTicker(void) g->p += 32; // ok (32 because there's both the skin and the colour) if (ziptic & DXD_WEAPONPREF) g->p++; // ditto + if (ziptic & DXD_START) + g->linecrossed = true; } else if (ziptic == DW_RNG) { @@ -1463,6 +1474,9 @@ skippedghosttic: continue; } + if (linecrossed && !g->linecrossed) + goto readghosttic; + p = g; #undef follow } diff --git a/src/g_demo.h b/src/g_demo.h index 96217a310..89e7f6fd7 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -126,6 +126,7 @@ extern UINT8 demo_writerng; #define DXD_NAME 0x08 // name changed #define DXD_COLOR 0x10 // color changed #define DXD_FOLLOWER 0x20 // follower was changed +#define DXD_START 0x40 // Crossed the line in TA #define DXD_ADDPLAYER (DXD_JOINDATA|DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER) @@ -168,6 +169,7 @@ struct demoghost { UINT8 fadein; UINT16 version; UINT8 numskins; + boolean linecrossed; democharlist_t *skinlist; mobj_t oldmo, *mo; struct demoghost *next; diff --git a/src/g_game.c b/src/g_game.c index 728fec037..e65baacd1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -310,6 +310,7 @@ boolean thwompsactive; // Thwomps activate on lap 2 UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors SINT8 spbplace; // SPB exists, give the person behind better items boolean rainbowstartavailable; // Boolean, keeps track of if the rainbow start was gotten +tic_t linecrossed; // For Time Attack boolean inDuel; // Boolean, keeps track of if it is a 1v1 // Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players) @@ -328,6 +329,11 @@ UINT16 prevmap, nextmap; char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; INT32 player_name_changes[MAXPLAYERS]; +boolean G_TimeAttackStart(void) +{ + return (modeattacking && (gametyperules & (GTR_CIRCUIT|GTR_CATCHER)) == GTR_CIRCUIT); +} + // MAKE SURE YOU SAVE DATA BEFORE CALLING THIS void G_ClearRecords(void) { diff --git a/src/g_game.h b/src/g_game.h index eeda11a79..fc747ae7b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -263,6 +263,8 @@ void G_LoadGameSettings(void); void G_SetGameModified(boolean silent, boolean major); void G_SetUsedCheats(void); +boolean G_TimeAttackStart(void); + // Gamedata record shit void G_ClearRecords(void); diff --git a/src/k_kart.c b/src/k_kart.c index 1af666237..a7e343550 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -118,6 +118,7 @@ void K_TimerReset(void) darkness = darktimer = 0; numbulbs = 1; inDuel = rainbowstartavailable = false; + linecrossed = 0; timelimitintics = extratimeintics = secretextratime = 0; g_pointlimit = 0; } @@ -262,6 +263,12 @@ void K_TimerInit(void) introtime = 0; } + if (G_TimeAttackStart()) + { + starttime = 15*TICRATE; // Longest permitted start. No half-laps in reverse. + // (Changed on finish line cross later, don't worry.) + } + K_SpawnItemCapsules(); K_BattleInit(domodeattack); @@ -8332,7 +8339,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // If the button stays held, delay charge a bit. if (player->instaWhipChargeLockout) player->instaWhipChargeLockout--; - if (player->rings > 0 || player->itemamount || player->ringdelay || player->rocketsneakertimer) + if (player->rings > 0 || player->itemamount || player->ringdelay || player->rocketsneakertimer || player->ringboxdelay) player->instaWhipChargeLockout = INSTAWHIP_HOLD_DELAY; else if (!(player->cmd.buttons & BT_ATTACK)) // Deliberate Item button release, no need to protect you from lockout player->instaWhipChargeLockout = 0; @@ -8357,7 +8364,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) S_StopSoundByID(player->mo, sfx_wchrg2); } - if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer) + if (player->itemamount || player->respawn.state != RESPAWNST_NONE || player->pflags & (PF_ITEMOUT|PF_EGGMANOUT) || player->rocketsneakertimer || player->ringboxdelay) player->instaWhipCharge = 0; if (player->tiregrease) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index b52a500e8..8fbc292d1 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -319,6 +319,13 @@ boolean M_Responder(event_t *ev) } #endif + // Attack modes quick-restart + if (CON_Ready() == false && modeattacking && G_PlayerInputDown(0, gc_y, splitscreen + 1) == true) + { + M_TryAgain(0); + return true; + } + if (CON_Ready() == false && G_PlayerInputDown(0, gc_start, splitscreen + 1) == true) { if (!chat_on) diff --git a/src/k_race.c b/src/k_race.c index 0a1b64a02..766eadf28 100644 --- a/src/k_race.c +++ b/src/k_race.c @@ -283,7 +283,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * y = liney + FixedMul(FixedMul(FINISHLINEBEAM_SPACING, FINESINE(lineangle >> ANGLETOFINESHIFT)), FINECOSINE(aiming >> ANGLETOFINESHIFT)); z = FINISHLINEBEAM_SPACING + FixedMul(FINISHLINEBEAM_SPACING, FINESINE(aiming >> ANGLETOFINESHIFT)); - if (leveltime >= starttime) + if (leveltime >= starttime || G_TimeAttackStart()) { spriteframe = 4; // Weakest sprite when passable } diff --git a/src/p_spec.c b/src/p_spec.c index 9b80efa4f..e8d8f8c57 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -49,6 +49,7 @@ #include "k_objects.h" #include "acs/interface.h" #include "m_easing.h" +#include "music.h" // Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog #include @@ -1909,7 +1910,7 @@ static void K_HandleLapIncrement(player_t *player) { if (player) { - if (leveltime < starttime && !(gametyperules & GTR_ROLLINGSTART)) + if (!G_TimeAttackStart() && leveltime < starttime && !(gametyperules & GTR_ROLLINGSTART)) { // freeze 'em until fault penalty is over player->mo->hitlag = starttime - leveltime + TICRATE*3; @@ -1964,6 +1965,15 @@ static void K_HandleLapIncrement(player_t *player) player->karthud[khud_lapanimation] = 80; } + if (G_TimeAttackStart() && !linecrossed) + { + linecrossed = leveltime; + if (starttime > leveltime) // Overlong starts shouldn't reset time on cross + starttime = leveltime; + demo_extradata[player-players] |= DXD_START; + Music_Stop("position"); + } + if (rainbowstartavailable == true && player->mo->hitlag == 0) { S_StartSound(player->mo, sfx_s23c); diff --git a/src/p_user.c b/src/p_user.c index cec5759f8..fb4a2f031 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1330,7 +1330,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) if (demo.playback == false) { - if (modeattacking == true) + if (modeattacking) { G_UpdateRecords(); } @@ -2834,28 +2834,6 @@ static void P_DeathThink(player_t *player) K_ToggleDirector(G_PartyPosition(player - players), true); } - // Keep time rolling - if (!(player->exiting || mapreset) && !(player->pflags & PF_NOCONTEST) && !stoppedclock) - { - if (leveltime >= starttime) - { - player->realtime = leveltime - starttime; - if (player == &players[consoleplayer]) - { - if (player->spectator) - curlap = 0; - else if (curlap != UINT32_MAX) - curlap++; // This is too complicated to sync to realtime, just sorta hope for the best :V - } - } - else - { - player->realtime = 0; - if (player == &players[consoleplayer]) - curlap = 0; - } - } - if (!player->mo) return;