Kart-Public/src/f_finale.c

1489 lines
34 KiB
C
Raw Normal View History

2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file f_finale.c
/// \brief Title screen, intro, game evaluation, and credits.
#include "doomdef.h"
#include "doomstat.h"
#include "d_main.h"
#include "f_finale.h"
#include "g_game.h"
#include "hu_stuff.h"
#include "r_local.h"
#include "s_sound.h"
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
#include "i_time.h"
2014-03-15 16:59:03 +00:00
#include "i_video.h"
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
#include "i_system.h"
#include "i_threads.h"
2014-03-15 16:59:03 +00:00
#include "m_menu.h"
#include "dehacked.h"
#include "g_input.h"
#include "console.h"
#include "m_random.h"
#include "y_inter.h"
#include "m_cond.h"
// Stage of animation:
// 0 = text, 1 = art screen
static INT32 finalecount;
INT32 titlescrollspeed = 5;
2014-03-15 16:59:03 +00:00
static INT32 timetonext; // Delay between screen changes
static INT32 continuetime; // Short delay when continuing
static tic_t animtimer; // Used for some animation timings
2018-03-29 22:11:06 +00:00
static tic_t credbgtimer; // Credits background
2014-03-15 16:59:03 +00:00
static INT32 roidtics; // Asteroid spinning
static tic_t stoptimer;
static boolean keypressed = false;
// (no longer) De-Demo'd Title Screen
#if 0
static UINT8 laststaff = 0;
#endif
2014-03-15 16:59:03 +00:00
static UINT32 demoDelayLeft;
static UINT32 demoIdleLeft;
static patch_t *ttbanner; // SONIC ROBO BLAST 2
static patch_t *ttkart; // *vroom* KART
static patch_t *ttcheckers; // *vroom* KART
static patch_t *ttkflash; // flash screen
2014-03-15 16:59:03 +00:00
static patch_t *driver[2]; // Driving character on the waiting screen
static UINT8 *waitcolormap; // colormap for the spinning character
2014-03-15 16:59:03 +00:00
static void F_SkyScroll(INT32 scrollspeed);
//
// CUTSCENE TEXT WRITING
//
static const char *cutscene_basetext = NULL;
static char cutscene_disptext[1024];
static INT32 cutscene_baseptr = 0;
static INT32 cutscene_writeptr = 0;
static INT32 cutscene_textcount = 0;
static INT32 cutscene_textspeed = 0;
static UINT8 cutscene_boostspeed = 0;
static tic_t cutscene_lasttextwrite = 0;
//
// This alters the text string cutscene_disptext.
// Use the typical string drawing functions to display it.
// Returns 0 if \0 is reached (end of input)
//
static UINT8 F_WriteText(void)
{
INT32 numtowrite = 1;
const char *c;
tic_t ltw = I_GetTime();
if (cutscene_lasttextwrite == ltw)
return 1; // singletics prevention
cutscene_lasttextwrite = ltw;
if (cutscene_boostspeed)
{
// for custom cutscene speedup mode
numtowrite = 8;
}
else
{
// Don't draw any characters if the count was 1 or more when we started
if (--cutscene_textcount >= 0)
return 1;
if (cutscene_textspeed < 7)
numtowrite = 8 - cutscene_textspeed;
}
for (;numtowrite > 0;++cutscene_baseptr)
{
c = &cutscene_basetext[cutscene_baseptr];
if (!c || !*c || *c=='#')
return 0;
// \xA0 - \xAF = change text speed
if ((UINT8)*c >= 0xA0 && (UINT8)*c <= 0xAF)
{
cutscene_textspeed = (INT32)((UINT8)*c - 0xA0);
continue;
}
// \xB0 - \xD2 = delay character for up to one second (35 tics)
else if ((UINT8)*c >= 0xB0 && (UINT8)*c <= (0xB0+TICRATE-1))
{
cutscene_textcount = (INT32)((UINT8)*c - 0xAF);
numtowrite = 0;
continue;
}
cutscene_disptext[cutscene_writeptr++] = *c;
// Ignore other control codes (color)
if ((UINT8)*c < 0x80)
--numtowrite;
}
// Reset textcount for next tic based on speed
// if it wasn't already set by a delay.
if (cutscene_textcount < 0)
{
cutscene_textcount = 0;
if (cutscene_textspeed > 7)
cutscene_textcount = cutscene_textspeed - 7;
}
return 1;
}
static void F_NewCutscene(const char *basetext)
{
cutscene_basetext = basetext;
memset(cutscene_disptext,0,sizeof(cutscene_disptext));
cutscene_writeptr = cutscene_baseptr = 0;
cutscene_textspeed = 9;
cutscene_textcount = TICRATE/2;
}
//
// F_SkyScroll
//
static void F_SkyScroll(INT32 scrollspeed)
{
2018-11-14 05:30:51 +00:00
INT32 x, y, w;
patch_t *pat, *pat2;
INT32 anim2 = 0;
pat = W_CachePatchName("TITLEBG1", PU_CACHE);
pat2 = W_CachePatchName("TITLEBG2", PU_CACHE);
2014-03-15 16:59:03 +00:00
2018-11-14 05:30:51 +00:00
w = vid.width / vid.dupx;
2014-03-15 16:59:03 +00:00
animtimer = ((finalecount*scrollspeed)/16) % SHORT(pat->width);
2018-11-14 05:30:51 +00:00
anim2 = SHORT(pat2->width) - (((finalecount*scrollspeed)/16) % SHORT(pat2->width));
2014-03-15 16:59:03 +00:00
2018-11-14 05:30:51 +00:00
// SRB2Kart: F_DrawPatchCol is over-engineered; recoded to be less shitty and error-prone
if (rendermode != render_none)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120);
2014-03-15 16:59:03 +00:00
x = -((INT32)animtimer);
2018-11-14 05:30:51 +00:00
y = 0;
while (x < w)
{
2018-11-14 05:30:51 +00:00
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, pat, NULL);
x += SHORT(pat->width);
2019-02-05 20:42:37 +00:00
}
2018-11-14 05:30:51 +00:00
x = -anim2;
y = BASEVIDHEIGHT - SHORT(pat2->height);
while (x < w)
{
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, pat2, NULL);
x += SHORT(pat2->width);
}
2014-03-15 16:59:03 +00:00
}
W_UnlockCachedPatch(pat);
2018-11-14 05:30:51 +00:00
W_UnlockCachedPatch(pat2);
2014-03-15 16:59:03 +00:00
}
// =============
// INTRO SCENE
// =============
2017-10-25 19:30:02 +00:00
#define NUMINTROSCENES 1
2014-03-15 16:59:03 +00:00
INT32 intro_scenenum = 0;
INT32 intro_curtime = 0;
const char *introtext[NUMINTROSCENES];
static tic_t introscenetime[NUMINTROSCENES] =
{
4*TICRATE, // KART KR(eW
2014-03-15 16:59:03 +00:00
};
// custom intros
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer);
void F_StartIntro(void)
{
if (gamestate)
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_level_final], false);
}
2014-03-15 16:59:03 +00:00
if (introtoplay)
{
if (!cutscenes[introtoplay - 1])
D_StartTitle();
else
F_StartCustomCutscene(introtoplay - 1, false, false);
return;
}
introtext[0] = " #";
G_SetGamestate(GS_INTRO);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
F_NewCutscene(introtext[0]);
intro_scenenum = 0;
finalecount = animtimer = stoptimer = 0;
roidtics = BASEVIDWIDTH - 64;
timetonext = introscenetime[intro_scenenum];
2017-10-25 19:30:02 +00:00
S_StopMusic();
2014-03-15 16:59:03 +00:00
}
//
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
// F_IntroDrawer
2014-03-15 16:59:03 +00:00
//
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
void F_IntroDrawer(void)
2014-03-15 16:59:03 +00:00
{
boolean highres = false;
INT32 cx = 8, cy = 128;
patch_t *background = NULL;
INT32 bgxoffs = 0;
// DRAW A FULL PIC INSTEAD OF FLAT!
2017-10-25 19:30:02 +00:00
if (intro_scenenum == 0)
2014-03-15 16:59:03 +00:00
{
2017-10-25 19:30:02 +00:00
background = W_CachePatchName("KARTKREW", PU_CACHE);
2017-10-25 22:05:19 +00:00
highres = true;
2014-03-15 16:59:03 +00:00
}
2017-10-25 19:30:02 +00:00
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120);
2014-03-15 16:59:03 +00:00
if (background)
{
if (highres)
V_DrawSmallScaledPatch(bgxoffs, 0, 0, background);
else
V_DrawScaledPatch(bgxoffs, 0, 0, background);
}
W_UnlockCachedPatch(background);
if (animtimer)
animtimer--;
V_DrawString(cx, cy, 0, cutscene_disptext);
}
//
// F_IntroTicker
//
void F_IntroTicker(void)
{
// advance animation
finalecount++;
if (finalecount % 3 == 0)
roidtics--;
timetonext--;
if (intro_scenenum == 0)
{
if (finalecount == 8)
S_StartSound(NULL, sfx_vroom);
else if (finalecount == 47)
{
// Need to use M_Random otherwise it always uses the same sound
INT32 rskin = M_RandomKey(numskins);
UINT8 rtaunt = M_RandomKey(2);
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
S_StartSound(NULL, rsound);
}
}
2014-03-15 16:59:03 +00:00
F_WriteText();
// check for skipping
if (keypressed)
keypressed = false;
}
//
// F_IntroResponder
//
boolean F_IntroResponder(event_t *event)
{
INT32 key = event->data1;
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_MOUSE1:
key = KEY_ENTER;
break;
case KEY_MOUSE1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_JOY1:
case KEY_JOY1 + 2:
key = KEY_ENTER;
break;
case KEY_JOY1 + 3:
key = 'n';
break;
case KEY_JOY1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_HAT1:
key = KEY_UPARROW;
break;
case KEY_HAT1 + 1:
key = KEY_DOWNARROW;
break;
case KEY_HAT1 + 2:
key = KEY_LEFTARROW;
break;
case KEY_HAT1 + 3:
key = KEY_RIGHTARROW;
break;
}
if (event->type != ev_keydown && key != 301)
return false;
if (key != 27 && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE)
return false;
if (keypressed)
return false;
keypressed = true;
return true;
}
// =========
// CREDITS
// =========
static const char *credits[] = {
2018-11-16 03:55:01 +00:00
"\1SRB2Kart",
2014-11-12 00:55:07 +00:00
"\1Credits",
2014-03-15 16:59:03 +00:00
"",
"\1Game Design",
2018-11-16 03:55:01 +00:00
"Sally \"TehRealSalt\" Cochenour",
"Jeffery \"Chromatian\" Scott",
"\"VelocitOni\"",
2014-03-15 16:59:03 +00:00
"",
2018-11-16 03:55:01 +00:00
"\1Lead Programming",
"Sally \"TehRealSalt\" Cochenour",
"Vivian \"toaster\" Grannell",
"Sean \"Sryder\" Ryder",
"Ehab \"wolfs\" Saeed",
"\"ZarroTsu\"",
2014-03-15 16:59:03 +00:00
"",
2018-11-16 03:55:01 +00:00
"\1Support Programming",
"Colette \"fickleheart\" Bordelon",
2018-11-16 03:55:01 +00:00
"\"Lat\'\"",
"\"Monster Iestyn\"",
2021-08-31 01:45:56 +00:00
"James Robert Roman",
2018-11-16 03:55:01 +00:00
"\"Shuffle\"",
2020-05-09 06:17:10 +00:00
"\"SteelT\"",
2018-11-16 03:55:01 +00:00
"",
"\1Lead Artists",
"Desmond \"Blade\" DesJardins",
2018-11-16 03:55:01 +00:00
"\"VelocitOni\"",
"",
"\1Support Artists",
"Sally \"TehRealSalt\" Cochenour",
"Sherman \"CoatRack\" DesJardins",
2018-11-29 11:54:36 +00:00
"\"DrTapeworm\"",
2018-11-16 03:55:01 +00:00
"Jesse \"Jeck Jims\" Emerick",
2018-03-29 05:34:31 +00:00
"Wesley \"Charyb\" Gillebaard",
2018-11-16 03:55:01 +00:00
"Vivian \"toaster\" Grannell",
2018-03-28 23:27:26 +00:00
"James \"SeventhSentinel\" Hall",
2018-11-29 11:54:36 +00:00
"\"Lat\'\"",
2018-11-16 03:55:01 +00:00
"\"Tyrannosaur Chao\"",
"\"ZarroTsu\"",
"",
"\1External Artists",
2019-05-13 17:49:44 +00:00
"\"1-Up Mason\"",
"\"Chengi\"",
2018-11-16 03:55:01 +00:00
"\"Chrispy\"",
"\"DirkTheHusky\"",
2019-05-13 17:49:44 +00:00
"\"LJSTAR\"",
2018-03-29 05:34:31 +00:00
"\"MotorRoach\"",
2018-11-16 03:55:01 +00:00
"\"Nev3r\"",
2020-05-09 06:17:10 +00:00
"\"rairai104n\"",
2018-11-16 03:55:01 +00:00
"\"Ritz\"",
"\"Rob\"",
"\"SmithyGNC\"",
2018-11-29 11:54:36 +00:00
"\"Snu\"",
2018-11-16 03:55:01 +00:00
"\"Spherallic\"",
2020-05-09 06:17:10 +00:00
"\"TelosTurntable\"",
2018-03-29 05:34:31 +00:00
"\"VAdaPEGA\"",
2018-11-29 11:54:36 +00:00
"\"Virt\"",
2019-05-13 17:49:44 +00:00
"\"Voltrix\"",
2014-03-15 16:59:03 +00:00
"",
2018-11-16 03:55:01 +00:00
"\1Sound Design",
"James \"SeventhSentinel\" Hall",
"Sonic Team",
"\"VAdaPEGA\"",
"\"VelocitOni\"",
"",
"\1Music",
2018-11-16 03:55:01 +00:00
"\"DrTapeworm\"",
2018-03-29 05:34:31 +00:00
"Wesley \"Charyb\" Gillebaard",
"James \"SeventhSentinel\" Hall",
2014-03-15 16:59:03 +00:00
"",
2018-11-16 03:55:01 +00:00
"\1Lead Level Design",
"\"Blitz-T\"",
"Sally \"TehRealSalt\" Cochenour",
"Desmond \"Blade\" DesJardins",
2018-11-16 03:55:01 +00:00
"Jeffery \"Chromatian\" Scott",
"\"Tyrannosaur Chao\"",
"",
"\1Support Level Design",
"\"Chaos Zero 64\"",
"\"D00D64\"",
"\"DrTapeworm\"",
"Paul \"Boinciel\" Clempson",
"Sherman \"CoatRack\" DesJardins",
2019-05-15 03:29:28 +00:00
"Colette \"fickleheart\" Bordelon",
2018-11-16 17:05:57 +00:00
"Vivian \"toaster\" Grannell",
2020-05-09 06:17:10 +00:00
"\"Gunla\"",
"James \"SeventhSentinel\" Hall",
2018-11-16 03:55:01 +00:00
"\"Lat\'\"",
2019-05-15 03:29:28 +00:00
"\"MK\"",
"\"Ninferno\"",
"Sean \"Sryder\" Ryder",
"\"Ryuspark\"",
2018-03-28 23:27:26 +00:00
"\"Simsmagic\"",
2018-11-16 03:55:01 +00:00
"\"SP47\"",
2019-05-15 03:29:28 +00:00
"\"TG\"",
"\"Victor Rush Turbo\"",
"\"ZarroTsu\"",
2018-03-28 23:27:26 +00:00
"",
"\1Testing",
"\"CyberIF\"",
"\"Dani\"",
"Karol \"Fooruman\" D""\x1E""browski", // DÄ…browski, <Sryder> accents in srb2 :ytho:
2018-03-28 23:27:26 +00:00
"\"VirtAnderson\"",
2014-03-15 16:59:03 +00:00
"",
"\1Special Thanks",
2018-11-16 03:55:01 +00:00
"SEGA",
"Sonic Team",
"SRB2 & Sonic Team Jr. (www.srb2.org)",
"\"blazethecat\"",
"\"Chaos Zero 64\"",
"\"Rob\"",
2014-11-12 00:55:07 +00:00
"",
"\1Produced By",
"Kart Krew",
2014-03-15 16:59:03 +00:00
"",
2018-03-28 23:27:26 +00:00
"\1In Memory of",
"\"Tyler52\"",
"",
2018-11-16 03:55:01 +00:00
"",
2014-03-15 16:59:03 +00:00
"\1Thank you",
"\1for playing!",
NULL
};
static struct {
UINT32 x, y;
const char *patch;
2018-11-16 03:55:01 +00:00
UINT8 colorize;
2014-03-15 16:59:03 +00:00
} credits_pics[] = {
2018-11-16 03:55:01 +00:00
// We don't have time to be fancy, let's just colorize some item sprites :V
{224, 80+(200* 1), "K_ITJAWZ", SKINCOLOR_CREAMSICLE},
{224, 80+(200* 2), "K_ITSPB", SKINCOLOR_GARDEN},
{224, 80+(200* 3), "K_ITBANA", SKINCOLOR_LILAC},
{224, 80+(200* 4), "K_ITHYUD", SKINCOLOR_DREAM},
{224, 80+(200* 5), "K_ITBHOG", SKINCOLOR_TANGERINE},
{224, 80+(200* 6), "K_ITSHRK", SKINCOLOR_JAWZ},
{224, 80+(200* 7), "K_ITSHOE", SKINCOLOR_MINT},
{224, 80+(200* 8), "K_ITGROW", SKINCOLOR_RUBY},
{224, 80+(200* 9), "K_ITPOGO", SKINCOLOR_SAPPHIRE},
{224, 80+(200*10), "K_ITRSHE", SKINCOLOR_YELLOW},
{224, 80+(200*11), "K_ITORB4", SKINCOLOR_DUSK},
{224, 80+(200*12), "K_ITEGGM", SKINCOLOR_GREEN},
{224, 80+(200*13), "K_ITMINE", SKINCOLOR_BRONZE},
{224, 80+(200*14), "K_ITTHNS", SKINCOLOR_RASPBERRY},
{224, 80+(200*15), "K_ITINV1", SKINCOLOR_GREY},
// This Tyler52 gag is troublesome
// Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15))
// Current max image spacing: (200*17)
2020-05-09 06:17:10 +00:00
{112, (15*100)+(17*38)+(88*15), "TYLER52", SKINCOLOR_NONE},
2018-11-16 03:55:01 +00:00
{0, 0, NULL, SKINCOLOR_NONE}
2014-03-15 16:59:03 +00:00
};
void F_StartCredits(void)
{
G_SetGamestate(GS_CREDITS);
// Just in case they're open ... somehow
M_ClearMenus(true);
// Save the second we enter the credits
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot >= 0)
G_SaveGame((UINT32)cursaveslot);
if (creditscutscene)
{
F_StartCustomCutscene(creditscutscene - 1, false, false);
return;
}
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
S_StopMusic();
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal("credit", false);
2019-03-31 17:49:42 +00:00
S_ShowMusicCredit();
2014-03-15 16:59:03 +00:00
finalecount = 0;
animtimer = 0;
timetonext = 2*TICRATE;
}
void F_CreditDrawer(void)
{
UINT16 i;
fixed_t y = (80<<FRACBITS) - 5*(animtimer<<FRACBITS)/8;
//V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
2014-03-15 16:59:03 +00:00
2018-03-28 23:27:26 +00:00
// Draw background
2018-03-29 22:11:06 +00:00
V_DrawSciencePatch(0, 0 - FixedMul(32<<FRACBITS, FixedDiv(credbgtimer%TICRATE, TICRATE)), V_SNAPTOTOP, W_CachePatchName("CREDTILE", PU_CACHE), FRACUNIT);
2018-03-28 23:27:26 +00:00
2018-03-29 22:11:06 +00:00
V_DrawSciencePatch(0, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP, W_CachePatchName("CREDZIGZ", PU_CACHE), FRACUNIT);
V_DrawSciencePatch(320<<FRACBITS, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP|V_FLIP, W_CachePatchName("CREDZIGZ", PU_CACHE), FRACUNIT);
2018-03-28 23:27:26 +00:00
// Draw pictures
2014-03-15 16:59:03 +00:00
for (i = 0; credits_pics[i].patch; i++)
2018-11-16 03:55:01 +00:00
{
UINT8 *colormap = NULL;
fixed_t sc = FRACUNIT>>1;
if (credits_pics[i].colorize != SKINCOLOR_NONE)
{
colormap = R_GetTranslationColormap(TC_RAINBOW, credits_pics[i].colorize, GTC_MENUCACHE);
2018-11-16 03:55:01 +00:00
sc = FRACUNIT; // quick hack so I don't have to add another field to credits_pics
}
V_DrawFixedPatch(credits_pics[i].x<<FRACBITS, (credits_pics[i].y<<FRACBITS) - 4*(animtimer<<FRACBITS)/5, sc, 0, W_CachePatchName(credits_pics[i].patch, PU_CACHE), colormap);
}
2014-03-15 16:59:03 +00:00
2018-11-23 01:08:02 +00:00
// Dim the background
2018-11-29 15:07:35 +00:00
//V_DrawFadeScreen();
2018-11-23 01:08:02 +00:00
2014-03-15 16:59:03 +00:00
// Draw credits text on top
for (i = 0; credits[i]; i++)
{
switch(credits[i][0])
{
case 0:
y += 80<<FRACBITS;
break;
case 1:
if (y>>FRACBITS > -20)
V_DrawCreditString((160 - (V_CreditStringWidth(&credits[i][1])>>1))<<FRACBITS, y, 0, &credits[i][1]);
y += 30<<FRACBITS;
break;
default:
if (y>>FRACBITS > -10)
V_DrawStringAtFixed(32<<FRACBITS, y, V_ALLOWLOWERCASE, credits[i]);
y += 12<<FRACBITS;
break;
}
if (((y>>FRACBITS) * vid.dupy) > vid.height)
2014-03-15 16:59:03 +00:00
break;
}
}
2014-03-15 16:59:03 +00:00
void F_CreditTicker(void)
{
// "Simulate" the drawing of the credits so that dedicated mode doesn't get stuck
UINT16 i;
fixed_t y = (80<<FRACBITS) - 5*(animtimer<<FRACBITS)/8;
2019-03-31 17:49:42 +00:00
// Draw credits text on top
for (i = 0; credits[i]; i++)
{
switch(credits[i][0])
{
case 0: y += 80<<FRACBITS; break;
case 1: y += 30<<FRACBITS; break;
default: y += 12<<FRACBITS; break;
}
if (FixedMul(y,vid.dupy) > vid.height)
break;
}
2014-03-15 16:59:03 +00:00
// Do this here rather than in the drawer you doofus! (this is why dedicated mode broke at credits)
2014-03-15 16:59:03 +00:00
if (!credits[i] && y <= 120<<FRACBITS && !finalecount)
{
timetonext = 5*TICRATE+1;
finalecount = 5*TICRATE;
}
if (timetonext)
timetonext--;
else
animtimer++;
2018-03-29 22:11:06 +00:00
credbgtimer++;
2014-03-15 16:59:03 +00:00
if (finalecount && --finalecount == 0)
F_StartGameEvaluation();
}
boolean F_CreditResponder(event_t *event)
{
INT32 key = event->data1;
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_MOUSE1:
key = KEY_ENTER;
break;
case KEY_MOUSE1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_JOY1:
case KEY_JOY1 + 2:
key = KEY_ENTER;
break;
case KEY_JOY1 + 3:
key = 'n';
break;
case KEY_JOY1 + 1:
key = KEY_BACKSPACE;
break;
case KEY_HAT1:
key = KEY_UPARROW;
break;
case KEY_HAT1 + 1:
key = KEY_DOWNARROW;
break;
case KEY_HAT1 + 2:
key = KEY_LEFTARROW;
break;
case KEY_HAT1 + 3:
key = KEY_RIGHTARROW;
break;
}
if (event->type != ev_keydown)
return false;
if (key == KEY_DOWNARROW || key == KEY_SPACE)
{
if (!timetonext && !finalecount)
animtimer += 7;
return false;
}
/*if (!(timesBeaten) && !(netgame || multiplayer))
return false;*/
if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_BACKSPACE)
2014-03-15 16:59:03 +00:00
return false;
if (keypressed)
return true;
keypressed = true;
return true;
}
// ============
// EVALUATION
// ============
#define INTERVAL 50
#define TRANSLEVEL V_80TRANS
static INT32 eemeralds_start;
static boolean drawemblem = false, drawchaosemblem = false;
void F_StartGameEvaluation(void)
{
// Credits option in secrets menu
if (cursaveslot == -2)
{
F_StartGameEnd();
return;
}
G_SetGamestate(GS_EVALUATION);
// Just in case they're open ... somehow
M_ClearMenus(true);
// Save the second we enter the evaluation
// We need to do this again! Remember, it's possible a mod designed skipped
// the credits sequence!
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot >= 0)
G_SaveGame((UINT32)cursaveslot);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
finalecount = 0;
}
void F_GameEvaluationDrawer(void)
{
INT32 x, y, i;
const fixed_t radius = 48*FRACUNIT;
angle_t fa;
INT32 eemeralds_cur;
char patchname[7] = "CEMGx0";
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Draw all the good crap here.
if (ALL7EMERALDS(emeralds))
V_DrawString(114, 16, 0, "GOT THEM ALL!");
else
V_DrawString(124, 16, 0, "TRY AGAIN!");
eemeralds_start++;
eemeralds_cur = eemeralds_start;
for (i = 0; i < 7; ++i)
{
fa = (FixedAngle(eemeralds_cur*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK;
x = 160 + FixedInt(FixedMul(FINECOSINE(fa),radius));
y = 100 + FixedInt(FixedMul(FINESINE(fa),radius));
patchname[4] = 'A'+(char)i;
if (emeralds & (1<<i))
V_DrawScaledPatch(x, y, 0, W_CachePatchName(patchname, PU_CACHE));
else
V_DrawTranslucentPatch(x, y, TRANSLEVEL, W_CachePatchName(patchname, PU_CACHE));
eemeralds_cur += INTERVAL;
}
if (eemeralds_start >= 360)
eemeralds_start -= 360;
if (finalecount == 5*TICRATE)
{
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer))
{
++timesBeaten;
if (ALL7EMERALDS(emeralds))
++timesBeatenWithEmeralds;
2016-07-06 04:09:17 +00:00
/*if (ultimatemode)
++timesBeatenUltimate;*/
2016-07-06 04:09:17 +00:00
if (M_UpdateUnlockablesAndExtraEmblems(false))
2014-03-15 16:59:03 +00:00
S_StartSound(NULL, sfx_ncitem);
G_SaveGameData(false);
2014-03-15 16:59:03 +00:00
}
}
if (finalecount >= 5*TICRATE)
{
if (drawemblem)
V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE));
if (drawchaosemblem)
V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE));
V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:");
if (!(netgame) && (!modifiedgame || savemoddata))
{
INT32 startcoord = 32;
for (i = 0; i < MAXUNLOCKABLES; i++)
{
if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS
&& unlockables[i].type && !unlockables[i].nocecho)
{
if (unlockables[i].unlocked)
V_DrawString(8, startcoord, 0, unlockables[i].name);
startcoord += 8;
}
}
}
else if (netgame)
V_DrawString(8, 96, V_YELLOWMAP, "Prizes only\nawarded in\nsingle player!");
else
V_DrawString(8, 96, V_YELLOWMAP, "Prizes not\nawarded in\nmodified games!");
}
}
void F_GameEvaluationTicker(void)
{
finalecount++;
if (finalecount > 10*TICRATE)
F_StartGameEnd();
}
// ==========
// GAME END
// ==========
void F_StartGameEnd(void)
{
G_SetGamestate(GS_GAMEEND);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
S_StopMusic();
// In case menus are still up?!!
M_ClearMenus(true);
timetonext = TICRATE;
}
//
// F_GameEndDrawer
//
void F_GameEndDrawer(void)
{
// this function does nothing
2014-03-15 16:59:03 +00:00
}
//
// F_GameEndTicker
//
void F_GameEndTicker(void)
{
if (timetonext > 0)
timetonext--;
else
D_StartTitle();
}
// ==============
// TITLE SCREEN
// ==============
void F_StartTitleScreen(void)
{
if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)
finalecount = 0;
else
wipegamestate = GS_TITLESCREEN;
G_SetGamestate(GS_TITLESCREEN);
CON_ClearHUD();
// IWAD dependent stuff.
// music is started in the ticker
if (!demo.fromtitle) // SRB2Kart: Don't reset music if the right track is already playing
2018-11-14 02:01:59 +00:00
S_StopMusic();
demo.fromtitle = false;
2014-03-15 16:59:03 +00:00
animtimer = 0;
demoDelayLeft = demoDelayTime;
demoIdleLeft = demoIdleTime;
ttbanner = W_CachePatchName("TTKBANNR", PU_LEVEL);
ttkart = W_CachePatchName("TTKART", PU_LEVEL);
ttcheckers = W_CachePatchName("TTCHECK", PU_LEVEL);
ttkflash = W_CachePatchName("TTKFLASH", PU_LEVEL);
2014-03-15 16:59:03 +00:00
}
// (no longer) De-Demo'd Title Screen
void F_TitleScreenDrawer(void)
{
if (modeattacking)
return; // We likely came here from retrying. Don't do a damn thing.
// Don't draw outside of the title screen, or if the patch isn't there.
if (!ttbanner || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
{
F_SkyScroll(titlescrollspeed);
2014-03-15 16:59:03 +00:00
return;
}
2014-03-15 16:59:03 +00:00
if (finalecount < 50)
2014-03-15 16:59:03 +00:00
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawSmallScaledPatch(84, 36, 0, ttbanner);
if (finalecount >= 20)
V_DrawSmallScaledPatch(84, 87, 0, ttkart);
else if (finalecount >= 10)
V_DrawSciencePatch((84<<FRACBITS) - FixedDiv(180<<FRACBITS, 10<<FRACBITS)*(20-finalecount), (87<<FRACBITS), 0, ttkart, FRACUNIT/2);
2014-03-15 16:59:03 +00:00
}
else if (finalecount < 52)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 120);
V_DrawSmallScaledPatch(84, 36, 0, ttkflash);
}
2014-03-15 16:59:03 +00:00
else
{
INT32 transval = 0;
if (finalecount <= (50+(9<<1)))
transval = (finalecount - 50)>>1;
F_SkyScroll(titlescrollspeed);
V_DrawSciencePatch(0, 0 - FixedMul(40<<FRACBITS, FixedDiv(finalecount%70, 70)), V_SNAPTOTOP|V_SNAPTOLEFT, ttcheckers, FRACUNIT);
V_DrawSciencePatch(280<<FRACBITS, -(40<<FRACBITS) + FixedMul(40<<FRACBITS, FixedDiv(finalecount%70, 70)), V_SNAPTOTOP|V_SNAPTORIGHT, ttcheckers, FRACUNIT);
2014-03-15 16:59:03 +00:00
if (transval)
V_DrawFadeScreen(120, 10 - transval);
V_DrawSmallScaledPatch(84, 36, 0, ttbanner);
V_DrawSmallScaledPatch(84, 87, 0, ttkart);
if (!transval)
return;
V_DrawSmallScaledPatch(84, 36, transval<<V_ALPHASHIFT, ttkflash);
}
2014-03-15 16:59:03 +00:00
}
// (no longer) De-Demo'd Title Screen
void F_TitleScreenTicker(boolean run)
{
if (run)
{
2014-03-15 16:59:03 +00:00
finalecount++;
if (finalecount == 10)
{
2018-11-12 00:22:15 +00:00
S_StartSound(NULL, sfx_s23e);
}
else if (finalecount == 50)
{
// Now start the music
S_ChangeMusicInternal("titles", looptitle);
2018-11-12 00:22:15 +00:00
S_StartSound(NULL, sfx_s23c);
}
}
2014-03-15 16:59:03 +00:00
// don't trigger if doing anything besides idling on title
if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN)
return;
// are demos disabled?
if (!cv_rollingdemos.value)
2014-03-15 16:59:03 +00:00
return;
// Wait for a while (for the music to finish, preferably)
// before starting demos
if (demoDelayLeft)
{
--demoDelayLeft;
return;
}
// Hold up for a bit if menu or console active
if (menuactive || CON_Ready())
{
demoIdleLeft = demoIdleTime;
return;
}
// is it time?
if (!(--demoIdleLeft))
{
//static boolean use_netreplay = false;
2014-03-15 16:59:03 +00:00
char dname[9];
lumpnum_t l;
const char *mapname;
UINT8 numstaff;
2014-03-15 16:59:03 +00:00
//@TODO uncomment this when this goes into vanilla
/*if ((use_netreplay = !use_netreplay))*/
{
numstaff = 1;
while ((l = W_CheckNumForName(va("TDEMO%03u", numstaff))) != LUMPERROR)
numstaff++;
numstaff--;
if (numstaff)
{
numstaff = M_RandomKey(numstaff)+1;
snprintf(dname, 9, "TDEMO%03u", numstaff);
goto loadreplay;
}
}
2014-03-15 16:59:03 +00:00
// prevent console spam if failed
demoIdleLeft = demoIdleTime;
if ((l = W_CheckNumForName("MAP01S01")) == LUMPERROR) // gotta have ONE
{
F_StartIntro();
return;
}
2014-03-15 16:59:03 +00:00
// Replay intro when done cycling through demos
/*if (curDemo == numDemos) -- uuuh... we have a LOT of maps AND a big devteam... probably not gonna see a repeat unless you're super unlucky :V
2014-03-15 16:59:03 +00:00
{
curDemo = 0;
F_StartIntro();
return;
}*/
mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, false, 0, false, NULL)+1);
numstaff = 1;
while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",mapname,numstaff+1))) != LUMPERROR)
numstaff++;
#if 0 // turns out this isn't how we're gonna organise 'em
if (numstaff > 1)
{
if (laststaff && laststaff <= numstaff) // don't do the same staff member twice in a row, even if they're on different maps
{
numstaff = M_RandomKey(numstaff-1)+1;
if (numstaff >= laststaff)
numstaff++;
}
else
numstaff = M_RandomKey(numstaff)+1;
}
2018-11-05 14:03:09 +00:00
laststaff = numstaff;
#else
numstaff = M_RandomKey(numstaff)+1;
#endif
2014-03-15 16:59:03 +00:00
// Setup demo name
snprintf(dname, 9, "%sS%02u", mapname, numstaff);
2014-03-15 16:59:03 +00:00
/*if ((l = W_CheckNumForName(dname)) == LUMPERROR) -- we KNOW it exists now
2014-03-15 16:59:03 +00:00
{
CONS_Alert(CONS_ERROR, M_GetText("Demo lump \"%s\" doesn't exist\n"), dname);
F_StartIntro();
return;
}*/
2014-03-15 16:59:03 +00:00
loadreplay:
demo.title = demo.fromtitle = true;
demo.ignorefiles = true;
demo.loadfiles = false;
2014-03-15 16:59:03 +00:00
G_DoPlayDemo(dname);
}
}
void F_TitleDemoTicker(void)
{
keypressed = false;
}
// ================
// WAITINGPLAYERS
// ================
void F_StartWaitingPlayers(void)
{
INT32 i;
INT32 randskin;
spriteframe_t *sprframe;
wipegamestate = GS_TITLESCREEN; // technically wiping from title screen
finalecount = 0;
randskin = M_RandomKey(numskins);
if (waitcolormap)
Z_Free(waitcolormap);
waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0);
for (i = 0; i < 2; i++)
{
sprframe = &skins[randskin].spritedef.spriteframes[(6+(i*3)) & FF_FRAMEMASK];
driver[i] = W_CachePatchNum(sprframe->lumppat[1], PU_LEVEL);
}
}
void F_WaitingPlayersTicker(void)
{
if (paused)
return;
finalecount++;
// dumb hack, only start the music on the 1st tick so if you instantly go into the map you aren't hearing a tic of music
if (finalecount == 2)
S_ChangeMusicInternal("WAIT2J", true);
}
void F_WaitingPlayersDrawer(void)
{
UINT32 frame = (finalecount % 8) / 4; // The game only tics every other frame while waitingplayers
INT32 flags = V_FLIP;
const char *waittext1 = "You will join";
const char *waittext2 = "the next race...";
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<<FRACBITS, 48<<FRACBITS, 0, waittext1);
V_DrawCreditString((160 - (V_CreditStringWidth(waittext2)>>1))<<FRACBITS, 64<<FRACBITS, 0, waittext2);
V_DrawFixedPatch((160<<FRACBITS) - driver[frame]->width / 2, 150<<FRACBITS, 1<<FRACBITS, flags, driver[frame], waitcolormap);
}
2014-03-15 16:59:03 +00:00
// ==========
// CONTINUE
// ==========
void F_StartContinue(void)
{
I_Assert(!netgame && !multiplayer);
if (players[consoleplayer].continues <= 0)
{
Command_ExitGame_f();
return;
}
G_SetGamestate(GS_CONTINUING);
gameaction = ga_nothing;
keypressed = false;
paused = false;
CON_ToggleOff();
// In case menus are still up?!!
M_ClearMenus(true);
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal("contsc", false);
2014-03-15 16:59:03 +00:00
S_StopSounds();
timetonext = TICRATE*11;
}
//
// F_ContinueDrawer
// Moved continuing out of the HUD (hack removal!!)
//
void F_ContinueDrawer(void)
{
patch_t *contsonic;
INT32 i, x = (BASEVIDWIDTH/2) + 4, ncontinues = players[consoleplayer].continues;
if (ncontinues > 20)
ncontinues = 20;
if (imcontinuing)
contsonic = W_CachePatchName("CONT2", PU_CACHE);
else
contsonic = W_CachePatchName("CONT1", PU_CACHE);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?");
// Draw a Sonic!
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic);
// Draw the continue markers! Show continues minus one.
x -= ncontinues * 6;
for (i = 0; i < ncontinues; ++i)
V_DrawContinueIcon(x + (i*12), 140, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);
V_DrawCenteredString(BASEVIDWIDTH/2, 168, 0, va("\x82*\x80" " %02d " "\x82*\x80", timetonext/TICRATE));
}
void F_ContinueTicker(void)
{
if (!imcontinuing)
{
// note the setup to prevent 2x reloading
if (timetonext >= 0)
timetonext--;
if (timetonext == 0)
Command_ExitGame_f();
}
else
{
// note the setup to prevent 2x reloading
if (continuetime >= 0)
continuetime--;
if (continuetime == 0)
G_Continue();
}
}
boolean F_ContinueResponder(event_t *event)
{
INT32 key = event->data1;
if (keypressed)
return true;
if (timetonext >= 21*TICRATE/2)
return false;
if (event->type != ev_keydown)
return false;
// remap virtual keys (mouse & joystick buttons)
switch (key)
{
case KEY_ENTER:
case KEY_SPACE:
case KEY_MOUSE1:
case KEY_JOY1:
case KEY_JOY1 + 2:
break;
default:
return false;
}
keypressed = true;
imcontinuing = true;
continuetime = TICRATE;
S_StartSound(0, sfx_itemup);
return true;
}
// ==================
// CUSTOM CUTSCENES
// ==================
static INT32 scenenum, cutnum;
static INT32 picxpos, picypos, picnum, pictime;
static INT32 textxpos, textypos;
static boolean dofadenow = false, cutsceneover = false;
static boolean runningprecutscene = false, precutresetplayer = false;
static void F_AdvanceToNextScene(void)
{
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
if (rendermode != render_none)
{
F_WipeStartScreen();
// Fade to any palette color you want.
if (cutscenes[cutnum]->scene[scenenum].fadecolor)
{
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,cutscenes[cutnum]->scene[scenenum].fadecolor);
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
F_WipeStartScreen();
}
}
2014-03-15 16:59:03 +00:00
// Don't increment until after endcutscene check
// (possible overflow / bad patch names from the one tic drawn before the fade)
if (scenenum+1 >= cutscenes[cutnum]->numscenes)
{
F_EndCutScene();
return;
}
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
2014-03-15 16:59:03 +00:00
++scenenum;
timetonext = 0;
stoptimer = 0;
picnum = 0;
picxpos = cutscenes[cutnum]->scene[scenenum].xcoord[picnum];
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
2016-07-06 04:09:17 +00:00
if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
2016-07-06 04:09:17 +00:00
cutscenes[cutnum]->scene[scenenum].musswitchflags,
cutscenes[cutnum]->scene[scenenum].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
2014-03-15 16:59:03 +00:00
// Fade to the next
F_NewCutscene(cutscenes[cutnum]->scene[scenenum].text);
picnum = 0;
picxpos = cutscenes[cutnum]->scene[scenenum].xcoord[picnum];
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
textxpos = cutscenes[cutnum]->scene[scenenum].textxpos;
textypos = cutscenes[cutnum]->scene[scenenum].textypos;
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
Implement Uncapped (squashed) Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com> Co-Authored-By: James R <justsomejames2@gmail.com> Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com> Co-Authored-By: katsy <katmint@live.com> Place Frame Interpolation in "Experimental" video options header This seems like an appropriate way to describe the feature for now. Add smooth level platter under interpolation, `renderdeltatics` `renderdeltatics` can be used as a standard delta time in any place, allowing for smooth menus. It will always be equal to `realtics` when frame interpolation is turned off, producing consistent framerate behavior everywhere it is used. Add smooth rendering to save select screen Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll Ensure viewsector is accurate to viewx/viewy This fixes a potential crash in OpenGL when changing between levels. Ensure + commands get executed before map start Always have precise_t defined Fix misc dropshadow issues Reset view interpolation on level load Remove unnecessary precipmobj thinker hack Add reset interpolation state functions Reset precip interpolation on snap to ceil Reset mobj interp state on TeleportMove Only swap view interp state if a tick is run Run anti-lag chasecam at tic frequency Fixes jittery and unstable chasecam in high latency netgames Homogenize mobj interpolations Add sector plane level interpolations Add SectorScroll interpolator Add SideScroll interpolator Add Polyobj interpolator Intialize interpolator list at a better time Delete interpolators associated with thinkers Interpolate mobj angles and player drawangle Interpolate HWR_DrawModel Add functions to handle interpolation Much less code duplication P_InitAngle, to fix angle interpolation on spawning objects Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. Do not speed up underwater/heatwave effect in OpenGL Closer OpenGL underwater/heatwave effect to Software Interpolate from time of previous tic Previously interpolated from last 35th of a second, which may be offset from game time due to connection lag. Consider this the proper fix to 54148a0dd0 too. Calculate FPS stuff even if frame is skipped I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging. Keep rect in memory Feel better about this than creating one all da time Lots of FPS stuff - Disabled VSync, due to the numerous problems it has. - Instead, added an FPS cap. - Frame interpolation is now tied to fpscap != 35. - By default, the FPS cap is set to the monitor's refresh rate. - Rewrote the FPS counter. (This also consolidates several more commits ahead of this fixing various issues. -eid) Misc changes after Kart cherry-picks Fix renderdeltatics with new timing data Update mobj oldstates before all thinkers Allow FPS cap values Adjust how FPS cap is checked to improve FPS stability Fix precip crash from missing vars Improve the framerate limiter's timing for extreme stable FPS Handle the sleep at the end of D_SRB2Loop instead of the start Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long. Reset mobj interp state on add Add mobj interpolator on load netgame Move mobj interpolators to r_fps Dynamic slope interpolators I_GetFrameTime to try and improve frame pace (It doesn't feel that much better though.) Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code Fix plane interpolation light level flickering Fix flickering plane interpolation for OpenGL in the exact same way Funny OpenGL renderer being at least 50% copy-pasted Software code :) P_SetOrigin & P_MoveOrigin to replace P_TeleportMove Convert P_TeleportMove use to origin funcs Revert "P_InitAngle, to fix angle interpolation on spawning objects" This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5. Waypoint polyobjects interpolate z & children Add interpolation to more moving plane types Adds interpolation to the following: - Crumbling platforms - Mario blocks - Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?) Reset overlays interp states each TryRunTics Interpolate model interpolation (lol) Use interp tracer pos for GL linkdraw Papersprite angle interpolation Makes the ending signpost smooth Move intermission emerald bounce to ticker Bring back shadows on polyobjects Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy. Fix a bunch of ticking in hu_ drawing functions Revert "Reset overlays interp states each TryRunTics" This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92. Move intro ticking out of the drawer Adjust 1up monitor icon z offsets Fixes interpolation issues with 1up monitors. Delta time choose player menu animations Add drawerlib deltaTime function Interpolate afterimages further back Use old sleep in dedicated mode Clamp cechotimer to 0 Fixes issues with cechos staying on-screen and glitching out (NiGHTS items for example). Revert "Remove unnecessary precipmobj thinker hack" This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e. Fix frame pacing when game lags behind The frame timestamp should've been made at the start of the frame, not the end. Fix I_FrameCapSleep not respecting cpusleep Jonathan Joestar bruh Allow dedicated to use precise sleep timing again Instead of only using one old sleep, just enforce framerate cap to match TICRATE. Make Lua TeleportMove call MoveOrigin Reset Metal fume interp state on appear Add interpdebug Put interpdebug stuff in perfstats instead Add timescale cvar Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping! Enable timescale outside of DEVELOP builds It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer! Force interpolation when timescale != 1.0 Reset old_z in MT_LOCKON think Fixes interpolation artifacting due to spawn pos. Fix cutscenes in interp Fix boss1 laser in interp Interpolate mobj scale Precalculate refresh rate Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well Fix interp scaling crashing software Reset interp scale when Lua sets .scale Disable angle interp on fresh mobjs Fix interp scale crash for hires sprites Interp shadow scales Copy interp state in P_SpawnMobjFromMobj Fix multiplayer character select Don't interpolate mobj state if frac = 1.0 Fix Mario block item placement Interpolate spritescale/offset x/y Fix offset copies for SpawnMobjFromMobj THANKS SAL Add Lua HUD drawlists Buffers draw calls between tics to ensure hooks run at the originally intended rate. Rename drawerlib deltaTime to getDeltaTime Make renderisnewtic is false between tics I know what I'm doing! I swear Completely refactor timing system Time is now tracked internally in the game using I_GetPreciseTime and I_UpdateTime. I_Time now pulls from this internal timer. The system code no longer needs to keep track of time itself. This significantly improves frame and tic timing in interp mode, resulting in a much smoother image with essentially no judder at any framerate. Ensure mobj interpolators reset on level load Ensure view is not interpolated on first frame Disable sprite offset interpolation (for now) Refactor timing code even more System layer is greatly simplified and framecap logic has been moved internally. I_Sleep now takes a sleep duration and I_SleepDuration generically implements a precise sleep with spin loop.
2019-10-06 22:40:52 +00:00
if (rendermode != render_none)
{
F_CutsceneDrawer();
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
}
2014-03-15 16:59:03 +00:00
}
void F_EndCutScene(void)
{
cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later
2014-03-15 16:59:03 +00:00
if (runningprecutscene)
{
if (server)
D_MapChange(gamemap, gametype, false, precutresetplayer, 0, true, false);
2014-03-15 16:59:03 +00:00
}
else
{
if (cutnum == creditscutscene-1)
F_StartGameEvaluation();
else if (cutnum == introtoplay-1)
D_StartTitle();
else if (nextmap < 1100-1)
G_NextLevel();
else
G_EndGame();
2014-03-15 16:59:03 +00:00
}
}
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer)
{
if (!cutscenes[cutscenenum])
return;
G_SetGamestate(GS_CUTSCENE);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
F_NewCutscene(cutscenes[cutscenenum]->scene[0].text);
cutsceneover = false;
runningprecutscene = precutscene;
precutresetplayer = resetplayer;
scenenum = picnum = 0;
cutnum = cutscenenum;
picxpos = cutscenes[cutnum]->scene[0].xcoord[0];
picypos = cutscenes[cutnum]->scene[0].ycoord[0];
textxpos = cutscenes[cutnum]->scene[0].textxpos;
textypos = cutscenes[cutnum]->scene[0].textypos;
pictime = cutscenes[cutnum]->scene[0].picduration[0];
keypressed = false;
finalecount = 0;
timetonext = 0;
animtimer = cutscenes[cutnum]->scene[0].picduration[0]; // Picture duration
stoptimer = 0;
2016-07-06 04:09:17 +00:00
if (cutscenes[cutnum]->scene[0].musswitch[0])
S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
2016-07-06 04:09:17 +00:00
cutscenes[cutnum]->scene[0].musswitchflags,
cutscenes[cutnum]->scene[0].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
2014-03-15 16:59:03 +00:00
else
S_StopMusic();
}
//
// F_CutsceneDrawer
//
void F_CutsceneDrawer(void)
{
if (dofadenow && rendermode != render_none)
{
F_WipeStartScreen();
// Fade to any palette color you want.
if (cutscenes[cutnum]->scene[scenenum].fadecolor)
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, cutscenes[cutnum]->scene[scenenum].fadecolor);
2014-03-15 16:59:03 +00:00
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
F_WipeStartScreen();
}
}
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
2014-03-15 16:59:03 +00:00
if (cutscenes[cutnum]->scene[scenenum].picname[picnum][0] != '\0')
{
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
}
if (dofadenow && rendermode != render_none)
{
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
}
V_DrawString(textxpos, textypos, 0, cutscene_disptext);
}
void F_CutsceneTicker(void)
{
INT32 i;
// Online clients tend not to instantly get the map change, so just wait
// and don't send 30 of them.
if (cutsceneover)
return;
// advance animation
finalecount++;
cutscene_boostspeed = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
2017-11-11 05:34:37 +00:00
if (netgame && i != serverplayer && !IsPlayerAdmin(i))
2014-03-15 16:59:03 +00:00
continue;
if (players[i].cmd.buttons & BT_BRAKE || players[i].cmd.buttons & BT_ACCELERATE) // SRB2kart
2014-03-15 16:59:03 +00:00
{
keypressed = false;
cutscene_boostspeed = 1;
if (timetonext)
timetonext = 2;
}
}
if (animtimer)
{
animtimer--;
if (animtimer <= 0)
{
if (picnum < 7 && cutscenes[cutnum]->scene[scenenum].picname[picnum+1][0] != '\0')
{
picnum++;
picxpos = cutscenes[cutnum]->scene[scenenum].xcoord[picnum];
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
animtimer = pictime;
}
else
timetonext = 2;
}
}
if (timetonext)
--timetonext;
if (++stoptimer > 2 && timetonext == 1)
F_AdvanceToNextScene();
else if (!timetonext && !F_WriteText())
timetonext = 5*TICRATE + 1;
}
boolean F_CutsceneResponder(event_t *event)
{
if (cutnum == introtoplay-1)
return F_IntroResponder(event);
return false;
}