mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-25 11:50:50 +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.
This commit is contained in:
parent
da1dbac164
commit
8f354ad9c1
65 changed files with 2815 additions and 597 deletions
|
@ -81,6 +81,7 @@ set(SRB2_CORE_HEADERS
|
|||
i_sound.h
|
||||
i_system.h
|
||||
i_tcp.h
|
||||
i_time.h
|
||||
i_video.h
|
||||
info.h
|
||||
keys.h
|
||||
|
@ -118,6 +119,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.c
|
||||
r_plane.c
|
||||
r_segs.c
|
||||
|
@ -129,6 +131,7 @@ set(SRB2_CORE_RENDER_SOURCES
|
|||
r_data.h
|
||||
r_defs.h
|
||||
r_draw.h
|
||||
r_fps.h
|
||||
r_local.h
|
||||
r_main.h
|
||||
r_plane.h
|
||||
|
@ -158,6 +161,7 @@ set(SRB2_CORE_GAME_SOURCES
|
|||
p_tick.c
|
||||
p_user.c
|
||||
k_kart.c
|
||||
i_time.c
|
||||
|
||||
p_local.h
|
||||
p_maputl.h
|
||||
|
@ -248,6 +252,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
|
|||
lua_consolelib.c
|
||||
lua_hooklib.c
|
||||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
lua_infolib.c
|
||||
lua_maplib.c
|
||||
lua_mathlib.c
|
||||
|
@ -260,6 +265,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
|
|||
set(SRB2_LUA_HEADERS
|
||||
lua_hook.h
|
||||
lua_hud.h
|
||||
lua_hudlib_drawlist.h
|
||||
lua_libs.h
|
||||
lua_script.h
|
||||
)
|
||||
|
|
|
@ -587,6 +587,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/r_bsp.o \
|
||||
$(OBJDIR)/r_data.o \
|
||||
$(OBJDIR)/r_draw.o \
|
||||
$(OBJDIR)/r_fps.o \
|
||||
$(OBJDIR)/r_main.o \
|
||||
$(OBJDIR)/r_plane.o \
|
||||
$(OBJDIR)/r_segs.o \
|
||||
|
@ -602,6 +603,7 @@ OBJS:=$(i_main_o) \
|
|||
$(OBJDIR)/mserv.o \
|
||||
$(OBJDIR)/http-mserv.o\
|
||||
$(OBJDIR)/i_tcp.o \
|
||||
$(OBJDIR)/i_time.o \
|
||||
$(OBJDIR)/lzf.o \
|
||||
$(OBJDIR)/vid_copy.o \
|
||||
$(OBJDIR)/b_bot.o \
|
||||
|
|
|
@ -82,13 +82,17 @@ INT64 current_time_in_ps() {
|
|||
return (t.tv_sec * (INT64)1000000) + t.tv_usec;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
void I_Sleep(UINT32 ms){}
|
||||
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
INT64 since_start = current_time_in_ps() - start_time;
|
||||
return (since_start*TICRATE)/1000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
|
|
|
@ -270,8 +270,8 @@ void B_RespawnBot(INT32 playernum)
|
|||
player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots];
|
||||
player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
|
||||
|
||||
P_TeleportMove(tails, x, y, z);
|
||||
P_SetOrigin(tails, x, y, z);
|
||||
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_FALL1
|
||||
P_SetScale(tails, sonic->scale);
|
||||
tails->destscale = sonic->destscale;
|
||||
tails->destscale = tails->old_scale = sonic->destscale;
|
||||
}
|
||||
|
|
|
@ -50,4 +50,5 @@ OBJS:=$(OBJS) \
|
|||
$(OBJDIR)/lua_skinlib.o \
|
||||
$(OBJDIR)/lua_thinkerlib.o \
|
||||
$(OBJDIR)/lua_maplib.o \
|
||||
$(OBJDIR)/lua_hudlib.o
|
||||
$(OBJDIR)/lua_hudlib.o \
|
||||
$(OBJDIR)/lua_hudlib_drawlist.o
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <unistd.h> //for unlink
|
||||
#endif
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
@ -2502,7 +2503,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
#endif
|
||||
}
|
||||
else
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5540,8 +5544,10 @@ static void SV_Maketic(void)
|
|||
maketic++;
|
||||
}
|
||||
|
||||
void TryRunTics(tic_t realtics)
|
||||
boolean TryRunTics(tic_t realtics)
|
||||
{
|
||||
boolean ticking;
|
||||
|
||||
// the machine has lagged but it is not so bad
|
||||
if (realtics > TICRATE/7) // FIXME: consistency failure!!
|
||||
{
|
||||
|
@ -5593,10 +5599,17 @@ void TryRunTics(tic_t realtics)
|
|||
if (player_joining)
|
||||
{
|
||||
hu_stopped = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (neededtic > gametic)
|
||||
ticking = neededtic > gametic;
|
||||
|
||||
if (player_joining)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ticking)
|
||||
{
|
||||
if (advancedemo)
|
||||
D_StartTitle();
|
||||
|
@ -5620,6 +5633,8 @@ void TryRunTics(tic_t realtics)
|
|||
{
|
||||
hu_stopped = true;
|
||||
}
|
||||
|
||||
return ticking;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -595,7 +595,7 @@ boolean Playing(void);
|
|||
void D_QuitNetGame(void);
|
||||
|
||||
//? How many ticks to run?
|
||||
void TryRunTics(tic_t realtic);
|
||||
boolean TryRunTics(tic_t realtic);
|
||||
|
||||
// extra data for lmps
|
||||
// these functions scare me. they contain magic.
|
||||
|
|
153
src/d_main.c
153
src/d_main.c
|
@ -50,6 +50,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "hu_stuff.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_time.h"
|
||||
#include "i_threads.h"
|
||||
#include "i_video.h"
|
||||
#include "m_argv.h"
|
||||
|
@ -73,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "dehacked.h" // Dehacked list test
|
||||
#include "m_cond.h" // condition initialization
|
||||
#include "fastcmp.h"
|
||||
#include "r_fps.h" // Frame interpolation/uncapped
|
||||
#include "keys.h"
|
||||
#include "filesrch.h" // refreshdirmenu
|
||||
|
||||
|
@ -268,7 +270,7 @@ void D_ProcessEvents(void)
|
|||
// added comment : there is a wipe eatch change of the gamestate
|
||||
gamestate_t wipegamestate = GS_LEVEL;
|
||||
|
||||
static void D_Display(void)
|
||||
static boolean D_Display(void)
|
||||
{
|
||||
boolean forcerefresh = false;
|
||||
static boolean wipe = false;
|
||||
|
@ -278,7 +280,7 @@ static void D_Display(void)
|
|||
if (!dedicated)
|
||||
{
|
||||
if (nodrawers)
|
||||
return; // for comparative timing/profiling
|
||||
return false; // for comparative timing/profiling
|
||||
|
||||
// check for change of screen size (video mode)
|
||||
if (setmodeneeded && !wipe)
|
||||
|
@ -343,7 +345,7 @@ static void D_Display(void)
|
|||
}
|
||||
|
||||
if (dedicated) //bail out after wipe logic
|
||||
return;
|
||||
return false;
|
||||
|
||||
// do buffered drawing
|
||||
switch (gamestate)
|
||||
|
@ -430,6 +432,8 @@ static void D_Display(void)
|
|||
// draw the view directly
|
||||
if (cv_renderview.value && !automapactive)
|
||||
{
|
||||
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
|
||||
|
@ -502,6 +506,8 @@ static void D_Display(void)
|
|||
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
R_RestoreLevelInterpolators();
|
||||
}
|
||||
|
||||
if (lastdraw)
|
||||
|
@ -607,8 +613,10 @@ static void D_Display(void)
|
|||
if (cv_shittyscreen.value)
|
||||
V_DrawVhsEffect(cv_shittyscreen.value == 2);
|
||||
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
return true; // Do I_FinishUpdate in the main loop
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
@ -619,7 +627,13 @@ tic_t rendergametic;
|
|||
|
||||
void D_SRB2Loop(void)
|
||||
{
|
||||
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
double deltatics = 0.0;
|
||||
double deltasecs = 0.0;
|
||||
|
||||
boolean interp = false;
|
||||
boolean doDisplay = false;
|
||||
boolean screenUpdate = false;
|
||||
|
||||
if (dedicated)
|
||||
server = true;
|
||||
|
@ -631,6 +645,7 @@ void D_SRB2Loop(void)
|
|||
I_DoStartupMouse();
|
||||
#endif
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
oldentertics = I_GetTime();
|
||||
|
||||
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
|
||||
|
@ -657,6 +672,19 @@ void D_SRB2Loop(void)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
// capbudget is the minimum precise_t duration of a single loop iteration
|
||||
precise_t capbudget;
|
||||
precise_t enterprecise = I_GetPreciseTime();
|
||||
precise_t finishprecise = enterprecise;
|
||||
|
||||
{
|
||||
// Casting the return value of a function is bad practice (apparently)
|
||||
double budget = round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision());
|
||||
capbudget = (precise_t) budget;
|
||||
}
|
||||
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
|
||||
if (lastwipetic)
|
||||
{
|
||||
oldentertics = lastwipetic;
|
||||
|
@ -668,7 +696,11 @@ void D_SRB2Loop(void)
|
|||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
if (demo.playback && gamestate == GS_LEVEL)
|
||||
{
|
||||
// Nicer place to put this.
|
||||
realtics = realtics * cv_playbackspeed.value;
|
||||
}
|
||||
|
||||
#ifdef DEBUGFILE
|
||||
if (!realtics)
|
||||
|
@ -676,45 +708,66 @@ void D_SRB2Loop(void)
|
|||
debugload--;
|
||||
#endif
|
||||
|
||||
if (!realtics && !singletics)
|
||||
{
|
||||
I_Sleep();
|
||||
continue;
|
||||
}
|
||||
interp = R_UsingFrameInterpolation() && !dedicated;
|
||||
doDisplay = screenUpdate = false;
|
||||
|
||||
#ifdef HW3SOUND
|
||||
HW3S_BeginFrameUpdate();
|
||||
#endif
|
||||
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
if (realtics > 0 || singletics)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
|
||||
// Update display, next frame, with current state.
|
||||
D_Display();
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic + TICRATE/17;
|
||||
|
||||
doDisplay = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
{
|
||||
doDisplay = true;
|
||||
}
|
||||
|
||||
renderisnewtic = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
else
|
||||
{
|
||||
D_Display();
|
||||
renderisnewtic = false;
|
||||
}
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
if (interp)
|
||||
{
|
||||
renderdeltatics = FLOAT_TO_FIXED(deltatics);
|
||||
|
||||
if (!(paused || P_AutoPause()))
|
||||
{
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
if (interp || doDisplay)
|
||||
{
|
||||
screenUpdate = D_Display();
|
||||
}
|
||||
|
||||
// consoleplayer -> displayplayers (hear sounds from viewpoint)
|
||||
|
@ -737,6 +790,34 @@ void D_SRB2Loop(void)
|
|||
Discord_RunCallbacks();
|
||||
}
|
||||
#endif
|
||||
|
||||
// I_FinishUpdate is now here instead of D_Display,
|
||||
// because it synchronizes it more closely with the frame counter.
|
||||
if (screenUpdate == true)
|
||||
{
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
}
|
||||
|
||||
// Fully completed frame made.
|
||||
finishprecise = I_GetPreciseTime();
|
||||
if (!singletics)
|
||||
{
|
||||
INT64 elapsed = (INT64)(finishprecise - enterprecise);
|
||||
if (elapsed > 0 && (INT64)capbudget > elapsed)
|
||||
{
|
||||
I_SleepDuration(capbudget - (finishprecise - enterprecise));
|
||||
}
|
||||
}
|
||||
// Capture the time once more to get the real delta time.
|
||||
finishprecise = I_GetPreciseTime();
|
||||
deltasecs = (double)((INT64)(finishprecise - enterprecise)) / I_GetPrecisePrecision();
|
||||
deltatics = deltasecs * NEWTICRATE;
|
||||
|
||||
// Only take screenshots after drawing.
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot)
|
||||
M_DoScreenShot();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1189,8 +1270,8 @@ void D_SRB2Main(void)
|
|||
//---------------------------------------------------- READY TIME
|
||||
// we need to check for dedicated before initialization of some subsystems
|
||||
|
||||
CONS_Printf("I_StartupTimer()...\n");
|
||||
I_StartupTimer();
|
||||
CONS_Printf("I_InitializeTime()...\n");
|
||||
I_InitializeTime();
|
||||
|
||||
// Make backups of some SOCcable tables.
|
||||
P_BackupTables();
|
||||
|
@ -1520,6 +1601,8 @@ void D_SRB2Main(void)
|
|||
// as having been modified for the first game.
|
||||
M_PushSpecialParameters(); // push all "+" parameter at the command buffer
|
||||
|
||||
COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin)
|
||||
|
||||
strncpy(connectedservername, cv_servername.string, MAXSERVERNAME);
|
||||
|
||||
if (M_CheckParm("-gametype") && M_IsNextParm())
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
@ -614,7 +615,10 @@ void Net_WaitAllAckReceived(UINT32 timeout)
|
|||
while (timeout > I_GetTime() && !Net_AllAcksReceived())
|
||||
{
|
||||
while (tictac == I_GetTime())
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
tictac = I_GetTime();
|
||||
HGetPacket();
|
||||
Net_AckTicker();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "console.h"
|
||||
#include "command.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -388,6 +388,7 @@ typedef struct player_s
|
|||
// SRB2kart stuff
|
||||
INT32 kartstuff[NUMKARTSTUFF];
|
||||
angle_t frameangle; // for the player add the ability to have the sprite only face other angles
|
||||
angle_t old_frameangle, old_frameangle2;
|
||||
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
|
||||
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right
|
||||
|
||||
|
|
|
@ -405,4 +405,6 @@ typedef UINT32 tic_t;
|
|||
#define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24)
|
||||
#endif
|
||||
|
||||
typedef UINT64 precise_t;
|
||||
|
||||
#endif //__DOOMTYPE__
|
||||
|
|
|
@ -11,12 +11,15 @@ UINT32 I_GetFreeMem(UINT32 *total)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
void I_Sleep(UINT32 ms){}
|
||||
|
||||
precise_t I_GetPreciseTime(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
UINT64 I_GetPrecisePrecision(void) {
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "r_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
|
@ -77,7 +78,6 @@ 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.
|
||||
|
@ -249,9 +249,9 @@ void F_StartIntro(void)
|
|||
}
|
||||
|
||||
//
|
||||
// F_IntroDrawScene
|
||||
// F_IntroDrawer
|
||||
//
|
||||
static void F_IntroDrawScene(void)
|
||||
void F_IntroDrawer(void)
|
||||
{
|
||||
boolean highres = false;
|
||||
INT32 cx = 8, cy = 128;
|
||||
|
@ -293,64 +293,6 @@ static void F_IntroDrawScene(void)
|
|||
V_DrawString(cx, cy, 0, cutscene_disptext);
|
||||
}
|
||||
|
||||
//
|
||||
// F_IntroDrawer
|
||||
//
|
||||
void F_IntroDrawer(void)
|
||||
{
|
||||
if (timetonext <= 0)
|
||||
{
|
||||
if (intro_scenenum == 0)
|
||||
{
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(99,true);
|
||||
}
|
||||
|
||||
// Stay on black for a bit. =)
|
||||
{
|
||||
tic_t quittime;
|
||||
quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
|
||||
while (quittime > I_GetTime())
|
||||
{
|
||||
I_OsPolling();
|
||||
I_UpdateNoBlit();
|
||||
#ifdef HAVE_THREADS
|
||||
I_lock_mutex(&m_menu_mutex);
|
||||
#endif
|
||||
M_Drawer(); // menu is drawn even on top of wipes
|
||||
#ifdef HAVE_THREADS
|
||||
I_unlock_mutex(m_menu_mutex);
|
||||
#endif
|
||||
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
|
||||
}
|
||||
}
|
||||
|
||||
D_StartTitle();
|
||||
// Yes, this is a weird hack, we need to force a wipe for this because the game state has changed in the middle of where it would normally wipe
|
||||
// Need to set the wipe start and then draw the first frame of the title screen to get it working
|
||||
F_WipeStartScreen();
|
||||
F_TitleScreenDrawer();
|
||||
wipegamestate = -1; // force a wipe
|
||||
return;
|
||||
}
|
||||
|
||||
F_NewCutscene(introtext[++intro_scenenum]);
|
||||
timetonext = introscenetime[intro_scenenum];
|
||||
|
||||
F_WipeStartScreen();
|
||||
wipegamestate = -1;
|
||||
animtimer = stoptimer = 0;
|
||||
}
|
||||
|
||||
intro_curtime = introscenetime[intro_scenenum] - timetonext;
|
||||
|
||||
F_IntroDrawScene();
|
||||
}
|
||||
|
||||
//
|
||||
// F_IntroTicker
|
||||
//
|
||||
|
@ -1318,6 +1260,22 @@ static boolean runningprecutscene = false, precutresetplayer = false;
|
|||
|
||||
static void F_AdvanceToNextScene(void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
@ -1325,6 +1283,7 @@ static void F_AdvanceToNextScene(void)
|
|||
F_EndCutScene();
|
||||
return;
|
||||
}
|
||||
|
||||
++scenenum;
|
||||
|
||||
timetonext = 0;
|
||||
|
@ -1340,7 +1299,6 @@ static void F_AdvanceToNextScene(void)
|
|||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
|
||||
// Fade to the next
|
||||
dofadenow = true;
|
||||
F_NewCutscene(cutscenes[cutnum]->scene[scenenum].text);
|
||||
|
||||
picnum = 0;
|
||||
|
@ -1350,6 +1308,14 @@ static void F_AdvanceToNextScene(void)
|
|||
textypos = cutscenes[cutnum]->scene[scenenum].textypos;
|
||||
|
||||
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
|
||||
|
||||
if (rendermode != render_none)
|
||||
{
|
||||
F_CutsceneDrawer();
|
||||
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
|
||||
}
|
||||
}
|
||||
|
||||
void F_EndCutScene(void)
|
||||
|
@ -1468,8 +1434,6 @@ void F_CutsceneTicker(void)
|
|||
finalecount++;
|
||||
cutscene_boostspeed = 0;
|
||||
|
||||
dofadenow = false;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (netgame && i != serverplayer && !IsPlayerAdmin(i))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
#include "m_menu.h"
|
||||
|
@ -365,7 +366,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lastwipetic = nowtime;
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "filesrch.h" // for refreshdirmenu
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "am_map.h"
|
||||
#include "m_random.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "m_cond.h" // condition sets
|
||||
#include "md5.h" // demo checksums
|
||||
#include "k_kart.h" // SRB2kart
|
||||
#include "r_fps.h" // frame interpolation/uncapped
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#include "discord.h"
|
||||
|
@ -2413,6 +2415,10 @@ void G_Ticker(boolean run)
|
|||
ST_Ticker();
|
||||
AM_Ticker();
|
||||
HU_Ticker();
|
||||
if (run)
|
||||
{
|
||||
R_UpdateViewInterpolation();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6131,7 +6137,7 @@ void G_ReadMetalTic(mobj_t *metal)
|
|||
// Read changes from the tic
|
||||
if (ziptic & GZT_XYZ)
|
||||
{
|
||||
P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
|
||||
P_MoveOrigin(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
|
||||
oldmetal.x = metal->x;
|
||||
oldmetal.y = metal->y;
|
||||
oldmetal.z = metal->z;
|
||||
|
|
|
@ -46,7 +46,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
|
|||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||
|
||||
//Hurdler: added for new development
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "../v_video.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../r_fps.h"
|
||||
#include "../r_local.h"
|
||||
#include "../r_bsp.h" // R_NoEncore
|
||||
#include "../r_main.h" // cv_fov
|
||||
|
@ -2389,6 +2390,7 @@ void HWR_Subsector(size_t num)
|
|||
INT32 light = 0;
|
||||
extracolormap_t *floorcolormap;
|
||||
extracolormap_t *ceilingcolormap;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef PARANOIA //no risk while developing, enough debugging nights!
|
||||
if (num >= addsubsector)
|
||||
|
@ -4139,14 +4141,26 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
|
||||
INT32 heightsec, phs;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
this_scale = FIXED_TO_FLOAT(thing->scale);
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
|
||||
|
@ -4156,8 +4170,8 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
return;
|
||||
|
||||
// The above can stay as it works for cutting sprites that are too close
|
||||
tr_x = FIXED_TO_FLOAT(thing->x);
|
||||
tr_y = FIXED_TO_FLOAT(thing->y);
|
||||
tr_x = FIXED_TO_FLOAT(interp.x);
|
||||
tr_y = FIXED_TO_FLOAT(interp.y);
|
||||
|
||||
// decide which patch to use for sprite relative to player
|
||||
#ifdef RANGECHECK
|
||||
|
@ -4192,10 +4206,7 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
|
||||
#endif
|
||||
|
||||
if (thing->player)
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
|
||||
else
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
|
||||
if (sprframe->rotate == SRF_SINGLE)
|
||||
{
|
||||
|
@ -4240,8 +4251,8 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (papersprite)
|
||||
{
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE((thing->angle)>>ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE((thing->angle)>>ANGLETOFINESHIFT));
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4268,12 +4279,12 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gz = FIXED_TO_FLOAT(interp.z + thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gzt = FIXED_TO_FLOAT(interp.z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
|
||||
gz = gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
|
||||
}
|
||||
|
||||
|
@ -4292,12 +4303,12 @@ void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
|
||||
{
|
||||
if (gr_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
|
||||
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
|
||||
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
|
||||
gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
|
||||
return;
|
||||
if (gr_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
|
||||
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gr_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
|
||||
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4375,9 +4386,25 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
unsigned rot = 0;
|
||||
UINT8 flip;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
|
||||
|
@ -4386,8 +4413,8 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (tz < ZCLIP_PLANE)
|
||||
return;
|
||||
|
||||
tr_x = FIXED_TO_FLOAT(thing->x);
|
||||
tr_y = FIXED_TO_FLOAT(thing->y);
|
||||
tr_x = FIXED_TO_FLOAT(interp.x);
|
||||
tr_y = FIXED_TO_FLOAT(interp.y);
|
||||
|
||||
// decide which patch to use for sprite relative to player
|
||||
if ((unsigned)thing->sprite >= numsprites)
|
||||
|
@ -4912,7 +4939,8 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
{
|
||||
// 10 by 10 grid. 2 coordinates (xy)
|
||||
float v[SCREENVERTS][SCREENVERTS][2];
|
||||
double disStart = leveltime;
|
||||
static double disStart = 0;
|
||||
|
||||
UINT8 x, y;
|
||||
INT32 WAVELENGTH;
|
||||
INT32 AMPLITUDE;
|
||||
|
@ -4921,15 +4949,15 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
// Modifies the wave.
|
||||
if (*type == postimg_water)
|
||||
{
|
||||
WAVELENGTH = 20; // Lower is longer
|
||||
AMPLITUDE = 20; // Lower is bigger
|
||||
FREQUENCY = 16; // Lower is faster
|
||||
WAVELENGTH = 5;
|
||||
AMPLITUDE = 20;
|
||||
FREQUENCY = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
WAVELENGTH = 10; // Lower is longer
|
||||
AMPLITUDE = 30; // Lower is bigger
|
||||
FREQUENCY = 4; // Lower is faster
|
||||
WAVELENGTH = 10;
|
||||
AMPLITUDE = 60;
|
||||
FREQUENCY = 4;
|
||||
}
|
||||
|
||||
for (x = 0; x < SCREENVERTS; x++)
|
||||
|
@ -4942,6 +4970,8 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
}
|
||||
}
|
||||
HWD.pfnPostImgRedraw(v);
|
||||
if (!(paused || P_AutoPause()))
|
||||
disStart += FIXED_TO_FLOAT(renderdeltatics);
|
||||
|
||||
// Capture the screen again for screen waving on the intermission
|
||||
if(gamestate != GS_INTERMISSION)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "hw_md2.h"
|
||||
#include "../d_main.h"
|
||||
#include "../r_bsp.h"
|
||||
#include "../r_fps.h"
|
||||
#include "../r_main.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../w_wad.h"
|
||||
|
@ -1128,6 +1129,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
float finalscale;
|
||||
interpmobjstate_t interp;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// Apparently people don't like jump frames like that, so back it goes
|
||||
//if (tics > durs)
|
||||
|
@ -1233,14 +1244,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
if (spr->mobj->frame & FF_ANIMATE)
|
||||
{
|
||||
// set duration and tics to be the correct values for FF_ANIMATE states
|
||||
durs = spr->mobj->state->var2;
|
||||
tics = spr->mobj->anim_duration;
|
||||
durs = (float)spr->mobj->state->var2;
|
||||
tics = (float)spr->mobj->anim_duration;
|
||||
}
|
||||
|
||||
//FIXME: this is not yet correct
|
||||
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
|
||||
|
||||
#ifdef USE_MODEL_NEXTFRAME
|
||||
// Interpolate the model interpolation. (lol)
|
||||
tics -= FixedToFloat(rendertimefrac);
|
||||
|
||||
if (cv_grmdls.value == 1 && tics <= durs)
|
||||
{
|
||||
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
|
||||
|
@ -1265,13 +1279,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
#endif
|
||||
|
||||
//Hurdler: it seems there is still a small problem with mobj angle
|
||||
p.x = FIXED_TO_FLOAT(spr->mobj->x);
|
||||
p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset;
|
||||
p.x = FIXED_TO_FLOAT(interp.x);
|
||||
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
|
||||
|
||||
if (spr->mobj->eflags & MFE_VERTICALFLIP)
|
||||
p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
|
||||
p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
|
||||
else
|
||||
p.z = FIXED_TO_FLOAT(spr->mobj->z);
|
||||
p.z = FIXED_TO_FLOAT(interp.z);
|
||||
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
sprdef = &((skin_t *)spr->mobj->skin)->spritedef;
|
||||
|
@ -1282,16 +1296,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
|
||||
if (sprframe->rotate)
|
||||
{
|
||||
fixed_t anglef;
|
||||
if (spr->mobj->player)
|
||||
anglef = AngleFixed(spr->mobj->player->frameangle);
|
||||
else
|
||||
anglef = AngleFixed(spr->mobj->angle);
|
||||
fixed_t anglef = AngleFixed(interp.angle);
|
||||
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
else
|
||||
{
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180);
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(interp.x, interp.y))-ANGLE_180);
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
p.anglex = 0.0f;
|
||||
|
@ -1311,7 +1322,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
#endif
|
||||
|
||||
// SRB2CBTODO: MD2 scaling support
|
||||
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
finalscale *= FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
p.flip = atransform.flip;
|
||||
#ifdef USE_FTRANSFORM_MIRROR
|
||||
|
|
|
@ -2865,7 +2865,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
|
|||
|
||||
#define BUFFER_OFFSET(i) ((char*)(i))
|
||||
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
|
@ -2884,11 +2884,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
scaley = scale;
|
||||
scalez = scale;
|
||||
|
||||
if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length
|
||||
if (duration > 0.0 && tics >= 0.0) // don't interpolate if instantaneous or infinite in length
|
||||
{
|
||||
UINT32 newtime = (duration - tics); // + 1;
|
||||
float newtime = (duration - tics); // + 1;
|
||||
|
||||
pol = (newtime)/(float)duration;
|
||||
pol = newtime / duration;
|
||||
|
||||
if (pol > 1.0f)
|
||||
pol = 1.0f;
|
||||
|
@ -3063,7 +3063,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
// -----------------+
|
||||
// HWRAPI DrawModel : Draw a model
|
||||
// -----------------+
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hook.h"
|
||||
#endif
|
||||
|
||||
|
@ -90,6 +91,10 @@ static boolean headsupactive = false;
|
|||
boolean hu_showscores; // draw rankings
|
||||
static char hu_tick;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
static huddrawlist_h luahuddrawlist_scores;
|
||||
#endif
|
||||
|
||||
patch_t *rflagico;
|
||||
patch_t *bflagico;
|
||||
patch_t *rmatcico;
|
||||
|
@ -176,6 +181,8 @@ static INT32 cechoflags = 0;
|
|||
// HEADS UP INIT
|
||||
//======================================================================
|
||||
|
||||
static tic_t resynch_ticker = 0;
|
||||
|
||||
#ifndef NONET
|
||||
// just after
|
||||
static void Command_Say_f(void);
|
||||
|
@ -385,12 +392,12 @@ static INT16 addy = 0; // use this to make the messages scroll smoothly when one
|
|||
|
||||
static void HU_removeChatText_Mini(void)
|
||||
{
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
size_t i;
|
||||
for(i=0;i<chat_nummsg_min-1;i++) {
|
||||
strcpy(chat_mini[i], chat_mini[i+1]);
|
||||
chat_timers[i] = chat_timers[i+1];
|
||||
}
|
||||
for(i=0;i<chat_nummsg_min-1;i++) {
|
||||
strcpy(chat_mini[i], chat_mini[i+1]);
|
||||
chat_timers[i] = chat_timers[i+1];
|
||||
}
|
||||
chat_nummsg_min--; // lost 1 msg.
|
||||
|
||||
// use addy and make shit slide smoothly af.
|
||||
|
@ -403,10 +410,10 @@ static void HU_removeChatText_Log(void)
|
|||
{
|
||||
// MPC: Don't create new arrays, just iterate through an existing one
|
||||
size_t i;
|
||||
for(i=0;i<chat_nummsg_log-1;i++) {
|
||||
strcpy(chat_log[i], chat_log[i+1]);
|
||||
}
|
||||
chat_nummsg_log--; // lost 1 msg.
|
||||
for(i=0;i<chat_nummsg_log-1;i++) {
|
||||
strcpy(chat_log[i], chat_log[i+1]);
|
||||
}
|
||||
chat_nummsg_log--; // lost 1 msg.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1071,6 +1078,15 @@ void HU_Ticker(void)
|
|||
hu_showscores = !chat_on;
|
||||
else
|
||||
hu_showscores = false;
|
||||
|
||||
if (chat_on)
|
||||
{
|
||||
// count down the scroll timer.
|
||||
if (chat_scrolltime > 0)
|
||||
chat_scrolltime--;
|
||||
}
|
||||
|
||||
if (cechotimer > 0) --cechotimer;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
|
@ -2204,8 +2220,6 @@ static void HU_DrawCEcho(void)
|
|||
echoptr = line;
|
||||
echoptr++;
|
||||
}
|
||||
|
||||
--cechotimer;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2305,9 +2319,6 @@ void HU_Drawer(void)
|
|||
// draw chat string plus cursor
|
||||
if (chat_on)
|
||||
{
|
||||
// count down the scroll timer.
|
||||
if (chat_scrolltime > 0)
|
||||
chat_scrolltime--;
|
||||
if (!OLDCHAT)
|
||||
HU_DrawChat();
|
||||
else
|
||||
|
@ -2317,30 +2328,10 @@ void HU_Drawer(void)
|
|||
{
|
||||
typelines = 1;
|
||||
chat_scrolltime = 0;
|
||||
|
||||
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden)
|
||||
HU_drawMiniChat(); // draw messages in a cool fashion.
|
||||
}
|
||||
|
||||
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
|
||||
// handle chat timers
|
||||
for (i=0; (i<chat_nummsg_min); i++)
|
||||
{
|
||||
if (chat_timers[i] > 0)
|
||||
chat_timers[i]--;
|
||||
else
|
||||
HU_removeChatText_Mini();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cechotimer)
|
||||
|
@ -2363,7 +2354,12 @@ void HU_Drawer(void)
|
|||
#endif
|
||||
HU_DrawRankings();
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_ScoresHUD();
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_scores);
|
||||
LUAh_ScoresHUD(luahuddrawlist_scores);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_scores);
|
||||
#endif
|
||||
}
|
||||
if (demo.playback)
|
||||
|
@ -2398,12 +2394,9 @@ void HU_Drawer(void)
|
|||
// draw desynch text
|
||||
if (hu_resynching)
|
||||
{
|
||||
static UINT32 resynch_ticker = 0;
|
||||
char resynch_text[14];
|
||||
UINT32 i;
|
||||
|
||||
// Animate the dots
|
||||
resynch_ticker++;
|
||||
strcpy(resynch_text, "Resynching");
|
||||
for (i = 0; i < (resynch_ticker / 16) % 4; i++)
|
||||
strcat(resynch_text, ".");
|
||||
|
|
|
@ -42,15 +42,32 @@ extern UINT8 keyboard_started;
|
|||
*/
|
||||
UINT32 I_GetFreeMem(UINT32 *total);
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
/** \brief Returns precise time value for performance measurement. The precise
|
||||
time should be a monotonically increasing counter, and will wrap.
|
||||
precise_t is internally represented as an unsigned integer and
|
||||
integer arithmetic may be used directly between values of precise_t.
|
||||
*/
|
||||
precise_t I_GetPreciseTime(void);
|
||||
|
||||
/** \brief The I_Sleep function
|
||||
/** \brief Get the precision of precise_t in units per second. Invocations of
|
||||
this function for the program's duration MUST return the same value.
|
||||
*/
|
||||
UINT64 I_GetPrecisePrecision(void);
|
||||
|
||||
/** \brief Get the current time in rendering tics, including fractions.
|
||||
*/
|
||||
double I_GetFrameTime(void);
|
||||
|
||||
/** \brief Sleeps for the given duration in milliseconds. Depending on the
|
||||
operating system's scheduler, the calling thread may give up its
|
||||
time slice for a longer duration. The implementation should give a
|
||||
best effort to sleep for the given duration, without spin-locking.
|
||||
Calling code should check the current precise time after sleeping
|
||||
and not assume the thread has slept for the expected duration.
|
||||
|
||||
\return void
|
||||
*/
|
||||
void I_Sleep(void);
|
||||
void I_Sleep(UINT32 ms);
|
||||
|
||||
/** \brief Get events
|
||||
|
||||
|
|
117
src/i_time.c
Normal file
117
src/i_time.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// 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 i_time.c
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#include "i_time.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "m_fixed.h"
|
||||
#include "i_system.h"
|
||||
|
||||
timestate_t g_time;
|
||||
|
||||
static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUNIT, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_timescale = {"timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, NULL, FRACUNIT, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static precise_t enterprecise, oldenterprecise;
|
||||
static fixed_t entertic, oldentertics;
|
||||
static double tictimer;
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
return g_time.time;
|
||||
}
|
||||
|
||||
void I_InitializeTime(void)
|
||||
{
|
||||
g_time.time = 0;
|
||||
g_time.timefrac = 0;
|
||||
|
||||
enterprecise = 0;
|
||||
oldenterprecise = 0;
|
||||
tictimer = 0.0;
|
||||
|
||||
CV_RegisterVar(&cv_timescale);
|
||||
|
||||
// I_StartupTimer is preserved for potential subsystems that need to setup
|
||||
// timing information for I_GetPreciseTime and sleeping
|
||||
I_StartupTimer();
|
||||
}
|
||||
|
||||
void I_UpdateTime(fixed_t timescale)
|
||||
{
|
||||
double ticratescaled;
|
||||
double elapsedseconds;
|
||||
tic_t realtics;
|
||||
|
||||
// get real tics
|
||||
ticratescaled = (double)TICRATE * FIXED_TO_FLOAT(timescale);
|
||||
|
||||
enterprecise = I_GetPreciseTime();
|
||||
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();
|
||||
tictimer += elapsedseconds;
|
||||
while (tictimer > 1.0/ticratescaled)
|
||||
{
|
||||
entertic += 1;
|
||||
tictimer -= 1.0/ticratescaled;
|
||||
}
|
||||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
oldenterprecise = enterprecise;
|
||||
|
||||
// Update global time state
|
||||
g_time.time += realtics;
|
||||
{
|
||||
double fractional, integral;
|
||||
fractional = modf(tictimer * ticratescaled, &integral);
|
||||
g_time.timefrac = FLOAT_TO_FIXED(fractional);
|
||||
}
|
||||
}
|
||||
|
||||
void I_SleepDuration(precise_t duration)
|
||||
{
|
||||
UINT64 precision = I_GetPrecisePrecision();
|
||||
INT32 sleepvalue = cv_sleep.value;
|
||||
UINT64 delaygranularity;
|
||||
precise_t cur;
|
||||
precise_t dest;
|
||||
|
||||
{
|
||||
double gran = round(((double)(precision / 1000) * sleepvalue * 2.1));
|
||||
delaygranularity = (UINT64)gran;
|
||||
}
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
dest = cur + duration;
|
||||
|
||||
// the reason this is not dest > cur is because the precise counter may wrap
|
||||
// two's complement arithmetic is our friend here, though!
|
||||
// e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
|
||||
// 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
|
||||
while ((INT64)(dest - cur) > 0)
|
||||
{
|
||||
// If our cv_sleep value exceeds the remaining sleep duration, use the
|
||||
// hard sleep function.
|
||||
if (sleepvalue > 0 && (dest - cur) > delaygranularity)
|
||||
{
|
||||
I_Sleep(sleepvalue);
|
||||
}
|
||||
|
||||
// Otherwise, this is a spinloop.
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
}
|
||||
}
|
54
src/i_time.h
Normal file
54
src/i_time.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2022 by Sonic Team Junior.
|
||||
//
|
||||
// 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 i_time.h
|
||||
/// \brief Timing for the system layer.
|
||||
|
||||
#ifndef __I_TIME_H__
|
||||
#define __I_TIME_H__
|
||||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "m_fixed.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct timestate_s {
|
||||
tic_t time;
|
||||
fixed_t timefrac;
|
||||
} timestate_t;
|
||||
|
||||
extern timestate_t g_time;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
/** \brief Called by D_SRB2Loop, returns current time in game tics.
|
||||
*/
|
||||
tic_t I_GetTime(void);
|
||||
|
||||
/** \brief Initializes timing system.
|
||||
*/
|
||||
void I_InitializeTime(void);
|
||||
|
||||
void I_UpdateTime(fixed_t timescale);
|
||||
|
||||
/** \brief Block for at minimum the duration specified. This function makes a
|
||||
best effort not to oversleep, and will spinloop if sleeping would
|
||||
take too long. However, callers should still check the current time
|
||||
after this returns.
|
||||
*/
|
||||
void I_SleepDuration(precise_t duration);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __I_TIME_H__
|
|
@ -135,4 +135,6 @@ void I_BeginRead(void);
|
|||
*/
|
||||
void I_EndRead(void);
|
||||
|
||||
UINT32 I_GetRefreshRate(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -182,10 +182,10 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// 1-Up Box Sprites (uses player sprite)
|
||||
// Kart: hide for now, fix for R2
|
||||
{SPR_NULL, 0, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2
|
||||
{SPR_NULL, 0, 2, {NULL}, 0, 18, S_PLAY_BOX2}, // S_PLAY_BOX1
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 18, S_PLAY_BOX1}, // S_PLAY_BOX2
|
||||
{SPR_NULL, 0, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1
|
||||
{SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2
|
||||
{SPR_NULL, 0, 12, {NULL}, 0, 4, S_PLAY_ICON3}, // S_PLAY_ICON2
|
||||
{SPR_NULL, 0, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
|
||||
|
||||
// Level end sign (uses player sprite)
|
||||
|
|
14
src/k_kart.c
14
src/k_kart.c
|
@ -2731,7 +2731,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
P_TeleportMove(th, th->x, th->y, th->z);
|
||||
P_SetOrigin(th, th->x, th->y, th->z);
|
||||
// spawn on the ground if the player is on the ground
|
||||
if (P_MobjFlip(source) < 0)
|
||||
{
|
||||
|
@ -3314,7 +3314,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
P_TeleportMove(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
|
||||
P_SetOrigin(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
|
||||
if (P_MobjWasRemoved(mo))
|
||||
return NULL;
|
||||
|
||||
|
@ -3827,7 +3827,7 @@ void K_DropHnextList(player_t *player)
|
|||
{
|
||||
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
|
||||
// This should set it for FOFs
|
||||
//P_TeleportMove(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
|
||||
//P_SetOrigin(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
|
||||
|
||||
if (flip == 1)
|
||||
{
|
||||
|
@ -4101,7 +4101,7 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
z = player->mo->z + player->mo->height - cur->height;
|
||||
|
||||
cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player
|
||||
P_TeleportMove(cur, player->mo->x, player->mo->y, z);
|
||||
P_MoveOrigin(cur, player->mo->x, player->mo->y, z);
|
||||
cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
|
||||
cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
|
||||
cur->flags &= ~MF_NOCLIPTHING;
|
||||
|
@ -4203,7 +4203,7 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false);
|
||||
|
||||
if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT)
|
||||
P_TeleportMove(cur, targx, targy, cur->z);
|
||||
P_MoveOrigin(cur, targx, targy, cur->z);
|
||||
|
||||
cur = cur->hnext;
|
||||
}
|
||||
|
@ -4287,12 +4287,12 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
diffy = targy - cur->y;
|
||||
diffz = targz - cur->z;
|
||||
|
||||
P_TeleportMove(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
|
||||
P_MoveOrigin(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
|
||||
cur->tracer->y + diffy + P_ReturnThrustY(cur, cur->angle + angoffset, 6*cur->scale), cur->tracer->z + diffz);
|
||||
P_SetScale(cur->tracer, (cur->tracer->destscale = 3*cur->scale/4));
|
||||
}
|
||||
|
||||
P_TeleportMove(cur, targx, targy, targz);
|
||||
P_MoveOrigin(cur, targx, targy, targz);
|
||||
K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks.
|
||||
num = (num+1) % 2;
|
||||
cur = cur->hnext;
|
||||
|
|
|
@ -1026,7 +1026,40 @@ static int lib_pTeleportMove(lua_State *L)
|
|||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
|
||||
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin");
|
||||
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lib_pSetOrigin(lua_State *L)
|
||||
{
|
||||
mobj_t *ptmthing = tmthing;
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_SetOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int lib_pMoveOrigin(lua_State *L)
|
||||
{
|
||||
mobj_t *ptmthing = tmthing;
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
NOHUD
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
|
@ -3038,6 +3071,8 @@ static luaL_Reg lib[] = {
|
|||
{"P_TryMove",lib_pTryMove},
|
||||
{"P_Move",lib_pMove},
|
||||
{"P_TeleportMove",lib_pTeleportMove},
|
||||
{"P_SetOrigin",lib_pSetOrigin},
|
||||
{"P_MoveOrigin",lib_pMoveOrigin},
|
||||
{"P_SlideMove",lib_pSlideMove},
|
||||
{"P_BounceMove",lib_pBounceMove},
|
||||
{"P_CheckSight", lib_pCheckSight},
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
/// \file lua_hud.h
|
||||
/// \brief HUD enable/disable flags for Lua scripting
|
||||
|
||||
#ifndef __LUA_HUD_H__
|
||||
#define __LUA_HUD_H__
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
enum hud {
|
||||
hud_stagetitle = 0,
|
||||
hud_textspectator,
|
||||
|
@ -36,5 +41,7 @@ extern boolean hud_running;
|
|||
|
||||
boolean LUA_HudEnabled(enum hud option);
|
||||
|
||||
void LUAh_GameHUD(player_t *stplyr);
|
||||
void LUAh_ScoresHUD(void);
|
||||
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
|
||||
void LUAh_ScoresHUD(huddrawlist_h list);
|
||||
|
||||
#endif // __LUA_HUD_H__
|
||||
|
|
132
src/lua_hudlib.c
132
src/lua_hudlib.c
|
@ -344,7 +344,8 @@ static int libd_draw(lua_State *L)
|
|||
{
|
||||
INT32 x, y, flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
|
@ -356,7 +357,14 @@ static int libd_draw(lua_State *L)
|
|||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDraw(list, x, y, patch, flags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -365,7 +373,8 @@ static int libd_drawScaled(lua_State *L)
|
|||
fixed_t x, y, scale;
|
||||
INT32 flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
|
@ -380,7 +389,14 @@ static int libd_drawScaled(lua_State *L)
|
|||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawScaled(list, x, y, scale, patch, flags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -391,6 +407,7 @@ static int libd_drawOnMinimap(lua_State *L)
|
|||
patch_t *patch; // patch we want to draw
|
||||
const UINT8 *colormap = NULL; // do we want to colormap this patch?
|
||||
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
|
||||
huddrawlist_h list;
|
||||
|
||||
// variables used to replicate k_kart's mmap drawer:
|
||||
INT32 lumpnum;
|
||||
|
@ -553,13 +570,24 @@ static int libd_drawOnMinimap(lua_State *L)
|
|||
amypos = amnumypos + ((my + AutomapPic->height/2)<<FRACBITS) - patchh;
|
||||
|
||||
// and NOW we can FINALLY DRAW OUR GOD DAMN PATCH :V
|
||||
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawScaled(list, amxpos, amypos, scale, patch, splitflags, colormap);
|
||||
else
|
||||
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawNum(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags, num;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
|
@ -567,13 +595,22 @@ static int libd_drawNum(lua_State *L)
|
|||
flags = luaL_optinteger(L, 4, 0);
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawTallNum(x, y, flags, num);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawNum(list, x, y, num, flags);
|
||||
else
|
||||
V_DrawTallNum(x, y, flags, num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawPaddedNum(lua_State *L)
|
||||
{
|
||||
INT32 x, y, flags, num, digits;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
|
@ -582,7 +619,14 @@ static int libd_drawPaddedNum(lua_State *L)
|
|||
flags = luaL_optinteger(L, 5, 0);
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawPaddedTallNum(x, y, flags, num, digits);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawPaddedNum(list, x, y, num, digits, flags);
|
||||
else
|
||||
V_DrawPaddedTallNum(x, y, flags, num, digits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -606,6 +650,7 @@ static int libd_drawPingNum(lua_State *L)
|
|||
|
||||
static int libd_drawFill(lua_State *L)
|
||||
{
|
||||
huddrawlist_h list;
|
||||
INT32 x = luaL_optinteger(L, 1, 0);
|
||||
INT32 y = luaL_optinteger(L, 2, 0);
|
||||
INT32 w = luaL_optinteger(L, 3, BASEVIDWIDTH);
|
||||
|
@ -613,7 +658,15 @@ static int libd_drawFill(lua_State *L)
|
|||
INT32 c = luaL_optinteger(L, 5, 31);
|
||||
|
||||
HUDONLY
|
||||
V_DrawFill(x, y, w, h, c);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawFill(list, x, y, w, h, c);
|
||||
else
|
||||
V_DrawFill(x, y, w, h, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -622,6 +675,7 @@ static int libd_fadeScreen(lua_State *L)
|
|||
UINT16 color = luaL_checkinteger(L, 1);
|
||||
UINT8 strength = luaL_checkinteger(L, 2);
|
||||
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
|
||||
|
@ -631,18 +685,31 @@ static int libd_fadeScreen(lua_State *L)
|
|||
if (strength > maxstrength)
|
||||
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (strength == maxstrength) // Allow as a shortcut for drawfill...
|
||||
{
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawFill(list, 0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
else
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
V_DrawFadeScreen(color, strength);
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddFadeScreen(list, color, strength);
|
||||
else
|
||||
V_DrawFadeScreen(color, strength);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_drawString(lua_State *L)
|
||||
{
|
||||
huddrawlist_h list;
|
||||
fixed_t x = luaL_checkinteger(L, 1);
|
||||
fixed_t y = luaL_checkinteger(L, 2);
|
||||
const char *str = luaL_checkstring(L, 3);
|
||||
|
@ -652,6 +719,15 @@ static int libd_drawString(lua_State *L)
|
|||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// okay, sorry, this is kind of ugly
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawString(list, x, y, str, flags, align);
|
||||
else
|
||||
switch(align)
|
||||
{
|
||||
// hu_font
|
||||
|
@ -691,11 +767,20 @@ static int libd_drawKartString(lua_State *L)
|
|||
fixed_t y = luaL_checkinteger(L, 2);
|
||||
const char *str = luaL_checkstring(L, 3);
|
||||
INT32 flags = luaL_optinteger(L, 4, V_ALLOWLOWERCASE);
|
||||
huddrawlist_h list;
|
||||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
V_DrawKartString(x, y, flags, str);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
list = (huddrawlist_h) lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (LUA_HUD_IsDrawListValid(list))
|
||||
LUA_HUD_AddDrawKartString(list, x, y, str, flags);
|
||||
else
|
||||
V_DrawKartString(x, y, flags, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -800,6 +885,14 @@ static int libd_getlocaltransflag(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Return the time elapsed for the previous frame, in tics.
|
||||
static int libd_getDeltaTime(lua_State *L)
|
||||
{
|
||||
HUDONLY
|
||||
lua_pushfixed(L, renderdeltatics);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static luaL_Reg lib_draw[] = {
|
||||
{"patchExists", libd_patchExists},
|
||||
{"cachePatch", libd_cachePatch},
|
||||
|
@ -821,6 +914,7 @@ static luaL_Reg lib_draw[] = {
|
|||
{"renderer", libd_renderer},
|
||||
{"localTransFlag", libd_getlocaltransflag},
|
||||
{"drawOnMinimap", libd_drawOnMinimap},
|
||||
{"getDeltaTime", libd_getDeltaTime},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -956,10 +1050,13 @@ boolean LUA_HudEnabled(enum hud option)
|
|||
}
|
||||
|
||||
// Hook for HUD rendering
|
||||
void LUAh_GameHUD(player_t *stplayr)
|
||||
void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_game)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_pop(gL, -1);
|
||||
|
@ -1004,12 +1101,18 @@ void LUAh_GameHUD(player_t *stplayr)
|
|||
}
|
||||
lua_pop(gL, -1);
|
||||
hud_running = false;
|
||||
|
||||
lua_pushlightuserdata(gL, NULL);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
}
|
||||
|
||||
void LUAh_ScoresHUD(void)
|
||||
void LUAh_ScoresHUD(huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_pop(gL, -1);
|
||||
|
@ -1029,6 +1132,9 @@ void LUAh_ScoresHUD(void)
|
|||
}
|
||||
lua_pop(gL, -1);
|
||||
hud_running = false;
|
||||
|
||||
lua_pushlightuserdata(gL, NULL);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
407
src/lua_hudlib_drawlist.c
Normal file
407
src/lua_hudlib_drawlist.c
Normal file
|
@ -0,0 +1,407 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2014-2016 by John "JTE" Muniz.
|
||||
// Copyright (C) 2014-2022 by Sonic Team Junior.
|
||||
//
|
||||
// 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 lua_hudlib_drawlist.c
|
||||
/// \brief a data structure for managing cached drawlists for the Lua hud lib
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
enum drawitem_e {
|
||||
DI_Draw = 0,
|
||||
DI_DrawScaled,
|
||||
DI_DrawNum,
|
||||
DI_DrawPaddedNum,
|
||||
DI_DrawFill,
|
||||
DI_DrawString,
|
||||
DI_DrawKartString,
|
||||
DI_DrawLevelTitle,
|
||||
DI_FadeScreen,
|
||||
DI_MAX,
|
||||
};
|
||||
|
||||
// A single draw item with all possible arguments needed for a draw call.
|
||||
typedef struct drawitem_s {
|
||||
enum drawitem_e type;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t w;
|
||||
fixed_t h;
|
||||
INT32 c;
|
||||
fixed_t scale;
|
||||
fixed_t hscale;
|
||||
fixed_t vscale;
|
||||
patch_t *patch;
|
||||
INT32 flags;
|
||||
UINT16 basecolor;
|
||||
UINT16 outlinecolor;
|
||||
UINT8 *colormap;
|
||||
UINT8 *basecolormap;
|
||||
UINT8 *outlinecolormap;
|
||||
fixed_t sx;
|
||||
fixed_t sy;
|
||||
INT32 num;
|
||||
INT32 digits;
|
||||
const char *str;
|
||||
UINT16 color;
|
||||
UINT8 strength;
|
||||
INT32 align;
|
||||
} drawitem_t;
|
||||
|
||||
// The internal structure of a drawlist.
|
||||
struct huddrawlist_s {
|
||||
drawitem_t *items;
|
||||
size_t items_capacity;
|
||||
size_t items_len;
|
||||
char *strbuf;
|
||||
size_t strbuf_capacity;
|
||||
size_t strbuf_len;
|
||||
};
|
||||
|
||||
// alignment types for v.drawString
|
||||
enum align {
|
||||
align_left = 0,
|
||||
align_center,
|
||||
align_right,
|
||||
align_fixed,
|
||||
align_small,
|
||||
align_smallright,
|
||||
align_thin,
|
||||
align_thinright
|
||||
};
|
||||
|
||||
huddrawlist_h LUA_HUD_CreateDrawList(void)
|
||||
{
|
||||
huddrawlist_h drawlist;
|
||||
|
||||
drawlist = (huddrawlist_h) Z_CallocAlign(sizeof(struct huddrawlist_s), PU_STATIC, NULL, 64);
|
||||
drawlist->items = NULL;
|
||||
drawlist->items_capacity = 0;
|
||||
drawlist->items_len = 0;
|
||||
drawlist->strbuf = NULL;
|
||||
drawlist->strbuf_capacity = 0;
|
||||
drawlist->strbuf_len = 0;
|
||||
|
||||
return drawlist;
|
||||
}
|
||||
|
||||
void LUA_HUD_ClearDrawList(huddrawlist_h list)
|
||||
{
|
||||
// rather than deallocate, we'll just save the existing allocation and empty
|
||||
// it out for reuse
|
||||
|
||||
// this memset probably isn't necessary
|
||||
if (list->items)
|
||||
{
|
||||
memset(list->items, 0, sizeof(drawitem_t) * list->items_capacity);
|
||||
}
|
||||
|
||||
list->items_len = 0;
|
||||
|
||||
if (list->strbuf)
|
||||
{
|
||||
list->strbuf[0] = 0;
|
||||
}
|
||||
list->strbuf_len = 0;
|
||||
}
|
||||
|
||||
void LUA_HUD_DestroyDrawList(huddrawlist_h list)
|
||||
{
|
||||
if (list == NULL) return;
|
||||
|
||||
if (list->items)
|
||||
{
|
||||
Z_Free(list->items);
|
||||
}
|
||||
Z_Free(list);
|
||||
}
|
||||
|
||||
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
|
||||
{
|
||||
if (!list) return false;
|
||||
|
||||
// that's all we can really do to check the validity of the handle right now
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t AllocateDrawItem(huddrawlist_h list)
|
||||
{
|
||||
if (!list) I_Error("can't allocate draw item: invalid list");
|
||||
if (list->items_capacity <= list->items_len + 1)
|
||||
{
|
||||
if (list->items_capacity == 0) list->items_capacity = 128;
|
||||
else list->items_capacity *= 2;
|
||||
list->items = (drawitem_t *) Z_ReallocAlign(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL, 64);
|
||||
}
|
||||
|
||||
return list->items_len++;
|
||||
}
|
||||
|
||||
// copy string to list's internal string buffer
|
||||
// lua can deallocate the string before we get to use it, so it's important to
|
||||
// keep our own copy
|
||||
static const char *CopyString(huddrawlist_h list, const char* str)
|
||||
{
|
||||
size_t lenstr;
|
||||
|
||||
if (!list) I_Error("can't allocate string; invalid list");
|
||||
lenstr = strlen(str);
|
||||
if (list->strbuf_capacity <= list->strbuf_len + lenstr + 1)
|
||||
{
|
||||
if (list->strbuf_capacity == 0) list->strbuf_capacity = 256;
|
||||
else list->strbuf_capacity *= 2;
|
||||
list->strbuf = (char*) Z_ReallocAlign(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL, 8);
|
||||
}
|
||||
const char *result = (const char *) &list->strbuf[list->strbuf_len];
|
||||
strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1);
|
||||
list->strbuf_len += lenstr + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDraw(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_Draw;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->patch = patch;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawScaled(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t scale,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawScaled;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->scale = scale;
|
||||
item->patch = patch;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawPaddedNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 digits,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawPaddedNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->digits = digits;
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawFill(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 w,
|
||||
INT32 h,
|
||||
INT32 c
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawFill;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->w = w;
|
||||
item->h = h;
|
||||
item->c = c;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags,
|
||||
INT32 align
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
item->align = align;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawKartString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawLevelTitle(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawLevelTitle;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->str = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddFadeScreen(
|
||||
huddrawlist_h list,
|
||||
UINT16 color,
|
||||
UINT8 strength
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_FadeScreen;
|
||||
item->color = color;
|
||||
item->strength = strength;
|
||||
}
|
||||
|
||||
void LUA_HUD_DrawList(huddrawlist_h list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!list) I_Error("HUD drawlist invalid");
|
||||
if (list->items_len <= 0) return;
|
||||
if (!list->items) I_Error("HUD drawlist->items invalid");
|
||||
|
||||
for (i = 0; i < list->items_len; i++)
|
||||
{
|
||||
drawitem_t *item = &list->items[i];
|
||||
|
||||
switch (item->type)
|
||||
{
|
||||
case DI_Draw:
|
||||
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
|
||||
break;
|
||||
case DI_DrawScaled:
|
||||
V_DrawFixedPatch(item->x, item->y, item->scale, item->flags, item->patch, item->colormap);
|
||||
break;
|
||||
case DI_DrawNum:
|
||||
V_DrawTallNum(item->x, item->y, item->flags, item->num);
|
||||
break;
|
||||
case DI_DrawPaddedNum:
|
||||
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
|
||||
break;
|
||||
case DI_DrawFill:
|
||||
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
|
||||
break;
|
||||
case DI_DrawString:
|
||||
switch(item->align)
|
||||
{
|
||||
// hu_font
|
||||
case align_left:
|
||||
V_DrawString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_center:
|
||||
V_DrawCenteredString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_right:
|
||||
V_DrawRightAlignedString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_fixed:
|
||||
V_DrawStringAtFixed(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
// hu_font, 0.5x scale
|
||||
case align_small:
|
||||
V_DrawSmallString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_smallright:
|
||||
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
// tny_font
|
||||
case align_thin:
|
||||
V_DrawThinString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_thinright:
|
||||
V_DrawRightAlignedThinString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DI_DrawKartString:
|
||||
V_DrawKartString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case DI_DrawLevelTitle:
|
||||
V_DrawLevelTitle(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case DI_FadeScreen:
|
||||
V_DrawFadeScreen(item->color, item->strength);
|
||||
break;
|
||||
default:
|
||||
I_Error("can't draw draw list item: invalid draw list item type");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
112
src/lua_hudlib_drawlist.h
Normal file
112
src/lua_hudlib_drawlist.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2022-2022 by Sonic Team Junior.
|
||||
//
|
||||
// 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 lua_hudlib_drawlist.h
|
||||
/// \brief a data structure for managing cached drawlists for the Lua hud lib
|
||||
|
||||
// The idea behinds this module is to cache drawcall information into an ordered
|
||||
// list to repeat the same draw operations in later frames. It's used to ensure
|
||||
// that the HUD hooks from Lua are called at precisely 35hz to avoid problems
|
||||
// with variable framerates in existing Lua addons.
|
||||
|
||||
#ifndef __LUA_HUDLIB_DRAWLIST__
|
||||
#define __LUA_HUDLIB_DRAWLIST__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct huddrawlist_s *huddrawlist_h;
|
||||
|
||||
// Create a new drawlist. Returns a handle to it.
|
||||
huddrawlist_h LUA_HUD_CreateDrawList(void);
|
||||
// Clears the draw list.
|
||||
void LUA_HUD_ClearDrawList(huddrawlist_h list);
|
||||
// Destroys the drawlist, invalidating the given handle
|
||||
void LUA_HUD_DestroyDrawList(huddrawlist_h list);
|
||||
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list);
|
||||
|
||||
void LUA_HUD_AddDraw(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
);
|
||||
void LUA_HUD_AddDrawScaled(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t scale,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
);
|
||||
void LUA_HUD_AddDrawNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawPaddedNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 num,
|
||||
INT32 digits,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawFill(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 w,
|
||||
INT32 h,
|
||||
INT32 c
|
||||
);
|
||||
void LUA_HUD_AddDrawString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags,
|
||||
INT32 align
|
||||
);
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddDrawLevelTitle(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
const char *str,
|
||||
INT32 flags
|
||||
);
|
||||
void LUA_HUD_AddFadeScreen(
|
||||
huddrawlist_h list,
|
||||
UINT16 color,
|
||||
UINT8 strength
|
||||
);
|
||||
|
||||
// Draws the given draw list
|
||||
void LUA_HUD_DrawList(huddrawlist_h list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __LUA_HUDLIB_DRAWLIST__
|
|
@ -373,7 +373,7 @@ static int mobj_get(lua_State *L)
|
|||
}
|
||||
|
||||
#define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
|
||||
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_TeleportMove") " instead.", mobj_opt[field])
|
||||
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
|
||||
static int mobj_set(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -639,6 +639,7 @@ static int mobj_set(lua_State *L)
|
|||
scale = FRACUNIT/100;
|
||||
mo->destscale = scale;
|
||||
P_SetScale(mo, scale);
|
||||
mo->old_scale = scale;
|
||||
break;
|
||||
}
|
||||
case mobj_destscale:
|
||||
|
|
|
@ -495,7 +495,7 @@ void Command_RTeleport_f(void)
|
|||
CONS_Printf(M_GetText("Teleporting by %d, %d, %d...\n"), intx, inty, FixedInt((intz-p->mo->z)));
|
||||
|
||||
P_MapStart();
|
||||
if (!P_TeleportMove(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
|
||||
if (!P_SetOrigin(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
|
||||
else
|
||||
S_StartSound(p->mo, sfx_mixup);
|
||||
|
@ -562,7 +562,7 @@ void Command_Teleport_f(void)
|
|||
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
|
||||
|
||||
P_MapStart();
|
||||
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
|
||||
if (!P_SetOrigin(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
|
||||
else
|
||||
S_StartSound(p->mo, sfx_mixup);
|
||||
|
@ -1107,13 +1107,13 @@ void OP_ObjectplaceMovement(player_t *player)
|
|||
if (cmd->forwardmove != 0)
|
||||
{
|
||||
P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
|
||||
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
player->mo->momx = player->mo->momy = 0;
|
||||
}
|
||||
/*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed
|
||||
{
|
||||
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
|
||||
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
|
||||
player->mo->momx = player->mo->momy = 0;
|
||||
}*/
|
||||
|
||||
|
|
22
src/m_menu.c
22
src/m_menu.c
|
@ -22,6 +22,7 @@
|
|||
#include "d_main.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "console.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_local.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "g_game.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
// Data.
|
||||
#include "sounds.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_threads.h"
|
||||
|
||||
|
@ -1255,9 +1257,10 @@ static menuitem_t OP_VideoOptionsMenu[] =
|
|||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "FPS Cap", &cv_fpscap, 110},
|
||||
|
||||
#ifdef HWRENDER
|
||||
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 120},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 130},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -6912,6 +6915,7 @@ static void M_DrawLoad(void)
|
|||
INT32 ymod = 0, offset = 0;
|
||||
|
||||
M_DrawMenuTitle();
|
||||
fixed_t scrollfrac = FixedDiv(2, 3);
|
||||
|
||||
if (menumovedir != 0) //movement illusion
|
||||
{
|
||||
|
@ -9337,7 +9341,7 @@ static void M_HandleConnectIP(INT32 choice)
|
|||
// ========================
|
||||
// Tails 03-02-2002
|
||||
|
||||
static INT32 multi_tics;
|
||||
static fixed_t multi_tics;
|
||||
static state_t *multi_state;
|
||||
|
||||
// this is set before entering the MultiPlayer setup menu,
|
||||
|
@ -9524,14 +9528,15 @@ static void M_DrawSetupMultiPlayerMenu(void)
|
|||
#undef iconwidth
|
||||
|
||||
// anim the player in the box
|
||||
if (--multi_tics <= 0)
|
||||
multi_tics -= renderdeltatics;
|
||||
while (multi_tics <= 0)
|
||||
{
|
||||
st = multi_state->nextstate;
|
||||
if (st != S_NULL)
|
||||
multi_state = &states[st];
|
||||
multi_tics = multi_state->tics;
|
||||
if (multi_tics == -1)
|
||||
multi_tics = 15;
|
||||
if (multi_tics <= -1*FRACUNIT)
|
||||
multi_tics += 15*FRACUNIT;
|
||||
}
|
||||
|
||||
// skin 0 is default player sprite
|
||||
|
@ -9692,7 +9697,7 @@ static void M_SetupMultiPlayer(INT32 choice)
|
|||
(void)choice;
|
||||
|
||||
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
|
||||
multi_tics = multi_state->tics;
|
||||
multi_tics = multi_state->tics*FRACUNIT;
|
||||
strcpy(setupm_name, cv_playername.string);
|
||||
|
||||
// set for player 1
|
||||
|
@ -9723,7 +9728,7 @@ static void M_SetupMultiPlayer2(INT32 choice)
|
|||
(void)choice;
|
||||
|
||||
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
|
||||
multi_tics = multi_state->tics;
|
||||
multi_tics = multi_state->tics*FRACUNIT;
|
||||
strcpy (setupm_name, cv_playername2.string);
|
||||
|
||||
// set for splitscreen secondary player
|
||||
|
@ -11226,7 +11231,8 @@ void M_QuitResponse(INT32 ch)
|
|||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001
|
||||
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
|
||||
I_Sleep();
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
}
|
||||
I_Quit();
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
#include "g_input.h"
|
||||
#include "i_time.h"
|
||||
#include "i_video.h"
|
||||
#include "d_main.h"
|
||||
#include "m_argv.h"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -600,6 +601,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
@ -676,6 +680,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
|
||||
ceiling->tag = sec->tag;
|
||||
ceiling->type = type;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -8660,10 +8660,10 @@ void A_LightningFollowPlayer(mobj_t *actor)
|
|||
{
|
||||
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
P_TeleportMove(actor, sx, sy, actor->target->z);
|
||||
P_MoveOrigin(actor, sx, sy, actor->target->z);
|
||||
}
|
||||
else // else just teleport to player directly
|
||||
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
|
||||
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
|
||||
actor->momx = actor->target->momx;
|
||||
|
@ -10731,7 +10731,7 @@ void A_VileAttack(mobj_t *actor)
|
|||
// move the fire between the vile and the player
|
||||
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
|
||||
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
|
||||
P_TeleportMove(fire,
|
||||
P_MoveOrigin(fire,
|
||||
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
fire->z);
|
||||
|
@ -10776,7 +10776,7 @@ void A_VileAttack(mobj_t *actor)
|
|||
// move the fire between the vile and the player
|
||||
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
|
||||
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
|
||||
P_TeleportMove(fire,
|
||||
P_MoveOrigin(fire,
|
||||
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
|
||||
fire->z);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -705,6 +706,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
|
|||
{
|
||||
faller->sector->ceilingheight = faller->ceilingwasheight;
|
||||
faller->sector->floorheight = faller->floorwasheight;
|
||||
R_ClearLevelInterpolatorState(&faller->thinker);
|
||||
}
|
||||
}
|
||||
else // Up
|
||||
|
@ -713,6 +715,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
|
|||
{
|
||||
faller->sector->ceilingheight = faller->ceilingwasheight;
|
||||
faller->sector->floorheight = faller->floorwasheight;
|
||||
R_ClearLevelInterpolatorState(&faller->thinker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2862,6 +2865,9 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
|
|||
}
|
||||
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
|
@ -2995,6 +3001,10 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
@ -3089,6 +3099,10 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
|
|||
bouncer->distance = FRACUNIT;
|
||||
bouncer->low = 1;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
#undef speed
|
||||
#undef distance
|
||||
|
@ -3135,6 +3149,10 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
|
|||
faller->direction = -1;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
#undef speed
|
||||
#undef direction
|
||||
|
@ -3210,6 +3228,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ);
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3250,6 +3272,10 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
block->vars[5] = FRACUNIT; // distance
|
||||
block->vars[6] = 1; // low
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, false);
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, true);
|
||||
|
||||
if (itsamonitor)
|
||||
{
|
||||
oldx = thing->x;
|
||||
|
@ -3258,9 +3284,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
}
|
||||
|
||||
P_UnsetThingPosition(thing);
|
||||
thing->x = roversector->soundorg.x;
|
||||
thing->y = roversector->soundorg.y;
|
||||
thing->z = topheight;
|
||||
thing->x = thing->old_x = roversector->soundorg.x;
|
||||
thing->y = thing->old_y = roversector->soundorg.y;
|
||||
thing->z = thing->old_z = topheight;
|
||||
thing->momz = FixedMul(6*FRACUNIT, thing->scale);
|
||||
P_SetThingPosition(thing);
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
|
@ -3289,9 +3315,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
|
|||
if (itsamonitor)
|
||||
{
|
||||
P_UnsetThingPosition(tmthing);
|
||||
tmthing->x = oldx;
|
||||
tmthing->y = oldy;
|
||||
tmthing->z = oldz;
|
||||
tmthing->x = thing->old_x = oldx;
|
||||
tmthing->y = thing->old_y = oldy;
|
||||
tmthing->z = thing->old_z = oldz;
|
||||
tmthing->momx = 1;
|
||||
tmthing->momy = 1;
|
||||
P_SetThingPosition(tmthing);
|
||||
|
|
|
@ -348,7 +348,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (!special->target)
|
||||
return; // foolproof crash prevention check!!!!!
|
||||
|
||||
P_TeleportMove(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
|
||||
P_SetOrigin(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
|
||||
player->mo->angle = special->target->angle;
|
||||
P_SetObjectMomZ(player->mo, 12<<FRACBITS, false);
|
||||
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);
|
||||
|
|
|
@ -348,7 +348,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
|
|||
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
|
||||
boolean P_Move(mobj_t *actor, fixed_t speed);
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
void P_SlideMove(mobj_t *mo, boolean forceslide);
|
||||
void P_BouncePlayerMove(mobj_t *mo);
|
||||
void P_BounceMove(mobj_t *mo);
|
||||
|
|
32
src/p_map.c
32
src/p_map.c
|
@ -19,6 +19,7 @@
|
|||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h" // NiGHTS stuff
|
||||
#include "r_fps.h"
|
||||
#include "r_state.h"
|
||||
#include "r_main.h"
|
||||
#include "r_sky.h"
|
||||
|
@ -75,7 +76,7 @@ camera_t *mapcampointer;
|
|||
//
|
||||
// P_TeleportMove
|
||||
//
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
// the move is ok,
|
||||
// so link the thing into its new position
|
||||
|
@ -105,6 +106,30 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
|||
return true;
|
||||
}
|
||||
|
||||
// P_SetOrigin - P_TeleportMove which RESETS interpolation values.
|
||||
//
|
||||
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
boolean result = P_TeleportMove(thing, x, y, z);
|
||||
|
||||
if (result == true)
|
||||
{
|
||||
thing->old_x = thing->x;
|
||||
thing->old_y = thing->y;
|
||||
thing->old_z = thing->z;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// P_MoveOrigin - P_TeleportMove which KEEPS interpolation values.
|
||||
//
|
||||
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
return P_TeleportMove(thing, x, y, z);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MOVEMENT ITERATOR FUNCTIONS
|
||||
// =========================================================================
|
||||
|
@ -599,9 +624,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
return true; // underneath
|
||||
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
thing->z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
|
||||
thing->z = thing->old_z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
|
||||
else
|
||||
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
|
||||
thing->z = thing->old_z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1);
|
||||
return true;
|
||||
|
@ -1904,7 +1929,6 @@ if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a
|
|||
if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld)
|
||||
== P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld))
|
||||
return true; // the line doesn't cross between collider's start or end
|
||||
|
||||
}
|
||||
|
||||
// A line has been hit
|
||||
|
|
61
src/p_mobj.c
61
src/p_mobj.c
|
@ -18,6 +18,7 @@
|
|||
#include "hu_stuff.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
|
@ -3795,15 +3796,22 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
|
|||
|
||||
void P_SnowThinker(precipmobj_t *mobj)
|
||||
{
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
// adjust height
|
||||
if ((mobj->z += mobj->momz) <= mobj->floorz)
|
||||
{
|
||||
mobj->z = mobj->ceilingz;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
void P_RainThinker(precipmobj_t *mobj)
|
||||
{
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
if (mobj->state != &states[S_RAIN1])
|
||||
|
@ -3823,6 +3831,7 @@ void P_RainThinker(precipmobj_t *mobj)
|
|||
return;
|
||||
|
||||
mobj->z = mobj->ceilingz;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
P_SetPrecipMobjState(mobj, S_RAIN1);
|
||||
|
||||
return;
|
||||
|
@ -4405,7 +4414,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
|
|||
while ((base = base->tracer))
|
||||
{
|
||||
for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s)
|
||||
P_TeleportMove(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
|
||||
P_MoveOrigin(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
|
||||
angle += ANGLE_MAX/3;
|
||||
}
|
||||
}
|
||||
|
@ -5151,7 +5160,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
|
|||
if (mobj->health > 3) {
|
||||
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
|
||||
P_SetScale(mobj->tracer, mobj->tracer->destscale);
|
||||
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
|
||||
P_SetOrigin(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
|
||||
mobj->tracer->momx = mobj->momx;
|
||||
mobj->tracer->momy = mobj->momy;
|
||||
mobj->tracer->momz = mobj->momz;
|
||||
|
@ -5821,9 +5830,9 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
|
|||
// place us on top of them then.
|
||||
source->momx = source->momy = source->momz = 0;
|
||||
P_UnsetThingPosition(source);
|
||||
source->x = tx;
|
||||
source->y = ty;
|
||||
source->z = tz;
|
||||
source->x = source->old_x = tx;
|
||||
source->y = source->old_x = ty;
|
||||
source->z = source->old_x = tz;
|
||||
P_SetThingPosition(source);
|
||||
}
|
||||
}
|
||||
|
@ -6101,7 +6110,7 @@ void P_RunShadows(void)
|
|||
if (dest->type == MT_THUNDERSHIELD)
|
||||
dest = dest->target;
|
||||
|
||||
P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z);
|
||||
P_SetOrigin(mobj, dest->x, dest->y, mobj->target->z);
|
||||
|
||||
if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height))
|
||||
|| (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z)))
|
||||
|
@ -6119,7 +6128,7 @@ void P_RunShadows(void)
|
|||
P_SetScale(mobj, FixedDiv(mobj->scale, max(FRACUNIT, ((mobj->target->z-mobj->z)/200)+FRACUNIT)));
|
||||
|
||||
// Check new position to see if you should still be on that ledge
|
||||
P_TeleportMove(mobj, dest->x, dest->y, mobj->z);
|
||||
P_SetOrigin(mobj, dest->x, dest->y, mobj->z);
|
||||
|
||||
mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz);
|
||||
|
||||
|
@ -7000,7 +7009,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (mobj->target->eflags & MFE_VERTICALFLIP)
|
||||
z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height);
|
||||
|
||||
P_TeleportMove(mobj, x, y, z);
|
||||
P_MoveOrigin(mobj, x, y, z);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -7400,7 +7409,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
|
||||
break;
|
||||
case MT_HAMMER:
|
||||
if (mobj->z <= mobj->floorz)
|
||||
|
@ -8027,7 +8036,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
|
||||
mobj->angle = mobj->target->angle;
|
||||
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
|
||||
P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
|
||||
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
|
||||
P_SetScale(mobj, mobj->target->scale);
|
||||
|
||||
|
@ -8076,7 +8085,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_SetOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_BRAKEDRIFT:
|
||||
if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target))
|
||||
|
@ -8096,7 +8105,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
|
||||
newx = mobj->target->x + P_ReturnThrustX(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
|
||||
newy = mobj->target->y + P_ReturnThrustY(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
|
||||
P_TeleportMove(mobj, newx, newy, mobj->target->z);
|
||||
P_MoveOrigin(mobj, newx, newy, mobj->target->z);
|
||||
|
||||
mobj->angle = travelangle - ((ANGLE_90/5)*mobj->target->player->kartstuff[k_drift]);
|
||||
P_SetScale(mobj, (mobj->destscale = mobj->target->scale));
|
||||
|
@ -8124,7 +8133,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_INSTASHIELDB:
|
||||
mobj->flags2 ^= MF2_DONTDRAW;
|
||||
|
@ -8137,7 +8146,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
break;
|
||||
case MT_BATTLEPOINT:
|
||||
if (!mobj->target || P_MobjWasRemoved(mobj->target))
|
||||
|
@ -8159,7 +8168,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->movefactor = mobj->target->height;
|
||||
}
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
|
||||
break;
|
||||
case MT_THUNDERSHIELD:
|
||||
{
|
||||
|
@ -8194,7 +8203,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
desty = mobj->target->y;
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, destx, desty, mobj->target->z);
|
||||
P_MoveOrigin(mobj, destx, desty, mobj->target->z);
|
||||
break;
|
||||
}
|
||||
case MT_ROCKETSNEAKER:
|
||||
|
@ -8230,7 +8239,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
return;
|
||||
}
|
||||
|
||||
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
|
||||
mobj->angle = mobj->target->angle;
|
||||
mobj->scalespeed = mobj->target->scalespeed;
|
||||
mobj->destscale = mobj->target->destscale;
|
||||
|
@ -8291,7 +8300,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (cur->lastlook == 2 || cur->lastlook == 3)
|
||||
offy *= -1;
|
||||
|
||||
P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z);
|
||||
P_MoveOrigin(cur, mobj->x + offx, mobj->y + offy, mobj->z);
|
||||
cur->scalespeed = mobj->target->scalespeed;
|
||||
cur->destscale = mobj->target->destscale;
|
||||
P_SetScale(cur, mobj->target->scale);
|
||||
|
@ -8416,7 +8425,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
while (cur && !P_MobjWasRemoved(cur))
|
||||
{
|
||||
cur->angle += FixedAngle(mobj->info->speed);
|
||||
P_TeleportMove(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
|
||||
P_MoveOrigin(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
|
||||
mobj->y + FINESINE((cur->angle*8)>>ANGLETOFINESHIFT), mobj->z);
|
||||
//P_SpawnGhostMobj(cur)->tics = 2;
|
||||
|
||||
|
@ -8549,7 +8558,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1));
|
||||
|
||||
if (cur && !P_MobjWasRemoved(cur))
|
||||
P_TeleportMove(cur, wx, wy, wz);
|
||||
P_MoveOrigin(cur, wx, wy, wz);
|
||||
else
|
||||
cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT);
|
||||
|
||||
|
@ -8660,7 +8669,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
continue;
|
||||
}
|
||||
else // Move into place
|
||||
P_TeleportMove(cur, mobj->x, mobj->y, segz);
|
||||
P_MoveOrigin(cur, mobj->x, mobj->y, segz);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8734,7 +8743,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj->extravalue1 = 1;
|
||||
player->kartstuff[k_offroad] += 2<<FRACBITS;
|
||||
|
||||
P_TeleportMove(mobj,
|
||||
P_MoveOrigin(mobj,
|
||||
player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius)
|
||||
+ P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<<FRACBITS),
|
||||
player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius)
|
||||
|
@ -9855,7 +9864,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_SIDE);
|
||||
P_SetTarget(&cur->target, mobj);
|
||||
cur->threshold = i;
|
||||
P_TeleportMove(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
|
||||
P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
|
||||
cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)), cur->z);
|
||||
cur->angle = ANGLE_90*(cur->threshold+1);
|
||||
|
||||
|
@ -9925,6 +9934,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP))
|
||||
P_CheckGravity(mobj, false);
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
@ -10086,6 +10097,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
|| mobj->subsector->sector->floorpic == skyflatnum)
|
||||
mobj->precipflags |= PCF_PIT;
|
||||
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
@ -10237,6 +10250,8 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
#endif
|
||||
P_RemoveThinker((thinker_t *)mobj);
|
||||
}
|
||||
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
}
|
||||
|
||||
// This does not need to be added to Lua.
|
||||
|
|
11
src/p_mobj.h
11
src/p_mobj.h
|
@ -274,6 +274,8 @@ typedef struct mobj_s
|
|||
|
||||
// Info for drawing: position.
|
||||
fixed_t x, y, z;
|
||||
fixed_t old_x, old_y, old_z; // position interpolation
|
||||
fixed_t old_x2, old_y2, old_z2;
|
||||
|
||||
// More list: links in sector (if needed)
|
||||
struct mobj_s *snext;
|
||||
|
@ -281,6 +283,8 @@ typedef struct mobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle; // orientation
|
||||
angle_t old_angle; // orientation interpolation
|
||||
angle_t old_angle2;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
UINT16 anim_duration; // for FF_ANIMATE states
|
||||
|
@ -356,6 +360,8 @@ typedef struct mobj_s
|
|||
UINT32 mobjnum; // A unique number for this mobj. Used for restoring pointers on save games.
|
||||
|
||||
fixed_t scale;
|
||||
fixed_t old_scale; // interpolation
|
||||
fixed_t old_scale2;
|
||||
fixed_t destscale;
|
||||
fixed_t scalespeed;
|
||||
|
||||
|
@ -370,6 +376,7 @@ typedef struct mobj_s
|
|||
|
||||
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
|
||||
|
||||
boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation)
|
||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
|
@ -389,6 +396,8 @@ typedef struct precipmobj_s
|
|||
|
||||
// Info for drawing: position.
|
||||
fixed_t x, y, z;
|
||||
fixed_t old_x, old_y, old_z; // position interpolation
|
||||
fixed_t old_x2, old_y2, old_z2;
|
||||
|
||||
// More list: links in sector (if needed)
|
||||
struct precipmobj_s *snext;
|
||||
|
@ -396,6 +405,8 @@ typedef struct precipmobj_s
|
|||
|
||||
// More drawing info: to determine current sprite.
|
||||
angle_t angle; // orientation
|
||||
angle_t old_angle; // orientation interpolation
|
||||
angle_t old_angle2;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
UINT16 anim_duration; // for FF_ANIMATE states
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "p_tick.h"
|
||||
#include "p_local.h"
|
||||
#include "p_polyobj.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "r_state.h"
|
||||
#include "r_defs.h"
|
||||
|
@ -2367,6 +2368,9 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
th->turnobjs = prdata->turnobjs;
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
|
@ -2428,6 +2432,9 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2443,12 +2450,14 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
{
|
||||
polyobj_t *po;
|
||||
polyobj_t *oldpo;
|
||||
polywaypoint_t *th;
|
||||
mobj_t *mo2;
|
||||
mobj_t *first = NULL;
|
||||
mobj_t *last = NULL;
|
||||
mobj_t *target = NULL;
|
||||
thinker_t *wp;
|
||||
INT32 start;
|
||||
|
||||
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
|
||||
{
|
||||
|
@ -2594,6 +2603,26 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
// T_PolyObjWaypoint is the only polyobject movement
|
||||
// that can adjust z, so we add these ones too.
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
|
||||
|
||||
// Most other polyobject functions handle children by recursively
|
||||
// giving each child another thinker. T_PolyObjWaypoint handles
|
||||
// it manually though, which means we need to manually give them
|
||||
// interpolation here instead.
|
||||
start = 0;
|
||||
oldpo = po;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
{
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
|
||||
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
|
||||
}
|
||||
|
||||
// Set pointnum
|
||||
th->pointnum = target->health;
|
||||
|
||||
|
@ -2645,6 +2674,9 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// start action on mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2685,6 +2717,9 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// start action on mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2756,6 +2791,9 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
@ -2859,6 +2897,9 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
|
|||
|
||||
oldpo = po;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_Polyobj(&th->thinker, po);
|
||||
|
||||
// apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
while ((po = Polyobj_GetChild(oldpo, &start)))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_state.h"
|
||||
#include "w_wad.h"
|
||||
|
@ -2163,6 +2164,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
|
|||
P_SetTarget(&waypointcap, mobj);
|
||||
|
||||
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "p_saveg.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_sound.h" // for I_PlayCD()..
|
||||
#include "i_video.h" // for I_FinishUpdate()..
|
||||
#include "r_sky.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "r_things.h"
|
||||
#include "r_sky.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_fps.h" // R_ResetViewInterpolation in level load
|
||||
|
||||
#include "s_sound.h"
|
||||
#include "st_stuff.h"
|
||||
|
@ -2909,7 +2911,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
{
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lastwipetic = nowtime;
|
||||
if (moviemode) // make sure we save frames for the white hold too
|
||||
M_SaveFrame();
|
||||
|
@ -2988,7 +2993,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
R_ClearLevelSplats();
|
||||
#endif
|
||||
|
||||
R_InitializeLevelInterpolators();
|
||||
|
||||
P_InitThinkers();
|
||||
R_InitMobjInterpolators();
|
||||
P_InitCachedActions();
|
||||
|
||||
/// \note for not spawning precipitation, etc. when loading netgame snapshots
|
||||
|
@ -3375,6 +3383,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
G_AddMapToBuffer(gamemap-1);
|
||||
|
||||
R_ResetViewInterpolation();
|
||||
R_ResetViewInterpolation();
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
43
src/p_spec.c
43
src/p_spec.c
|
@ -20,6 +20,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_setup.h" // levelflats for flat animation
|
||||
#include "r_data.h"
|
||||
#include "r_fps.h"
|
||||
#include "m_random.h"
|
||||
#include "p_mobj.h"
|
||||
#include "i_system.h"
|
||||
|
@ -2384,7 +2385,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
UINT8 i;
|
||||
|
||||
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
|
||||
P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z);
|
||||
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
|
||||
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
{
|
||||
|
@ -2846,7 +2847,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// Reset bot too.
|
||||
if (bot) {
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
P_TeleportMove(bot, mo->x, mo->y, mo->z);
|
||||
P_SetOrigin(bot, mo->x, mo->y, mo->z);
|
||||
bot->momx = bot->momy = bot->momz = 1;
|
||||
bot->pmomz = 0;
|
||||
bot->player->rmomx = bot->player->rmomy = 1;
|
||||
|
@ -2890,7 +2891,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// (Teleport them to you so they don't break it.)
|
||||
if (bot && (bot->flags2 & MF2_TWOD) != (mo->flags2 & MF2_TWOD)) {
|
||||
bot->flags2 = (bot->flags2 & ~MF2_TWOD) | (mo->flags2 & MF2_TWOD);
|
||||
P_TeleportMove(bot, mo->x, mo->y, mo->z);
|
||||
P_SetOrigin(bot, mo->x, mo->y, mo->z);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -5277,6 +5278,10 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
|
|||
floater->sector = sec;
|
||||
floater->vars[0] = tag;
|
||||
floater->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a bridge thinker.
|
||||
|
@ -5309,6 +5314,9 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
|
|||
// Control sector tags should be End_Tag + (End_Tag - Start_Tag)
|
||||
bridge->vars[4] = sourceline->tag; // Start tag
|
||||
bridge->vars[5] = (sides[sourceline->sidenum[0]].textureoffset>>FRACBITS); // End tag
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&bridge->thinker, §ors[affectee], false);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -5388,6 +5396,10 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
|
|||
- (sec->ceilingheight - sec->floorheight);
|
||||
|
||||
raise->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, true);
|
||||
}
|
||||
|
||||
// Function to maintain backwards compatibility
|
||||
|
@ -5430,6 +5442,10 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
|||
- (sec->ceilingheight - sec->floorheight);
|
||||
|
||||
airbob->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a thwomp thinker.
|
||||
|
@ -5471,6 +5487,11 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
|
|||
thwomp->sourceline = sourceline;
|
||||
thwomp->sector->floordata = thwomp;
|
||||
thwomp->sector->ceilingdata = thwomp;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, true);
|
||||
|
||||
return;
|
||||
#undef speed
|
||||
#undef direction
|
||||
|
@ -7036,6 +7057,22 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
|
|||
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
|
||||
s->affectee = affectee;
|
||||
P_AddThinker(&s->thinker);
|
||||
|
||||
// interpolation
|
||||
switch (type)
|
||||
{
|
||||
case sc_side:
|
||||
R_CreateInterpolator_SideScroll(&s->thinker, &sides[affectee]);
|
||||
break;
|
||||
case sc_floor:
|
||||
R_CreateInterpolator_SectorScroll(&s->thinker, §ors[affectee], false);
|
||||
break;
|
||||
case sc_ceiling:
|
||||
R_CreateInterpolator_SectorScroll(&s->thinker, §ors[affectee], true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a wall scroller.
|
||||
|
|
|
@ -128,7 +128,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
|
|||
{
|
||||
UINT8 i;
|
||||
|
||||
if (!P_TeleportMove(thing, x, y, z))
|
||||
if (!P_SetOrigin(thing, x, y, z))
|
||||
return false;
|
||||
|
||||
thing->angle = angle;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "k_kart.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
// Object place
|
||||
#include "m_cheat.h"
|
||||
|
@ -610,6 +611,8 @@ void P_Ticker(boolean run)
|
|||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
if (demo.recording)
|
||||
{
|
||||
G_WriteDemoExtraData();
|
||||
|
@ -796,6 +799,11 @@ void P_Ticker(boolean run)
|
|||
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
|
||||
}
|
||||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateLevelInterpolators();
|
||||
}
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
if (demo.playback)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "d_net.h"
|
||||
#include "g_game.h"
|
||||
#include "p_local.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_main.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_things.h"
|
||||
|
@ -1683,6 +1684,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
if (!(mobj->flags & MF_DONTENCOREMAP))
|
||||
mobj->flags &= ~MF_DONTENCOREMAP;
|
||||
|
||||
// Copy interpolation data :)
|
||||
ghost->old_x = mobj->old_x2;
|
||||
ghost->old_y = mobj->old_y2;
|
||||
ghost->old_z = mobj->old_z2;
|
||||
ghost->old_angle = (mobj->player ? mobj->player->old_frameangle2 : mobj->old_angle2);
|
||||
|
||||
return ghost;
|
||||
}
|
||||
|
||||
|
@ -9102,7 +9109,7 @@ void P_PlayerAfterThink(player_t *player)
|
|||
player->mo->momx = (player->mo->tracer->x - player->mo->x)*2;
|
||||
player->mo->momy = (player->mo->tracer->y - player->mo->y)*2;
|
||||
player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2;
|
||||
P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
|
||||
P_MoveOrigin(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
|
||||
player->pflags |= PF_JUMPED;
|
||||
player->secondjump = 0;
|
||||
player->pflags &= ~PF_THOKKED;
|
||||
|
|
20
src/r_bsp.c
20
src/r_bsp.c
|
@ -831,6 +831,7 @@ static void R_Subsector(size_t num)
|
|||
extracolormap_t *floorcolormap;
|
||||
extracolormap_t *ceilingcolormap;
|
||||
fixed_t floorcenterz, ceilingcenterz;
|
||||
ffloor_t *rover;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num >= numsubsectors)
|
||||
|
@ -862,7 +863,23 @@ static void R_Subsector(size_t num)
|
|||
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
|
||||
if (frontsector->ffloors)
|
||||
{
|
||||
if (frontsector->moved)
|
||||
boolean anyMoved = frontsector->moved;
|
||||
|
||||
if (anyMoved == false)
|
||||
{
|
||||
for (rover = frontsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *controlSec = §ors[rover->secnum];
|
||||
|
||||
if (controlSec->moved == true)
|
||||
{
|
||||
anyMoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMoved == true)
|
||||
{
|
||||
frontsector->numlights = sub->sector->numlights = 0;
|
||||
R_Prep3DFloors(frontsector);
|
||||
|
@ -919,7 +936,6 @@ static void R_Subsector(size_t num)
|
|||
ffloor[numffloors].polyobj = NULL;
|
||||
if (frontsector->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t heightcheck, planecenterz;
|
||||
|
||||
for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next)
|
||||
|
|
740
src/r_fps.c
Normal file
740
src/r_fps.c
Normal file
|
@ -0,0 +1,740 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
|
||||
// Copyright (C) 1999-2019 by Sonic Team Junior.
|
||||
//
|
||||
// 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 r_fps.h
|
||||
/// \brief Uncapped framerate stuff.
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
#include "r_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_video.h"
|
||||
#include "r_plane.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_state.h"
|
||||
#include "z_zone.h"
|
||||
#include "console.h" // con_startup_loadprogress
|
||||
|
||||
static CV_PossibleValue_t fpscap_cons_t[] = {
|
||||
#ifdef DEVELOP
|
||||
// Lower values are actually pretty useful for debugging interp problems!
|
||||
{1, "MIN"},
|
||||
#else
|
||||
{TICRATE, "MIN"},
|
||||
#endif
|
||||
{300, "MAX"},
|
||||
{-1, "Unlimited"},
|
||||
{0, "Match refresh rate"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_fpscap = {"fpscap", "300", CV_SAVE, fpscap_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
UINT32 R_GetFramerateCap(void)
|
||||
{
|
||||
if (rendermode == render_none)
|
||||
{
|
||||
// If we're not rendering (dedicated server),
|
||||
// we shouldn't be using any interpolation.
|
||||
return TICRATE;
|
||||
}
|
||||
|
||||
if (cv_fpscap.value == 0)
|
||||
{
|
||||
// 0: Match refresh rate
|
||||
return I_GetRefreshRate();
|
||||
}
|
||||
|
||||
if (cv_fpscap.value < 0)
|
||||
{
|
||||
// -1: Unlimited
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cv_fpscap.value;
|
||||
}
|
||||
|
||||
boolean R_UsingFrameInterpolation(void)
|
||||
{
|
||||
return (R_GetFramerateCap() != TICRATE || cv_timescale.value < FRACUNIT);
|
||||
}
|
||||
|
||||
static viewvars_t pview_old[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t pview_new[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
static viewvars_t *oldview = &pview_old[0];
|
||||
static int oldview_invalid = 0;
|
||||
viewvars_t *newview = &pview_new[0];
|
||||
|
||||
|
||||
enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1;
|
||||
|
||||
static levelinterpolator_t **levelinterpolators;
|
||||
static size_t levelinterpolators_len;
|
||||
static size_t levelinterpolators_size;
|
||||
|
||||
|
||||
static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac)
|
||||
{
|
||||
return from + FixedMul(frac, to - from);
|
||||
}
|
||||
|
||||
static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac)
|
||||
{
|
||||
return from + FixedMul(frac, to - from);
|
||||
}
|
||||
|
||||
static vector2_t *R_LerpVector2(const vector2_t *from, const vector2_t *to, fixed_t frac, vector2_t *out)
|
||||
{
|
||||
FV2_SubEx(to, from, out);
|
||||
FV2_MulEx(out, frac, out);
|
||||
FV2_AddEx(from, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixed_t frac, vector3_t *out)
|
||||
{
|
||||
FV3_SubEx(to, from, out);
|
||||
FV3_MulEx(out, frac, out);
|
||||
FV3_AddEx(from, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(player_t *player, boolean skybox)
|
||||
{
|
||||
(void)player;
|
||||
(void)skybox;
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
}
|
||||
|
||||
centeryfrac = (viewheight/2)<<FRACBITS;
|
||||
|
||||
if (rendermode == render_soft)
|
||||
centeryfrac += FixedMul(AIMINGTODY(aimingangle), FixedDiv(viewwidth<<FRACBITS, BASEVIDWIDTH<<FRACBITS));
|
||||
|
||||
centery = FixedInt(FixedRound(centeryfrac));
|
||||
|
||||
if (rendermode == render_soft)
|
||||
yslope = &yslopetab[viewheight*8 - centery];
|
||||
}
|
||||
|
||||
#undef AIMINGTODY
|
||||
|
||||
void R_InterpolateView(fixed_t frac)
|
||||
{
|
||||
viewvars_t* prevview = oldview;
|
||||
boolean skybox = 0;
|
||||
if (FIXED_TO_FLOAT(frac) < 0)
|
||||
frac = 0;
|
||||
if (frac > FRACUNIT)
|
||||
frac = FRACUNIT;
|
||||
|
||||
if (oldview_invalid != 0)
|
||||
{
|
||||
// interpolate from newview to newview
|
||||
prevview = newview;
|
||||
}
|
||||
|
||||
viewx = R_LerpFixed(prevview->x, newview->x, frac);
|
||||
viewy = R_LerpFixed(prevview->y, newview->y, frac);
|
||||
viewz = R_LerpFixed(prevview->z, newview->z, frac);
|
||||
|
||||
viewangle = R_LerpAngle(prevview->angle, newview->angle, frac);
|
||||
aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac);
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
// this is gonna create some interesting visual errors for long distance teleports...
|
||||
// might want to recalculate the view sector every frame instead...
|
||||
viewplayer = newview->player;
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
|
||||
R_SetupFreelook(newview->player, skybox);
|
||||
}
|
||||
|
||||
void R_UpdateViewInterpolation(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
pview_old[i] = pview_new[i];
|
||||
skyview_old[i] = skyview_new[i];
|
||||
}
|
||||
|
||||
if (oldview_invalid) oldview_invalid--;
|
||||
}
|
||||
|
||||
void R_ResetViewInterpolation(void)
|
||||
{
|
||||
oldview_invalid++;
|
||||
}
|
||||
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
||||
I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1
|
||||
&& _viewcontext <= VIEWCONTEXT_SKY4);
|
||||
viewcontext = _viewcontext;
|
||||
|
||||
switch (viewcontext)
|
||||
{
|
||||
case VIEWCONTEXT_PLAYER1:
|
||||
case VIEWCONTEXT_PLAYER2:
|
||||
case VIEWCONTEXT_PLAYER3:
|
||||
case VIEWCONTEXT_PLAYER4:
|
||||
i = viewcontext - VIEWCONTEXT_PLAYER1;
|
||||
oldview = &pview_old[i];
|
||||
newview = &pview_new[i];
|
||||
break;
|
||||
case VIEWCONTEXT_SKY1:
|
||||
case VIEWCONTEXT_SKY2:
|
||||
case VIEWCONTEXT_SKY3:
|
||||
case VIEWCONTEXT_SKY4:
|
||||
i = viewcontext - VIEWCONTEXT_SKY1;
|
||||
oldview = &skyview_old[i];
|
||||
newview = &skyview_new[i];
|
||||
break;
|
||||
default:
|
||||
I_Error("viewcontext value is invalid: we should never get here without an assert!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
|
||||
{
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
return (R_LerpFixed(from, to, rendertimefrac));
|
||||
}
|
||||
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to)
|
||||
{
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
return (R_LerpAngle(from, to, rendertimefrac));
|
||||
}
|
||||
|
||||
void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
|
||||
{
|
||||
if (frac == FRACUNIT)
|
||||
{
|
||||
out->x = mobj->x;
|
||||
out->y = mobj->y;
|
||||
out->z = mobj->z;
|
||||
out->scale = mobj->scale;
|
||||
out->subsector = mobj->subsector;
|
||||
out->angle = mobj->player ? mobj->player->frameangle : mobj->angle;
|
||||
return;
|
||||
}
|
||||
|
||||
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
|
||||
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
|
||||
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
|
||||
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
|
||||
|
||||
out->subsector = R_PointInSubsector(out->x, out->y);
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
out->angle = mobj->resetinterp ? mobj->player->frameangle : R_LerpAngle(mobj->player->old_frameangle, mobj->player->frameangle, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
out->angle = mobj->resetinterp ? mobj->angle : R_LerpAngle(mobj->old_angle, mobj->angle, frac);
|
||||
}
|
||||
}
|
||||
|
||||
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
|
||||
{
|
||||
if (frac == FRACUNIT)
|
||||
{
|
||||
out->x = mobj->x;
|
||||
out->y = mobj->y;
|
||||
out->z = mobj->z;
|
||||
out->scale = FRACUNIT;
|
||||
out->subsector = mobj->subsector;
|
||||
out->angle = mobj->angle;
|
||||
return;
|
||||
}
|
||||
|
||||
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
|
||||
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
|
||||
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
|
||||
out->scale = FRACUNIT;
|
||||
|
||||
out->subsector = R_PointInSubsector(out->x, out->y);
|
||||
|
||||
out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac);
|
||||
}
|
||||
|
||||
static void AddInterpolator(levelinterpolator_t* interpolator)
|
||||
{
|
||||
if (levelinterpolators_len >= levelinterpolators_size)
|
||||
{
|
||||
if (levelinterpolators_size == 0)
|
||||
{
|
||||
levelinterpolators_size = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelinterpolators_size *= 2;
|
||||
}
|
||||
|
||||
levelinterpolators = Z_ReallocAlign(
|
||||
(void*) levelinterpolators,
|
||||
sizeof(levelinterpolator_t*) * levelinterpolators_size,
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
sizeof(levelinterpolator_t*) * 8
|
||||
);
|
||||
}
|
||||
|
||||
levelinterpolators[levelinterpolators_len] = interpolator;
|
||||
levelinterpolators_len += 1;
|
||||
}
|
||||
|
||||
static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker)
|
||||
{
|
||||
levelinterpolator_t *ret = (levelinterpolator_t*) Z_CallocAlign(
|
||||
sizeof(levelinterpolator_t),
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
sizeof(levelinterpolator_t) * 8
|
||||
);
|
||||
|
||||
ret->type = type;
|
||||
ret->thinker = thinker;
|
||||
|
||||
AddInterpolator(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorPlane, thinker);
|
||||
interp->sectorplane.sector = sector;
|
||||
interp->sectorplane.ceiling = ceiling;
|
||||
if (ceiling)
|
||||
{
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->ceilingheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->floorheight;
|
||||
}
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorScroll, thinker);
|
||||
interp->sectorscroll.sector = sector;
|
||||
interp->sectorscroll.ceiling = ceiling;
|
||||
if (ceiling)
|
||||
{
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->ceiling_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->ceiling_yoffs;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->floor_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->floor_yoffs;
|
||||
}
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SideScroll, thinker);
|
||||
interp->sidescroll.side = side;
|
||||
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset = side->textureoffset;
|
||||
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset = side->rowoffset;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_Polyobj, thinker);
|
||||
interp->polyobj.polyobj = polyobj;
|
||||
interp->polyobj.vertices_size = polyobj->numVertices;
|
||||
|
||||
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
|
||||
for (size_t i = 0; i < polyobj->numVertices; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
|
||||
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1] = polyobj->vertices[i]->y;
|
||||
}
|
||||
|
||||
interp->polyobj.oldcx = interp->polyobj.bakcx = polyobj->centerPt.x;
|
||||
interp->polyobj.oldcy = interp->polyobj.bakcy = polyobj->centerPt.y;
|
||||
}
|
||||
|
||||
void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
|
||||
{
|
||||
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_DynSlope, thinker);
|
||||
interp->dynslope.slope = slope;
|
||||
|
||||
FV3_Copy(&interp->dynslope.oldo, &slope->o);
|
||||
FV3_Copy(&interp->dynslope.bako, &slope->o);
|
||||
|
||||
FV2_Copy(&interp->dynslope.oldd, &slope->d);
|
||||
FV2_Copy(&interp->dynslope.bakd, &slope->d);
|
||||
|
||||
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
|
||||
}
|
||||
|
||||
void R_InitializeLevelInterpolators(void)
|
||||
{
|
||||
levelinterpolators_len = 0;
|
||||
levelinterpolators_size = 0;
|
||||
levelinterpolators = NULL;
|
||||
}
|
||||
|
||||
static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
interp->sectorplane.oldheight = interp->sectorplane.bakheight;
|
||||
interp->sectorplane.bakheight = interp->sectorplane.ceiling ? interp->sectorplane.sector->ceilingheight : interp->sectorplane.sector->floorheight;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floor_xoffs;
|
||||
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs;
|
||||
interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->floor_yoffs;
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset;
|
||||
interp->sidescroll.baktextureoffset = interp->sidescroll.side->textureoffset;
|
||||
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset;
|
||||
interp->sidescroll.bakrowoffset = interp->sidescroll.side->rowoffset;
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (i = 0; i < interp->polyobj.vertices_size; i++)
|
||||
{
|
||||
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ];
|
||||
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1];
|
||||
interp->polyobj.bakvertices[i * 2 ] = interp->polyobj.polyobj->vertices[i]->x;
|
||||
interp->polyobj.bakvertices[i * 2 + 1] = interp->polyobj.polyobj->vertices[i]->y;
|
||||
}
|
||||
interp->polyobj.oldcx = interp->polyobj.bakcx;
|
||||
interp->polyobj.oldcy = interp->polyobj.bakcy;
|
||||
interp->polyobj.bakcx = interp->polyobj.polyobj->centerPt.x;
|
||||
interp->polyobj.bakcy = interp->polyobj.polyobj->centerPt.y;
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
FV3_Copy(&interp->dynslope.oldo, &interp->dynslope.bako);
|
||||
FV2_Copy(&interp->dynslope.oldd, &interp->dynslope.bakd);
|
||||
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta;
|
||||
|
||||
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
|
||||
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
|
||||
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void R_UpdateLevelInterpolators(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
}
|
||||
}
|
||||
|
||||
void R_ClearLevelInterpolatorState(thinker_t *thinker)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
if (interp->thinker == thinker)
|
||||
{
|
||||
// Do it twice to make the old state match the new
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
UpdateLevelInterpolatorState(interp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_ApplyLevelInterpolators(fixed_t frac)
|
||||
{
|
||||
size_t i, ii;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
if (interp->sectorplane.ceiling)
|
||||
{
|
||||
interp->sectorplane.sector->ceilingheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.sector->floorheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
|
||||
}
|
||||
interp->sectorplane.sector->moved = true;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
if (interp->sectorscroll.ceiling)
|
||||
{
|
||||
interp->sectorscroll.sector->ceiling_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
|
||||
interp->sectorscroll.sector->ceiling_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.sector->floor_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
|
||||
interp->sectorscroll.sector->floor_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
|
||||
}
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.side->textureoffset = R_LerpFixed(interp->sidescroll.oldtextureoffset, interp->sidescroll.baktextureoffset, frac);
|
||||
interp->sidescroll.side->rowoffset = R_LerpFixed(interp->sidescroll.oldrowoffset, interp->sidescroll.bakrowoffset, frac);
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
|
||||
{
|
||||
interp->polyobj.polyobj->vertices[ii]->x = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 ], interp->polyobj.bakvertices[ii * 2 ], frac);
|
||||
interp->polyobj.polyobj->vertices[ii]->y = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 + 1], interp->polyobj.bakvertices[ii * 2 + 1], frac);
|
||||
}
|
||||
interp->polyobj.polyobj->centerPt.x = R_LerpFixed(interp->polyobj.oldcx, interp->polyobj.bakcx, frac);
|
||||
interp->polyobj.polyobj->centerPt.y = R_LerpFixed(interp->polyobj.oldcy, interp->polyobj.bakcy, frac);
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
|
||||
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
|
||||
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_RestoreLevelInterpolators(void)
|
||||
{
|
||||
size_t i, ii;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
switch (interp->type)
|
||||
{
|
||||
case LVLINTERP_SectorPlane:
|
||||
if (interp->sectorplane.ceiling)
|
||||
{
|
||||
interp->sectorplane.sector->ceilingheight = interp->sectorplane.bakheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorplane.sector->floorheight = interp->sectorplane.bakheight;
|
||||
}
|
||||
interp->sectorplane.sector->moved = true;
|
||||
break;
|
||||
case LVLINTERP_SectorScroll:
|
||||
if (interp->sectorscroll.ceiling)
|
||||
{
|
||||
interp->sectorscroll.sector->ceiling_xoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.sector->ceiling_yoffs = interp->sectorscroll.bakyoffs;
|
||||
}
|
||||
else
|
||||
{
|
||||
interp->sectorscroll.sector->floor_xoffs = interp->sectorscroll.bakxoffs;
|
||||
interp->sectorscroll.sector->floor_yoffs = interp->sectorscroll.bakyoffs;
|
||||
}
|
||||
break;
|
||||
case LVLINTERP_SideScroll:
|
||||
interp->sidescroll.side->textureoffset = interp->sidescroll.baktextureoffset;
|
||||
interp->sidescroll.side->rowoffset = interp->sidescroll.bakrowoffset;
|
||||
break;
|
||||
case LVLINTERP_Polyobj:
|
||||
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
|
||||
{
|
||||
interp->polyobj.polyobj->vertices[ii]->x = interp->polyobj.bakvertices[ii * 2 ];
|
||||
interp->polyobj.polyobj->vertices[ii]->y = interp->polyobj.bakvertices[ii * 2 + 1];
|
||||
}
|
||||
interp->polyobj.polyobj->centerPt.x = interp->polyobj.bakcx;
|
||||
interp->polyobj.polyobj->centerPt.y = interp->polyobj.bakcy;
|
||||
break;
|
||||
case LVLINTERP_DynSlope:
|
||||
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
|
||||
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
|
||||
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_DestroyLevelInterpolators(thinker_t *thinker)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < levelinterpolators_len; i++)
|
||||
{
|
||||
levelinterpolator_t *interp = levelinterpolators[i];
|
||||
|
||||
if (interp->thinker == thinker)
|
||||
{
|
||||
// Swap the tail of the level interpolators to this spot
|
||||
levelinterpolators[i] = levelinterpolators[levelinterpolators_len - 1];
|
||||
levelinterpolators_len -= 1;
|
||||
|
||||
Z_Free(interp);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mobj_t **interpolated_mobjs = NULL;
|
||||
static size_t interpolated_mobjs_len = 0;
|
||||
static size_t interpolated_mobjs_capacity = 0;
|
||||
|
||||
// NOTE: This will NOT check that the mobj has already been added, for perf
|
||||
// reasons.
|
||||
void R_AddMobjInterpolator(mobj_t *mobj)
|
||||
{
|
||||
if (interpolated_mobjs_len >= interpolated_mobjs_capacity)
|
||||
{
|
||||
if (interpolated_mobjs_capacity == 0)
|
||||
{
|
||||
interpolated_mobjs_capacity = 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
interpolated_mobjs_capacity *= 2;
|
||||
}
|
||||
|
||||
interpolated_mobjs = Z_ReallocAlign(
|
||||
interpolated_mobjs,
|
||||
sizeof(mobj_t *) * interpolated_mobjs_capacity,
|
||||
PU_LEVEL,
|
||||
NULL,
|
||||
64
|
||||
);
|
||||
}
|
||||
|
||||
interpolated_mobjs[interpolated_mobjs_len] = mobj;
|
||||
interpolated_mobjs_len += 1;
|
||||
|
||||
R_ResetMobjInterpolationState(mobj);
|
||||
mobj->resetinterp = true;
|
||||
}
|
||||
|
||||
void R_RemoveMobjInterpolator(mobj_t *mobj)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (interpolated_mobjs_len == 0) return;
|
||||
|
||||
for (i = 0; i < interpolated_mobjs_len - 1; i++)
|
||||
{
|
||||
if (interpolated_mobjs[i] == mobj)
|
||||
{
|
||||
interpolated_mobjs[i] = interpolated_mobjs[
|
||||
interpolated_mobjs_len - 1
|
||||
];
|
||||
interpolated_mobjs_len -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_InitMobjInterpolators(void)
|
||||
{
|
||||
// apparently it's not acceptable to free something already unallocated
|
||||
// Z_Free(interpolated_mobjs);
|
||||
interpolated_mobjs = NULL;
|
||||
interpolated_mobjs_len = 0;
|
||||
interpolated_mobjs_capacity = 0;
|
||||
}
|
||||
|
||||
void R_UpdateMobjInterpolators(void)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < interpolated_mobjs_len; i++)
|
||||
{
|
||||
mobj_t *mobj = interpolated_mobjs[i];
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
R_ResetMobjInterpolationState(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_ResetMobjInterpolationState
|
||||
//
|
||||
// Reset the rendering interpolation state of the mobj.
|
||||
//
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj)
|
||||
{
|
||||
mobj->old_x2 = mobj->old_x;
|
||||
mobj->old_y2 = mobj->old_y;
|
||||
mobj->old_z2 = mobj->old_z;
|
||||
mobj->old_angle2 = mobj->old_angle;
|
||||
mobj->old_scale2 = mobj->old_scale;
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_scale = mobj->scale;
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->player->old_frameangle2 = mobj->player->old_frameangle;
|
||||
mobj->player->old_frameangle = mobj->player->frameangle;
|
||||
}
|
||||
|
||||
mobj->resetinterp = false;
|
||||
}
|
||||
|
||||
//
|
||||
// P_ResetPrecipitationMobjInterpolationState
|
||||
//
|
||||
// Reset the rendering interpolation state of the precipmobj.
|
||||
//
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj)
|
||||
{
|
||||
mobj->old_x2 = mobj->old_x;
|
||||
mobj->old_y2 = mobj->old_y;
|
||||
mobj->old_z2 = mobj->old_z;
|
||||
mobj->old_angle2 = mobj->old_angle;
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
}
|
158
src/r_fps.h
Normal file
158
src/r_fps.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
|
||||
// Copyright (C) 1999-2019 by Sonic Team Junior.
|
||||
//
|
||||
// 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 r_fps.h
|
||||
/// \brief Uncapped framerate stuff.
|
||||
|
||||
#ifndef __R_FPS_H__
|
||||
#define __R_FPS_H__
|
||||
|
||||
#include "m_fixed.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
|
||||
extern consvar_t cv_fpscap;
|
||||
|
||||
UINT32 R_GetFramerateCap(void);
|
||||
boolean R_UsingFrameInterpolation(void);
|
||||
|
||||
enum viewcontext_e
|
||||
{
|
||||
VIEWCONTEXT_PLAYER1 = 0,
|
||||
VIEWCONTEXT_PLAYER2,
|
||||
VIEWCONTEXT_PLAYER3,
|
||||
VIEWCONTEXT_PLAYER4,
|
||||
VIEWCONTEXT_SKY1,
|
||||
VIEWCONTEXT_SKY2,
|
||||
VIEWCONTEXT_SKY3,
|
||||
VIEWCONTEXT_SKY4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
boolean sky;
|
||||
sector_t *sector;
|
||||
player_t *player;
|
||||
|
||||
angle_t angle;
|
||||
angle_t aim;
|
||||
fixed_t cos;
|
||||
fixed_t sin;
|
||||
mobj_t *mobj;
|
||||
} viewvars_t;
|
||||
|
||||
extern viewvars_t *newview;
|
||||
|
||||
typedef struct {
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
subsector_t *subsector;
|
||||
angle_t angle;
|
||||
fixed_t scale;
|
||||
} interpmobjstate_t;
|
||||
|
||||
// Level interpolators
|
||||
|
||||
// The union tag for levelinterpolator_t
|
||||
typedef enum {
|
||||
LVLINTERP_SectorPlane,
|
||||
LVLINTERP_SectorScroll,
|
||||
LVLINTERP_SideScroll,
|
||||
LVLINTERP_Polyobj,
|
||||
LVLINTERP_DynSlope,
|
||||
} levelinterpolator_type_e;
|
||||
|
||||
// Tagged union of a level interpolator
|
||||
typedef struct levelinterpolator_s {
|
||||
levelinterpolator_type_e type;
|
||||
thinker_t *thinker;
|
||||
union {
|
||||
struct {
|
||||
sector_t *sector;
|
||||
fixed_t oldheight;
|
||||
fixed_t bakheight;
|
||||
boolean ceiling;
|
||||
} sectorplane;
|
||||
struct {
|
||||
sector_t *sector;
|
||||
fixed_t oldxoffs, oldyoffs, bakxoffs, bakyoffs;
|
||||
boolean ceiling;
|
||||
} sectorscroll;
|
||||
struct {
|
||||
side_t *side;
|
||||
fixed_t oldtextureoffset, oldrowoffset, baktextureoffset, bakrowoffset;
|
||||
} sidescroll;
|
||||
struct {
|
||||
polyobj_t *polyobj;
|
||||
fixed_t *oldvertices;
|
||||
fixed_t *bakvertices;
|
||||
size_t vertices_size;
|
||||
fixed_t oldcx, oldcy, bakcx, bakcy;
|
||||
} polyobj;
|
||||
struct {
|
||||
pslope_t *slope;
|
||||
vector3_t oldo, bako;
|
||||
vector2_t oldd, bakd;
|
||||
fixed_t oldzdelta, bakzdelta;
|
||||
} dynslope;
|
||||
};
|
||||
} levelinterpolator_t;
|
||||
|
||||
// Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext
|
||||
void R_InterpolateView(fixed_t frac);
|
||||
// Buffer the current new views into the old views. Call once after each real tic.
|
||||
void R_UpdateViewInterpolation(void);
|
||||
// Reset the view states (e.g. after level load) so R_InterpolateView doesn't interpolate invalid data
|
||||
void R_ResetViewInterpolation(void);
|
||||
// Set the current view context (the viewvars pointed to by newview)
|
||||
void R_SetViewContext(enum viewcontext_e _viewcontext);
|
||||
|
||||
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to);
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to);
|
||||
|
||||
// Evaluate the interpolated mobj state for the given mobj
|
||||
void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
|
||||
// Evaluate the interpolated mobj state for the given precipmobj
|
||||
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
|
||||
|
||||
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling);
|
||||
void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling);
|
||||
void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side);
|
||||
void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj);
|
||||
void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope);
|
||||
|
||||
// Initialize level interpolators after a level change
|
||||
void R_InitializeLevelInterpolators(void);
|
||||
// Update level interpolators, storing the previous and current states.
|
||||
void R_UpdateLevelInterpolators(void);
|
||||
// Clear states for all level interpolators for the thinker
|
||||
void R_ClearLevelInterpolatorState(thinker_t *thinker);
|
||||
// Apply level interpolators to the actual game state
|
||||
void R_ApplyLevelInterpolators(fixed_t frac);
|
||||
// Restore level interpolators to the real game state
|
||||
void R_RestoreLevelInterpolators(void);
|
||||
// Destroy interpolators associated with a thinker
|
||||
void R_DestroyLevelInterpolators(thinker_t *thinker);
|
||||
|
||||
// Initialize internal mobj interpolator list (e.g. during level loading)
|
||||
void R_InitMobjInterpolators(void);
|
||||
// Add interpolation state for the given mobj
|
||||
void R_AddMobjInterpolator(mobj_t *mobj);
|
||||
// Remove the interpolation state for the given mobj
|
||||
void R_RemoveMobjInterpolator(mobj_t *mobj);
|
||||
void R_UpdateMobjInterpolators(void);
|
||||
void R_ResetMobjInterpolationState(mobj_t *mobj);
|
||||
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);
|
||||
|
||||
#endif
|
258
src/r_main.c
258
src/r_main.c
|
@ -31,6 +31,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_random.h" // quake camera shake
|
||||
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
|
||||
#include "r_fps.h" // Frame interpolation/uncapped
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
@ -99,6 +100,10 @@ portal_pair *portal_base, *portal_cap;
|
|||
line_t *portalclipline;
|
||||
INT32 portalclipstart, portalclipend;
|
||||
|
||||
fixed_t rendertimefrac;
|
||||
fixed_t renderdeltatics;
|
||||
boolean renderisnewtic;
|
||||
|
||||
//
|
||||
// precalculated math tables
|
||||
//
|
||||
|
@ -793,31 +798,6 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
|
|||
|
||||
static mobj_t *viewmobj;
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
static void R_SetupFreelook(void)
|
||||
{
|
||||
INT32 dy = 0;
|
||||
|
||||
// clip it in the case we are looking a hardware 90 degrees full aiming
|
||||
// (lmps, network and use F12...)
|
||||
if (rendermode == render_soft
|
||||
#ifdef HWRENDER
|
||||
|| cv_grshearing.value
|
||||
#endif
|
||||
)
|
||||
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
|
||||
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
dy = (AIMINGTODY(aimingangle)/fovtan) * viewwidth/BASEVIDWIDTH;
|
||||
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
|
||||
}
|
||||
centery = (viewheight/2) + dy;
|
||||
centeryfrac = centery<<FRACBITS;
|
||||
}
|
||||
|
||||
void R_SkyboxFrame(player_t *player)
|
||||
{
|
||||
camera_t *thiscam = &camera[0];
|
||||
|
@ -830,13 +810,18 @@ void R_SkyboxFrame(player_t *player)
|
|||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
thiscam = &camera[i];
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_SetViewContext(VIEWCONTEXT_SKY1);
|
||||
}
|
||||
|
||||
// cut-away view stuff
|
||||
viewsky = true;
|
||||
newview->sky = true;
|
||||
viewmobj = skyboxmo[0];
|
||||
#ifdef PARANOIA
|
||||
if (!viewmobj)
|
||||
|
@ -847,24 +832,24 @@ void R_SkyboxFrame(player_t *player)
|
|||
#endif
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = player->awayviewmobj->angle;
|
||||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = player->awayviewmobj->angle;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
aimingangle = player->aiming;
|
||||
viewangle = player->mo->angle;
|
||||
newview->aim = player->aiming;
|
||||
newview->angle = player->mo->angle;
|
||||
if (/*!demo.playback && */player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle[0]; // WARNING: camera uses this
|
||||
aimingangle = localaiming[0];
|
||||
newview->angle = localangle[0]; // WARNING: camera uses this
|
||||
newview->aim = localaiming[0];
|
||||
}
|
||||
else if (splitscreen)
|
||||
{
|
||||
|
@ -872,27 +857,27 @@ void R_SkyboxFrame(player_t *player)
|
|||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
viewangle = localangle[i];
|
||||
aimingangle = localaiming[i];
|
||||
newview->angle = localangle[i];
|
||||
newview->aim = localaiming[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewangle += viewmobj->angle;
|
||||
newview->angle += viewmobj->angle;
|
||||
|
||||
viewplayer = player;
|
||||
newview->player = player;
|
||||
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewz = 0;
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->z = 0;
|
||||
if (viewmobj->spawnpoint)
|
||||
viewz = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
|
||||
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
viewz += quake.z;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
newview->z += quake.z;
|
||||
|
||||
if (mapheaderinfo[gamemap-1])
|
||||
{
|
||||
|
@ -914,35 +899,35 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
|
||||
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
|
||||
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
|
||||
}
|
||||
else if (thiscam->chase)
|
||||
{
|
||||
|
@ -961,35 +946,35 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
|
||||
newview->z += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
|
||||
newview->z += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1007,47 +992,47 @@ void R_SkyboxFrame(player_t *player)
|
|||
|
||||
if (viewmobj->angle == 0)
|
||||
{
|
||||
viewx += x;
|
||||
viewy += y;
|
||||
newview->x += x;
|
||||
newview->y += y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_90)
|
||||
{
|
||||
viewx -= y;
|
||||
viewy += x;
|
||||
newview->x -= y;
|
||||
newview->y += x;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_180)
|
||||
{
|
||||
viewx -= x;
|
||||
viewy -= y;
|
||||
newview->x -= x;
|
||||
newview->y -= y;
|
||||
}
|
||||
else if (viewmobj->angle == ANGLE_270)
|
||||
{
|
||||
viewx += y;
|
||||
viewy -= x;
|
||||
newview->x += y;
|
||||
newview->y -= x;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
|
||||
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
|
||||
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
|
||||
}
|
||||
}
|
||||
if (mh->skybox_scalez > 0)
|
||||
viewz += player->viewz / mh->skybox_scalez;
|
||||
newview->z += player->viewz / mh->skybox_scalez;
|
||||
else if (mh->skybox_scalez < 0)
|
||||
viewz += player->viewz * -mh->skybox_scalez;
|
||||
newview->z += player->viewz * -mh->skybox_scalez;
|
||||
}
|
||||
}
|
||||
|
||||
if (viewmobj->subsector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
newview->sector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_SetupFreelook();
|
||||
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
}
|
||||
|
||||
void R_SetupFrame(player_t *player, boolean skybox)
|
||||
|
@ -1059,21 +1044,25 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
{
|
||||
thiscam = &camera[3];
|
||||
chasecam = (cv_chasecam4.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER4);
|
||||
}
|
||||
else if (splitscreen > 1 && player == &players[displayplayers[2]])
|
||||
{
|
||||
thiscam = &camera[2];
|
||||
chasecam = (cv_chasecam3.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER3);
|
||||
}
|
||||
else if (splitscreen && player == &players[displayplayers[1]])
|
||||
{
|
||||
thiscam = &camera[1];
|
||||
chasecam = (cv_chasecam2.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER2);
|
||||
}
|
||||
else
|
||||
{
|
||||
thiscam = &camera[0];
|
||||
chasecam = (cv_chasecam.value != 0);
|
||||
R_SetViewContext(VIEWCONTEXT_PLAYER1);
|
||||
}
|
||||
|
||||
if (player->spectator) // no spectator chasecam
|
||||
|
@ -1089,41 +1078,41 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
else if (!chasecam)
|
||||
thiscam->chase = false;
|
||||
|
||||
viewsky = !skybox;
|
||||
newview->sky = !skybox;
|
||||
if (player->awayviewtics)
|
||||
{
|
||||
// cut-away view stuff
|
||||
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
|
||||
I_Assert(viewmobj != NULL);
|
||||
viewz = viewmobj->z + 20*FRACUNIT;
|
||||
aimingangle = player->awayviewaiming;
|
||||
viewangle = viewmobj->angle;
|
||||
newview->z = viewmobj->z + 20*FRACUNIT;
|
||||
newview->aim = player->awayviewaiming;
|
||||
newview->angle = viewmobj->angle;
|
||||
}
|
||||
else if (!player->spectator && chasecam)
|
||||
// use outside cam view
|
||||
{
|
||||
viewmobj = NULL;
|
||||
viewz = thiscam->z + (thiscam->height>>1);
|
||||
aimingangle = thiscam->aiming;
|
||||
viewangle = thiscam->angle;
|
||||
newview->z = thiscam->z + (thiscam->height>>1);
|
||||
newview->aim = thiscam->aiming;
|
||||
newview->angle = thiscam->angle;
|
||||
}
|
||||
else
|
||||
// use the player's eyes view
|
||||
{
|
||||
viewz = player->viewz;
|
||||
newview->z = player->viewz;
|
||||
|
||||
viewmobj = player->mo;
|
||||
I_Assert(viewmobj != NULL);
|
||||
|
||||
aimingangle = player->aiming;
|
||||
viewangle = viewmobj->angle;
|
||||
newview->aim = player->aiming;
|
||||
newview->angle = viewmobj->angle;
|
||||
|
||||
if (!demo.playback && player->playerstate != PST_DEAD)
|
||||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
viewangle = localangle[0]; // WARNING: camera uses this
|
||||
aimingangle = localaiming[0];
|
||||
newview->angle = localangle[0]; // WARNING: camera uses this
|
||||
newview->aim = localaiming[0];
|
||||
}
|
||||
else if (splitscreen)
|
||||
{
|
||||
|
@ -1132,47 +1121,47 @@ void R_SetupFrame(player_t *player, boolean skybox)
|
|||
{
|
||||
if (player == &players[displayplayers[i]])
|
||||
{
|
||||
viewangle = localangle[i];
|
||||
aimingangle = localaiming[i];
|
||||
newview->angle = localangle[i];
|
||||
newview->aim = localaiming[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewz += quake.z;
|
||||
newview->z += quake.z;
|
||||
|
||||
viewplayer = player;
|
||||
newview->player = player;
|
||||
|
||||
if (chasecam && !player->awayviewtics && !player->spectator)
|
||||
{
|
||||
viewx = thiscam->x;
|
||||
viewy = thiscam->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
newview->x = thiscam->x;
|
||||
newview->y = thiscam->y;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
|
||||
if (thiscam->subsector && thiscam->subsector->sector)
|
||||
viewsector = thiscam->subsector->sector;
|
||||
newview->sector = thiscam->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewx = viewmobj->x;
|
||||
viewy = viewmobj->y;
|
||||
viewx += quake.x;
|
||||
viewy += quake.y;
|
||||
newview->x = viewmobj->x;
|
||||
newview->y = viewmobj->y;
|
||||
newview->x += quake.x;
|
||||
newview->y += quake.y;
|
||||
|
||||
if (viewmobj->subsector && thiscam->subsector->sector)
|
||||
viewsector = viewmobj->subsector->sector;
|
||||
newview->sector = viewmobj->subsector->sector;
|
||||
else
|
||||
viewsector = R_PointInSubsector(viewx, viewy)->sector;
|
||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||
}
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
||||
R_SetupFreelook();
|
||||
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
}
|
||||
|
||||
#define ANGLED_PORTALS
|
||||
|
@ -1186,13 +1175,13 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
#endif
|
||||
|
||||
//R_SetupFrame(player, false);
|
||||
viewx = portal->viewx;
|
||||
viewy = portal->viewy;
|
||||
viewz = portal->viewz;
|
||||
newview->x = portal->viewx;
|
||||
newview->y = portal->viewy;
|
||||
newview->z = portal->viewz;
|
||||
|
||||
viewangle = portal->viewangle;
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
newview->angle = portal->viewangle;
|
||||
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
|
||||
portalcullsector = dest->frontsector;
|
||||
viewsector = dest->frontsector;
|
||||
|
@ -1211,22 +1200,22 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
|
||||
|
||||
// Heights!
|
||||
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
newview->z += dest->frontsector->floorheight - start->frontsector->floorheight;
|
||||
|
||||
// calculate the difference in position and rotation!
|
||||
#ifdef ANGLED_PORTALS
|
||||
if (dangle == 0)
|
||||
#endif
|
||||
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
|
||||
viewx += dest_c.x - start_c.x;
|
||||
viewy += dest_c.y - start_c.y;
|
||||
newview->x += dest_c.x - start_c.x;
|
||||
newview->y += dest_c.y - start_c.y;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ANGLED_PORTALS
|
||||
viewangle += dangle;
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
newview->angle += dangle;
|
||||
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
|
||||
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
|
||||
|
||||
// ????
|
||||
|
@ -1234,12 +1223,12 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
|
|||
fixed_t disttopoint;
|
||||
angle_t angtopoint;
|
||||
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
|
||||
disttopoint = R_PointToDist2(start_c.x, start_c.y, newview->x, newview->y);
|
||||
angtopoint = R_PointToAngle2(start_c.x, start_c.y, newview->x, newview->y);
|
||||
angtopoint += dangle;
|
||||
|
||||
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
newview->x = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
newview->y = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1544,4 +1533,7 @@ void R_RegisterEngineStuff(void)
|
|||
if (rendermode != render_soft && rendermode != render_none)
|
||||
HWR_AddCommands();
|
||||
#endif
|
||||
|
||||
// Frame interpolation/uncapped
|
||||
CV_RegisterVar(&cv_fpscap);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,13 @@ extern fixed_t projection, projectiony;
|
|||
|
||||
extern size_t validcount, linecount, loopcount, framecount;
|
||||
|
||||
// The fraction of a tic being drawn (for interpolation between two tics)
|
||||
extern fixed_t rendertimefrac;
|
||||
// Evaluated delta tics for this frame (how many tics since the last frame)
|
||||
extern fixed_t renderdeltatics;
|
||||
// The current render is a new logical tic
|
||||
extern boolean renderisnewtic;
|
||||
|
||||
//
|
||||
// Lighting LUT.
|
||||
// Used for z-depth cuing per column/row,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "z_zone.h"
|
||||
#include "m_misc.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_plane.h"
|
||||
#include "p_tick.h"
|
||||
|
@ -1158,13 +1159,28 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t gz, gzt;
|
||||
INT32 heightsec, phs;
|
||||
INT32 light = 0;
|
||||
fixed_t this_scale = thing->scale;
|
||||
fixed_t this_scale;
|
||||
|
||||
fixed_t ang_scale = FRACUNIT;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = interp.scale;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thing->x - viewx;
|
||||
tr_y = thing->y - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
gxt = FixedMul(tr_x, viewcos);
|
||||
gyt = -FixedMul(tr_y, viewsin);
|
||||
|
@ -1229,10 +1245,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (sprframe->rotate != SRF_SINGLE || papersprite)
|
||||
{
|
||||
if (thing->player)
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
|
||||
else
|
||||
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
if (papersprite)
|
||||
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
|
||||
}
|
||||
|
@ -1247,7 +1260,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
else
|
||||
{
|
||||
// choose a different rotation based on player view
|
||||
//ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
|
||||
//ang = R_PointToAngle (interp.x, interp.y) - interpangle;
|
||||
|
||||
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
|
||||
rot = 6; // F7 slot
|
||||
|
@ -1300,8 +1313,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
offset2 *= -1;
|
||||
}
|
||||
|
||||
cosmul = FINECOSINE(thing->angle>>ANGLETOFINESHIFT);
|
||||
sinmul = FINESINE(thing->angle>>ANGLETOFINESHIFT);
|
||||
cosmul = FINECOSINE(interp.angle >> ANGLETOFINESHIFT);
|
||||
sinmul = FINESINE(interp.angle >> ANGLETOFINESHIFT);
|
||||
|
||||
tr_x += FixedMul(offset, cosmul);
|
||||
tr_y += FixedMul(offset, sinmul);
|
||||
|
@ -1343,7 +1356,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1353,12 +1366,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
// When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned.
|
||||
// sprite height - sprite topoffset is the proper inverse of the vertical offset, of course.
|
||||
// remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes!
|
||||
gz = thing->z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gz = interp.z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gzt = gz + FixedMul(spritecachedinfo[lump].height, this_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = thing->z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gzt = interp.z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale);
|
||||
}
|
||||
|
||||
|
@ -1374,7 +1387,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
light = thing->subsector->sector->numlights - 1;
|
||||
|
||||
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
|
||||
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, interp.x, interp.y)
|
||||
: thing->subsector->sector->lightlist[lightnum].height;
|
||||
if (h <= gzt) {
|
||||
light = lightnum - 1;
|
||||
|
@ -1416,12 +1429,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->scale = yscale; //<<detailshift;
|
||||
vis->sortscale = sortscale;
|
||||
vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
|
||||
vis->gx = thing->x;
|
||||
vis->gy = thing->y;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = thing->height;
|
||||
vis->pz = thing->z;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = scalestep;
|
||||
|
@ -1539,9 +1552,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
//SoM: 3/17/2000
|
||||
fixed_t gz ,gzt;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thing->x - viewx;
|
||||
tr_y = thing->y - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
gxt = FixedMul(tr_x, viewcos);
|
||||
gyt = -FixedMul(tr_y, viewsin);
|
||||
|
@ -1610,7 +1636,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 > portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1626,7 +1652,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
|
||||
|
||||
//SoM: 3/17/2000: Disregard sprites that are out of view..
|
||||
gzt = thing->z + spritecachedinfo[lump].topoffset;
|
||||
gzt = interp.z + spritecachedinfo[lump].topoffset;
|
||||
gz = gzt - spritecachedinfo[lump].height;
|
||||
|
||||
if (thing->subsector->sector->cullheight)
|
||||
|
@ -1639,12 +1665,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis = R_NewVisSprite();
|
||||
vis->scale = vis->sortscale = yscale; //<<detailshift;
|
||||
vis->dispoffset = 0; // Monster Iestyn: 23/11/15
|
||||
vis->gx = thing->x;
|
||||
vis->gy = thing->y;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = 4*FRACUNIT;
|
||||
vis->pz = thing->z;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = 0;
|
||||
|
|
119
src/screen.c
119
src/screen.c
|
@ -15,6 +15,7 @@
|
|||
#include "screen.h"
|
||||
#include "console.h"
|
||||
#include "am_map.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "r_local.h"
|
||||
|
@ -29,6 +30,8 @@
|
|||
#include "d_clisrv.h"
|
||||
#include "f_finale.h"
|
||||
|
||||
// SRB2Kart
|
||||
#include "r_fps.h" // R_GetFramerateCap
|
||||
|
||||
#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
|
||||
#define RUSEASM //MSC.NET can't patch itself
|
||||
|
@ -397,46 +400,96 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
|
|||
);
|
||||
}
|
||||
|
||||
// XMOD FPS display
|
||||
// moved out of os-specific code for consistency
|
||||
static boolean fpsgraph[TICRATE];
|
||||
static tic_t lasttic;
|
||||
double averageFPS = 0.0f;
|
||||
|
||||
#define FPS_SAMPLE_RATE (50000) // How often to update FPS samples, in microseconds
|
||||
#define NUM_FPS_SAMPLES 16 // Number of samples to store
|
||||
|
||||
static double fps_samples[NUM_FPS_SAMPLES];
|
||||
|
||||
void SCR_CalculateFPS(void)
|
||||
{
|
||||
static boolean init = false;
|
||||
|
||||
static precise_t startTime = 0;
|
||||
precise_t endTime = 0;
|
||||
|
||||
static precise_t updateTime = 0;
|
||||
int updateElapsed = 0;
|
||||
int i;
|
||||
|
||||
endTime = I_GetPreciseTime();
|
||||
|
||||
if (init == false)
|
||||
{
|
||||
startTime = updateTime = endTime;
|
||||
init = true;
|
||||
return;
|
||||
}
|
||||
|
||||
updateElapsed = (endTime - updateTime) / (I_GetPrecisePrecision() / 1000000);
|
||||
|
||||
if (updateElapsed >= FPS_SAMPLE_RATE)
|
||||
{
|
||||
static int sampleIndex = 0;
|
||||
int frameElapsed = (endTime - startTime) / (I_GetPrecisePrecision() / 1000000);
|
||||
|
||||
fps_samples[sampleIndex] = frameElapsed / 1000.0f;
|
||||
|
||||
sampleIndex++;
|
||||
if (sampleIndex >= NUM_FPS_SAMPLES)
|
||||
sampleIndex = 0;
|
||||
|
||||
averageFPS = 0.0f;
|
||||
for (i = 0; i < NUM_FPS_SAMPLES; i++)
|
||||
{
|
||||
averageFPS += fps_samples[i];
|
||||
}
|
||||
averageFPS = 1000.0f / (averageFPS / NUM_FPS_SAMPLES);
|
||||
|
||||
updateTime = endTime;
|
||||
}
|
||||
|
||||
startTime = endTime;
|
||||
}
|
||||
|
||||
void SCR_DisplayTicRate(void)
|
||||
{
|
||||
tic_t i;
|
||||
tic_t ontic = I_GetTime();
|
||||
tic_t totaltics = 0;
|
||||
const UINT8 *ticcntcolor = NULL;
|
||||
|
||||
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
|
||||
fpsgraph[i % TICRATE] = false;
|
||||
|
||||
fpsgraph[ontic % TICRATE] = true;
|
||||
|
||||
for (i = 0;i < TICRATE;++i)
|
||||
if (fpsgraph[i])
|
||||
++totaltics;
|
||||
|
||||
if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SALMON, GTC_CACHE);
|
||||
else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
|
||||
/*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy),
|
||||
V_YELLOWMAP|V_NOSCALESTART, "FPS");
|
||||
V_DrawString(vid.width-(40*vid.dupx), vid.height-( 8*vid.dupy),
|
||||
ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/
|
||||
UINT32 cap = R_GetFramerateCap();
|
||||
UINT32 benchmark = (cap == 0) ? I_GetRefreshRate() : cap;
|
||||
INT32 x = 318;
|
||||
double fps = ceil(averageFPS);
|
||||
|
||||
// draw "FPS"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
// draw total frame:
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, TICRATE, ticcntcolor);
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, frameslash, ticcntcolor);
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
|
||||
if (fps > (benchmark - 5))
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
else if (fps < 20)
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
|
||||
if (cap != 0)
|
||||
{
|
||||
UINT32 digits = 1;
|
||||
UINT32 c2 = cap;
|
||||
|
||||
while (c2 > 0)
|
||||
{
|
||||
c2 = c2 / 10;
|
||||
digits++;
|
||||
}
|
||||
|
||||
// draw total frame:
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cap, ticcntcolor);
|
||||
x -= digits * 4;
|
||||
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(x<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
}
|
||||
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, totaltics, ticcntcolor);
|
||||
|
||||
|
||||
lasttic = ontic;
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, fps, ticcntcolor);
|
||||
}
|
||||
|
||||
// SCR_DisplayLocalPing
|
||||
|
|
|
@ -154,6 +154,7 @@ extern boolean R_SSE2;
|
|||
// ----------------
|
||||
extern viddef_t vid;
|
||||
extern INT32 setmodeneeded; // mode number to set if needed, or 0
|
||||
extern double averageFPS;
|
||||
|
||||
extern INT32 scr_bpp;
|
||||
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
||||
|
@ -161,6 +162,7 @@ extern UINT8 *scr_borderpatch; // patch used to fill the view borders
|
|||
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen;
|
||||
// wait for page flipping to end or not
|
||||
extern consvar_t cv_vidwait;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
// quick fix for tall/short skies, depending on bytesperpixel
|
||||
extern void (*walldrawerfunc)(void);
|
||||
|
@ -176,6 +178,8 @@ void SCR_SetDefaultMode (void);
|
|||
|
||||
void SCR_Startup (void);
|
||||
|
||||
void SCR_CalculateFPS(void);
|
||||
|
||||
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
|
||||
|
||||
// move out to main code for consistency
|
||||
|
|
|
@ -160,6 +160,7 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../doomdef.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -175,6 +176,9 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../m_argv.h"
|
||||
|
||||
#include "../r_main.h" // Frame interpolation/uncapped
|
||||
#include "../r_fps.h"
|
||||
|
||||
#ifdef MAC_ALERT
|
||||
#include "macosx/mac_alert.h"
|
||||
#endif
|
||||
|
@ -2927,122 +2931,80 @@ ticcmd_t *I_BaseTiccmd4(void)
|
|||
return &emptycmd4;
|
||||
}
|
||||
|
||||
#if defined (_WIN32)
|
||||
static HMODULE winmm = NULL;
|
||||
static DWORD starttickcount = 0; // hack for win2k time bug
|
||||
static p_timeGetTime pfntimeGetTime = NULL;
|
||||
static Uint64 timer_frequency;
|
||||
|
||||
// ---------
|
||||
// I_GetTime
|
||||
// Use the High Resolution Timer if available,
|
||||
// else use the multimedia timer which has 1 millisecond precision on Windowz 95,
|
||||
// but lower precision on Windows NT
|
||||
// ---------
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
tic_t newtics = 0;
|
||||
return SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
if (!starttickcount) // high precision timer
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
return SDL_GetPerformanceFrequency();
|
||||
}
|
||||
|
||||
static UINT32 frame_rate;
|
||||
|
||||
static double frame_frequency;
|
||||
static UINT64 frame_epoch;
|
||||
static double elapsed_frames;
|
||||
|
||||
static void I_InitFrameTime(const UINT64 now, const UINT32 cap)
|
||||
{
|
||||
frame_rate = cap;
|
||||
frame_epoch = now;
|
||||
|
||||
//elapsed_frames = 0.0;
|
||||
|
||||
if (frame_rate == 0)
|
||||
{
|
||||
LARGE_INTEGER currtime; // use only LowPart if high resolution counter is not available
|
||||
static LARGE_INTEGER basetime = {{0, 0}};
|
||||
// Shouldn't be used, but just in case...?
|
||||
frame_frequency = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// use this if High Resolution timer is found
|
||||
static LARGE_INTEGER frequency;
|
||||
frame_frequency = timer_frequency / (double)frame_rate;
|
||||
}
|
||||
|
||||
if (!basetime.LowPart)
|
||||
{
|
||||
if (!QueryPerformanceFrequency(&frequency))
|
||||
frequency.QuadPart = 0;
|
||||
else
|
||||
QueryPerformanceCounter(&basetime);
|
||||
}
|
||||
double I_GetFrameTime(void)
|
||||
{
|
||||
const UINT64 now = SDL_GetPerformanceCounter();
|
||||
const UINT32 cap = R_GetFramerateCap();
|
||||
|
||||
if (frequency.LowPart && QueryPerformanceCounter(&currtime))
|
||||
{
|
||||
newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE
|
||||
/ frequency.QuadPart);
|
||||
}
|
||||
else if (pfntimeGetTime)
|
||||
{
|
||||
currtime.LowPart = pfntimeGetTime();
|
||||
if (!basetime.LowPart)
|
||||
basetime.LowPart = currtime.LowPart;
|
||||
newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE));
|
||||
}
|
||||
if (cap != frame_rate)
|
||||
{
|
||||
// Maybe do this in a OnChange function for cv_fpscap?
|
||||
I_InitFrameTime(now, cap);
|
||||
}
|
||||
|
||||
if (frame_rate == 0)
|
||||
{
|
||||
// Always advance a frame.
|
||||
elapsed_frames += 1.0;
|
||||
}
|
||||
else
|
||||
newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE);
|
||||
|
||||
return newtics;
|
||||
}
|
||||
|
||||
static void I_ShutdownTimer(void)
|
||||
{
|
||||
pfntimeGetTime = NULL;
|
||||
if (winmm)
|
||||
{
|
||||
p_timeEndPeriod pfntimeEndPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeEndPeriod");
|
||||
if (pfntimeEndPeriod)
|
||||
pfntimeEndPeriod(1);
|
||||
FreeLibrary(winmm);
|
||||
winmm = NULL;
|
||||
elapsed_frames += (now - frame_epoch) / frame_frequency;
|
||||
}
|
||||
|
||||
frame_epoch = now; // moving epoch
|
||||
return elapsed_frames;
|
||||
}
|
||||
#else
|
||||
//
|
||||
// I_GetTime
|
||||
// returns time in 1/TICRATE second tics
|
||||
//
|
||||
tic_t I_GetTime (void)
|
||||
{
|
||||
static Uint64 basetime = 0;
|
||||
Uint64 ticks = SDL_GetTicks();
|
||||
|
||||
if (!basetime)
|
||||
basetime = ticks;
|
||||
|
||||
ticks -= basetime;
|
||||
|
||||
ticks = (ticks*TICRATE);
|
||||
|
||||
ticks = (ticks/1000);
|
||||
|
||||
return (tic_t)ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
//I_StartupTimer
|
||||
// I_StartupTimer
|
||||
//
|
||||
void I_StartupTimer(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// for win2k time bug
|
||||
if (M_CheckParm("-gettickcount"))
|
||||
{
|
||||
starttickcount = GetTickCount();
|
||||
CONS_Printf("%s", M_GetText("Using GetTickCount()\n"));
|
||||
}
|
||||
winmm = LoadLibraryA("winmm.dll");
|
||||
if (winmm)
|
||||
{
|
||||
p_timeEndPeriod pfntimeBeginPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeBeginPeriod");
|
||||
if (pfntimeBeginPeriod)
|
||||
pfntimeBeginPeriod(1);
|
||||
pfntimeGetTime = (p_timeGetTime)(LPVOID)GetProcAddress(winmm, "timeGetTime");
|
||||
}
|
||||
I_AddExitFunc(I_ShutdownTimer);
|
||||
#endif
|
||||
timer_frequency = SDL_GetPerformanceFrequency();
|
||||
|
||||
I_InitFrameTime(0, R_GetFramerateCap());
|
||||
elapsed_frames = 0.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void I_Sleep(void)
|
||||
void I_Sleep(UINT32 ms)
|
||||
{
|
||||
if (cv_sleep.value > 0)
|
||||
SDL_Delay(cv_sleep.value);
|
||||
SDL_Delay(ms);
|
||||
}
|
||||
|
||||
#ifdef NEWSIGNALHANDLER
|
||||
|
|
|
@ -1351,12 +1351,15 @@ void I_UpdateNoBlit(void)
|
|||
// from PrBoom's src/SDL/i_video.c
|
||||
static inline boolean I_SkipFrame(void)
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
// While I fixed the FPS counter bugging out with this,
|
||||
// I actually really like being able to pause and
|
||||
// use perfstats to measure rendering performance
|
||||
// without game logic changes.
|
||||
return false;
|
||||
#else
|
||||
static boolean skip = false;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return false;
|
||||
|
||||
skip = !skip;
|
||||
|
||||
switch (gamestate)
|
||||
|
@ -1371,17 +1374,20 @@ static inline boolean I_SkipFrame(void)
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// I_FinishUpdate
|
||||
//
|
||||
static SDL_Rect src_rect = { 0, 0, 0, 0 };
|
||||
|
||||
void I_FinishUpdate(void)
|
||||
{
|
||||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
SCR_CalculateFPS();
|
||||
|
||||
if (I_SkipFrame())
|
||||
return;
|
||||
|
||||
|
@ -1398,27 +1404,22 @@ void I_FinishUpdate(void)
|
|||
|
||||
if (rendermode == render_soft && screens[0])
|
||||
{
|
||||
SDL_Rect rect;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = vid.width;
|
||||
rect.h = vid.height;
|
||||
|
||||
if (!bufSurface) //Double-Check
|
||||
{
|
||||
Impl_VideoSetupSDLBuffer();
|
||||
}
|
||||
|
||||
if (bufSurface)
|
||||
{
|
||||
SDL_BlitSurface(bufSurface, NULL, vidSurface, &rect);
|
||||
SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect);
|
||||
// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
|
||||
SDL_LockSurface(vidSurface);
|
||||
SDL_UpdateTexture(texture, &rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UnlockSurface(vidSurface);
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderCopy(renderer, texture, &src_rect, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
|
@ -1428,6 +1429,7 @@ void I_FinishUpdate(void)
|
|||
OglSdlFinishUpdate(cv_vidwait.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
exposevideo = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1668,6 +1670,27 @@ INT32 VID_SetMode(INT32 modeNum)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static UINT32 refresh_rate;
|
||||
static UINT32 VID_GetRefreshRate(void)
|
||||
{
|
||||
int index = SDL_GetWindowDisplayIndex(window);
|
||||
SDL_DisplayMode m;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
{
|
||||
// Video not init yet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SDL_GetCurrentDisplayMode(index, &m) != 0)
|
||||
{
|
||||
// Error has occurred.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m.refresh_rate;
|
||||
}
|
||||
|
||||
static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
|
||||
{
|
||||
int flags = 0;
|
||||
|
@ -2057,4 +2080,15 @@ void I_ShutdownGraphics(void)
|
|||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
framebuffer = SDL_FALSE;
|
||||
}
|
||||
|
||||
UINT32 I_GetRefreshRate(void)
|
||||
{
|
||||
// Moved to VID_GetRefreshRate.
|
||||
// Precalculating it like that won't work as
|
||||
// well for windowed mode since you can drag
|
||||
// the window around, but very slow PCs might have
|
||||
// trouble querying mode over and over again.
|
||||
return refresh_rate;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,8 +42,12 @@
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hook.h"
|
||||
#endif
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
UINT16 objectsdrawn = 0;
|
||||
|
||||
//
|
||||
|
@ -175,6 +179,10 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
|
|||
{ 240, 160}, // HUD_LAP
|
||||
};
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
static huddrawlist_h luahuddrawlist_game;
|
||||
#endif
|
||||
|
||||
//
|
||||
// STATUS BAR CODE
|
||||
//
|
||||
|
@ -422,6 +430,10 @@ void ST_Init(void)
|
|||
return;
|
||||
|
||||
ST_LoadGraphics();
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
luahuddrawlist_game = LUA_HUD_CreateDrawList();
|
||||
#endif
|
||||
}
|
||||
|
||||
// change the status bar too, when pressing F12 while viewing a demo.
|
||||
|
@ -1952,7 +1964,14 @@ static void ST_overlayDrawer(void)
|
|||
|
||||
#ifdef HAVE_BLUA
|
||||
if (!(netgame || multiplayer) || !hu_showscores)
|
||||
LUAh_GameHUD(stplyr);
|
||||
{
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_game);
|
||||
LUAh_GameHUD(stplyr, luahuddrawlist_game);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_game);
|
||||
}
|
||||
#endif
|
||||
|
||||
// draw level title Tails
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "g_game.h" // G_LoadGameData
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "d_netfil.h"
|
||||
#include "dehacked.h"
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <mmsystem.h>
|
||||
|
||||
#include "../m_misc.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_video.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../i_system.h"
|
||||
|
@ -45,6 +46,7 @@
|
|||
#include "../d_main.h"
|
||||
|
||||
#include "../m_argv.h"
|
||||
#include "../m_fixed.h"
|
||||
|
||||
#include "../w_wad.h"
|
||||
#include "../z_zone.h"
|
||||
|
@ -259,10 +261,25 @@ tic_t I_GetTime(void)
|
|||
return newtics;
|
||||
}
|
||||
|
||||
void I_Sleep(void)
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
if (cv_sleep.value > 0)
|
||||
Sleep(cv_sleep.value);
|
||||
LARGE_INTEGER time;
|
||||
BOOL res = QueryPerformanceCounter(&time);
|
||||
if (!res) I_Error("QueryPerformanceCounter error"); // if this happens, you've gone back to the 90s
|
||||
return (precise_t) time.QuadPart;
|
||||
}
|
||||
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
LARGE_INTEGER time;
|
||||
BOOL res = QueryPerformanceFrequency(&time);
|
||||
if (!res) I_Error("QueryPerformanceFrequency error"); // if this happens, you've gone back to the 90s
|
||||
return (precise_t) time.QuadPart;
|
||||
}
|
||||
|
||||
void I_Sleep(UINT32 ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
// should move to i_video
|
||||
|
|
Loading…
Reference in a new issue