diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4c3a0f483..6cfd57723 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2691,11 +2691,17 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (!paused && (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS))) + if (!paused && (!(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS))) { CONS_Printf(M_GetText("You can't pause here.\n")); return; } + else if (modeattacking) // in time attack, pausing restarts the map + { + M_ModeAttackRetry(0); // directly call from m_menu; + return; + } + SendNetXCmd(XD_PAUSE, &buf, 2); } else diff --git a/src/g_game.c b/src/g_game.c index 78df6320e..a62e4223d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2319,6 +2319,12 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; ticcmd_t *cmd; + UINT32 ra_timeskip = (modeattacking && !demo.playback && leveltime < starttime - TICRATE*4) ? 0 : (starttime - TICRATE*4 - 1); + // starttime - TICRATE*4 is where we want RA to start when we PLAY IT, so we will loop the main thinker on RA start to get it to this point, + // the reason this is done is to ensure that ghosts won't look out of synch with other map elements (objects, moving platforms...) + // when we REPLAY, don't skip, let the camera spin, do its thing etc~ + + // also the -1 is to ensure that the thinker runs in the loop below. P_MapStart(); // do player reborns if needed @@ -2391,12 +2397,16 @@ void G_Ticker(boolean run) switch (gamestate) { case GS_LEVEL: - if (demo.title) - F_TitleDemoTicker(); - P_Ticker(run); // tic the game - ST_Ticker(); - AM_Ticker(); - HU_Ticker(); + + for (; ra_timeskip < starttime - TICRATE*4; ra_timeskip++) // this looks weird but this is done to not break compability with older demos for now. + { + if (demo.title) + F_TitleDemoTicker(); + P_Ticker(run); // tic the game + ST_Ticker(); + AM_Ticker(); + HU_Ticker(); + } break; case GS_INTERMISSION: diff --git a/src/m_menu.c b/src/m_menu.c index ea095c743..7bbe1e9b8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -231,7 +231,6 @@ static void M_HandleStaffReplay(INT32 choice); static void M_ReplayTimeAttack(INT32 choice); static void M_ChooseTimeAttack(INT32 choice); //static void M_ChooseNightsAttack(INT32 choice); -static void M_ModeAttackRetry(INT32 choice); static void M_ModeAttackEndGame(INT32 choice); static void M_SetGuestReplay(INT32 choice); //static void M_ChoosePlayer(INT32 choice); @@ -8259,7 +8258,7 @@ static void M_SetGuestReplay(INT32 choice) which(0); } -static void M_ModeAttackRetry(INT32 choice) +void M_ModeAttackRetry(INT32 choice) { (void)choice; G_CheckDemoStatus(); // Cancel recording diff --git a/src/m_menu.h b/src/m_menu.h index f9b88019f..240b27965 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -57,6 +57,9 @@ void M_SortServerList(void); // Draws a box with a texture inside as background for messages void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines); +// Used in d_netcmd to restart time attack +void M_ModeAttackRetry(INT32 choice); + // the function to show a message box typing with the string inside // string must be static (not in the stack) // routine is a function taking a INT32 in parameter diff --git a/src/p_tick.c b/src/p_tick.c index 0ed7fb0b7..0ce72c778 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -691,7 +691,10 @@ void P_Ticker(boolean run) if (run) leveltime++; - timeinmap++; + + // as this is mostly used for HUD stuff, add the record attack specific hack to it as well! + if (!(modeattacking && !demo.playback) || leveltime >= starttime - TICRATE*4) + timeinmap++; /*if (G_TagGametype()) P_DoTagStuff(); diff --git a/src/p_user.c b/src/p_user.c index 9560db392..f33b9cd70 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7657,7 +7657,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15)); camrotate += timeovercam; } - else if (leveltime < introtime) // Whoooshy camera! + else if (leveltime < introtime && !(modeattacking && !demo.playback)) // Whoooshy camera! (don't do this in RA when we PLAY, still do it in replays however~) { const INT32 introcam = (introtime - leveltime); camrotate += introcam*5;