mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Uncapped (squashed v2)
Squashed SRB2 2.2 Public uncapped without UDMF merge
Implement interpolation at the renderer level
Instead of interpolating thinkers, we interpolate mobjs inside the
renderer. Further interpolation is TBI.
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 6ecac4159a 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.
Adjust spawned mobj z by gravity inversion
Only check VERTICALFLIP for old_z calc
Fix Marathon Mode menu for uncapped
Move screenshot code before timing
Only play emerald hunt sounds on new tics
Restore deleted zofs (fixes signpost sparkles etc)
Revert to before screenUpdate boolean was added
Was done this way for the sake of an older version of uncapped's timing; now that the new timing is much better, I decided it should remain as close to pre-uncapped as it can be.
Run UpdateLevelInterpolators in preticker
Fixes KartKrew/Kart-Public#10
Run UpdateMobjInterpolators in preticker
Reset view interp in preticker
Add per-split player view resets
This commit is contained in:
parent
f13149c061
commit
f7ec2f182f
62 changed files with 2509 additions and 665 deletions
|
|
@ -20,6 +20,7 @@ command.c
|
|||
console.c
|
||||
font.c
|
||||
hu_stuff.c
|
||||
i_time.c
|
||||
y_inter.c
|
||||
st_stuff.c
|
||||
m_aatree.c
|
||||
|
|
@ -97,6 +98,7 @@ lua_taglib.c
|
|||
lua_polyobjlib.c
|
||||
lua_blockmaplib.c
|
||||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
k_kart.c
|
||||
k_respawn.c
|
||||
k_collide.c
|
||||
|
|
@ -115,4 +117,4 @@ k_boss.c
|
|||
k_hud.c
|
||||
k_terrain.c
|
||||
k_brightmap.c
|
||||
k_director.c
|
||||
k_director.c
|
||||
|
|
|
|||
|
|
@ -82,20 +82,18 @@ 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;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
//stub
|
||||
return 0;
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
void I_OsPolling(void){}
|
||||
|
|
|
|||
|
|
@ -2010,9 +2010,10 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
{
|
||||
increment = 0;
|
||||
currentindice = max;
|
||||
break; // The value we definitely want, stop here.
|
||||
}
|
||||
else if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max;
|
||||
currentindice = max; // The value we maybe want.
|
||||
}
|
||||
|
||||
if (increment)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <unistd.h> //for unlink
|
||||
#endif
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
|
@ -1947,7 +1948,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;
|
||||
}
|
||||
|
|
|
|||
128
src/d_main.c
128
src/d_main.c
|
|
@ -40,6 +40,7 @@
|
|||
#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"
|
||||
|
|
@ -455,6 +456,8 @@ static void D_Display(void)
|
|||
{
|
||||
if (!automapactive && !dedicated && cv_renderview.value)
|
||||
{
|
||||
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
|
||||
|
||||
viewwindowy = 0;
|
||||
viewwindowx = 0;
|
||||
|
||||
|
|
@ -530,6 +533,7 @@ static void D_Display(void)
|
|||
}
|
||||
|
||||
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime;
|
||||
R_RestoreLevelInterpolators();
|
||||
}
|
||||
|
||||
if (lastdraw)
|
||||
|
|
@ -710,9 +714,11 @@ tic_t rendergametic;
|
|||
|
||||
void D_SRB2Loop(void)
|
||||
{
|
||||
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
boolean ticked;
|
||||
boolean interp;
|
||||
tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
double deltatics = 0.0;
|
||||
double deltasecs = 0.0;
|
||||
|
||||
boolean interp = false;
|
||||
boolean doDisplay = false;
|
||||
|
||||
if (dedicated)
|
||||
|
|
@ -725,6 +731,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()
|
||||
|
|
@ -766,6 +773,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;
|
||||
|
|
@ -777,8 +797,6 @@ 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.
|
||||
|
|
@ -791,16 +809,8 @@ void D_SRB2Loop(void)
|
|||
debugload--;
|
||||
#endif
|
||||
|
||||
interp = R_UsingFrameInterpolation();
|
||||
interp = R_UsingFrameInterpolation() && !dedicated;
|
||||
doDisplay = false;
|
||||
ticked = false;
|
||||
|
||||
if (!realtics && !singletics && !interp)
|
||||
{
|
||||
// Non-interp sleep
|
||||
I_Sleep();
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef HW3SOUND
|
||||
HW3S_BeginFrameUpdate();
|
||||
|
|
@ -814,12 +824,12 @@ void D_SRB2Loop(void)
|
|||
realtics = 1;
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
ticked = TryRunTics(realtics);
|
||||
TryRunTics(realtics);
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
rendertimeout = entertic + TICRATE/17;
|
||||
|
||||
doDisplay = true;
|
||||
}
|
||||
|
|
@ -827,63 +837,26 @@ void D_SRB2Loop(void)
|
|||
{
|
||||
doDisplay = true;
|
||||
}
|
||||
|
||||
renderisnewtic = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderisnewtic = false;
|
||||
}
|
||||
|
||||
if (interp)
|
||||
{
|
||||
static float tictime = 0.0f;
|
||||
static float prevtime = 0.0f;
|
||||
float entertime = I_GetTimeFrac();
|
||||
|
||||
fixed_t entertimefrac = FRACUNIT;
|
||||
|
||||
if (ticked)
|
||||
{
|
||||
tictime = entertime;
|
||||
}
|
||||
|
||||
// Handle interp sleep / framerate cap here.
|
||||
// TryRunTics needs ran if possible to prevent lagged map changes,
|
||||
// (and if that runs, the code above needs to also run)
|
||||
// so this is done here after TryRunTics.
|
||||
if (D_CheckFrameCap())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
renderdeltatics = FLOAT_TO_FIXED(deltatics);
|
||||
|
||||
if (!(paused || P_AutoPause()))
|
||||
{
|
||||
#if 0
|
||||
CONS_Printf("prevtime = %f\n", prevtime);
|
||||
CONS_Printf("entertime = %f\n", entertime);
|
||||
CONS_Printf("tictime = %f\n", tictime);
|
||||
CONS_Printf("entertime - prevtime = %f\n", entertime - prevtime);
|
||||
CONS_Printf("entertime - tictime = %f\n", entertime - tictime);
|
||||
CONS_Printf("========\n");
|
||||
#endif
|
||||
|
||||
if (entertime - prevtime >= 1.0f)
|
||||
{
|
||||
// Lagged for more frames than a gametic...
|
||||
// No need for interpolation.
|
||||
entertimefrac = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
entertimefrac = min(FRACUNIT, FLOAT_TO_FIXED(entertime - tictime));
|
||||
}
|
||||
|
||||
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
if (entertimefrac > rendertimefrac)
|
||||
renderdeltatics += entertimefrac - rendertimefrac;
|
||||
else
|
||||
renderdeltatics -= rendertimefrac - entertimefrac;
|
||||
|
||||
rendertimefrac = entertimefrac;
|
||||
rendertimefrac = g_time.timefrac;
|
||||
}
|
||||
else
|
||||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
prevtime = entertime;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -896,9 +869,10 @@ void D_SRB2Loop(void)
|
|||
D_Display();
|
||||
}
|
||||
|
||||
// Only take screenshots after drawing.
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
if (takescreenshot)
|
||||
M_DoScreenShot();
|
||||
|
||||
// consoleplayer -> displayplayers (hear sounds from viewpoint)
|
||||
|
|
@ -918,10 +892,20 @@ void D_SRB2Loop(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Moved to here from I_FinishUpdate.
|
||||
// It doesn't track fades properly anymore by being here (might be easy fix),
|
||||
// but it's a little more accurate for actual game logic when its here.
|
||||
SCR_CalculateFPS();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1404,8 +1388,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();
|
||||
CON_SetLoadingProgress(LOADED_ISTARTUPTIMER);
|
||||
|
||||
// Make backups of some SOCcable tables.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -618,7 +619,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"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,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"
|
||||
|
|
|
|||
|
|
@ -343,6 +343,7 @@ typedef struct player_s
|
|||
// fun thing for player sprite
|
||||
angle_t drawangle;
|
||||
angle_t old_drawangle; // interp
|
||||
angle_t old_drawangle2;
|
||||
|
||||
// Bit flags.
|
||||
// See pflags_t, above.
|
||||
|
|
|
|||
|
|
@ -402,9 +402,7 @@ unset_bit_array (bitarray_t * const array, const int value)
|
|||
array[value >> 3] &= ~(1<<(value & 7));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SDL
|
||||
typedef UINT64 precise_t;
|
||||
#endif
|
||||
|
||||
#define intsign(n) \
|
||||
((n) < 0 ? -1 : (n) > 0 ? 1 : 0)
|
||||
|
|
|
|||
|
|
@ -11,18 +11,16 @@ UINT32 I_GetFreeMem(UINT32 *total)
|
|||
return 0;
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
void I_Sleep(UINT32 ms){}
|
||||
|
||||
precise_t I_GetPreciseTime(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
{
|
||||
return 0;
|
||||
UINT64 I_GetPrecisePrecision(void) {
|
||||
return 1000000;
|
||||
}
|
||||
|
||||
void I_Sleep(void){}
|
||||
|
||||
void I_GetEvent(void){}
|
||||
|
||||
void I_OsPolling(void){}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,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"
|
||||
|
|
@ -58,8 +59,6 @@ static tic_t stoptimer;
|
|||
|
||||
static boolean keypressed = false;
|
||||
|
||||
static tic_t xscrolltimer;
|
||||
static tic_t yscrolltimer;
|
||||
static INT32 menuanimtimer; // Title screen: background animation timing
|
||||
mobj_t *titlemapcameraref = NULL;
|
||||
|
||||
|
|
@ -158,6 +157,8 @@ static tic_t cutscene_lasttextwrite = 0;
|
|||
// STJR Intro
|
||||
char stjrintro[9] = "STJRI000";
|
||||
|
||||
static huddrawlist_h luahuddrawlist_title;
|
||||
|
||||
//
|
||||
// This alters the text string cutscene_disptext.
|
||||
// Use the typical string drawing functions to display it.
|
||||
|
|
@ -361,9 +362,6 @@ static void F_IntroDrawScene(void)
|
|||
|
||||
W_UnlockCachedPatch(background);
|
||||
|
||||
if (animtimer)
|
||||
animtimer--;
|
||||
|
||||
V_DrawString(cx, cy, 0, cutscene_disptext);
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +390,10 @@ void F_IntroDrawer(void)
|
|||
while (quittime > nowtime)
|
||||
{
|
||||
while (!((nowtime = I_GetTime()) - lasttime))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lasttime = nowtime;
|
||||
|
||||
I_OsPolling();
|
||||
|
|
@ -462,6 +463,9 @@ void F_IntroTicker(void)
|
|||
// check for skipping
|
||||
if (keypressed)
|
||||
keypressed = false;
|
||||
|
||||
if (animtimer > 0)
|
||||
animtimer--;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1706,6 +1710,9 @@ void F_InitMenuPresValues(void)
|
|||
//M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY");
|
||||
//M_SetMenuCurFadeValue(16);
|
||||
//M_SetMenuCurTitlePics();
|
||||
|
||||
LUA_HUD_DestroyDrawList(luahuddrawlist_title);
|
||||
luahuddrawlist_title = LUA_HUD_CreateDrawList();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1721,6 +1728,7 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
|
|||
INT32 pw, ph; // scaled by dupz
|
||||
patch_t *pat;
|
||||
INT32 i, j;
|
||||
fixed_t fracmenuanimtimer, xscrolltimer, yscrolltimer;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return;
|
||||
|
|
@ -1747,12 +1755,13 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
|
|||
tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center
|
||||
tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2;
|
||||
|
||||
xscrolltimer = ((menuanimtimer*scrollxspeed)/16 + patwidth*xneg) % (patwidth);
|
||||
yscrolltimer = ((menuanimtimer*scrollyspeed)/16 + patheight*yneg) % (patheight);
|
||||
fracmenuanimtimer = (menuanimtimer * FRACUNIT) - (FRACUNIT - rendertimefrac);
|
||||
xscrolltimer = ((fracmenuanimtimer*scrollxspeed)/16 + patwidth*xneg*FRACUNIT) % (patwidth * FRACUNIT);
|
||||
yscrolltimer = ((fracmenuanimtimer*scrollyspeed)/16 + patheight*yneg*FRACUNIT) % (patheight * FRACUNIT);
|
||||
|
||||
// coordinate offsets
|
||||
xscrolled = xscrolltimer * dupz;
|
||||
yscrolled = yscrolltimer * dupz;
|
||||
xscrolled = FixedInt(xscrolltimer * dupz);
|
||||
yscrolled = FixedInt(yscrolltimer * dupz);
|
||||
|
||||
for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0;
|
||||
i < tilex;
|
||||
|
|
@ -1997,7 +2006,12 @@ void F_TitleScreenDrawer(void)
|
|||
}
|
||||
|
||||
luahook:
|
||||
LUAh_TitleHUD();
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_title);
|
||||
LUAh_TitleHUD(luahuddrawlist_title);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_title);
|
||||
}
|
||||
|
||||
// separate animation timer for backgrounds, since we also count
|
||||
|
|
@ -2260,6 +2274,7 @@ static INT32 textxpos, textypos;
|
|||
static boolean dofadenow = false, cutsceneover = false;
|
||||
static boolean runningprecutscene = false, precutresetplayer = false;
|
||||
|
||||
|
||||
static void F_AdvanceToNextScene(void)
|
||||
{
|
||||
// Don't increment until after endcutscene check
|
||||
|
|
@ -2269,6 +2284,7 @@ static void F_AdvanceToNextScene(void)
|
|||
F_EndCutScene();
|
||||
return;
|
||||
}
|
||||
|
||||
++scenenum;
|
||||
|
||||
timetonext = 0;
|
||||
|
|
@ -2284,7 +2300,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;
|
||||
|
|
@ -2417,8 +2432,6 @@ void F_CutsceneTicker(void)
|
|||
finalecount++;
|
||||
cutscene_boostspeed = 0;
|
||||
|
||||
dofadenow = false;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (netgame && i != serverplayer && !IsPlayerAdmin(i))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,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"
|
||||
|
|
@ -477,7 +478,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean r
|
|||
|
||||
// wait loop
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lastwipetic = nowtime;
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "d_player.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "p_setup.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
|
|
|
|||
10
src/g_game.c
10
src/g_game.c
|
|
@ -21,6 +21,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"
|
||||
|
|
@ -1336,7 +1337,10 @@ void G_PreLevelTitleCard(void)
|
|||
M_DoScreenShot();
|
||||
|
||||
while (!((nowtime = I_GetTime()) - lasttime))
|
||||
I_Sleep();
|
||||
{
|
||||
I_Sleep(cv_sleep.value);
|
||||
I_UpdateTime(cv_timescale.value);
|
||||
}
|
||||
lasttime = nowtime;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1928,7 +1932,6 @@ void G_Ticker(boolean run)
|
|||
F_TextPromptTicker();
|
||||
AM_Ticker();
|
||||
HU_Ticker();
|
||||
R_UpdateViewInterpolation();
|
||||
|
||||
break;
|
||||
|
||||
|
|
@ -1987,10 +1990,7 @@ void G_Ticker(boolean run)
|
|||
|
||||
case GS_TITLESCREEN:
|
||||
if (titlemapinaction)
|
||||
{
|
||||
P_Ticker(run);
|
||||
R_UpdateViewInterpolation();
|
||||
}
|
||||
|
||||
F_TitleScreenTicker(run);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,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 hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "../v_video.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../r_fps.h"
|
||||
#include "../r_local.h"
|
||||
#include "../r_patch.h"
|
||||
#include "../r_picformats.h"
|
||||
|
|
@ -3051,6 +3052,7 @@ static 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)
|
||||
|
|
@ -3108,7 +3110,22 @@ static void HWR_Subsector(size_t num)
|
|||
|
||||
if (gl_frontsector->ffloors)
|
||||
{
|
||||
if (gl_frontsector->moved)
|
||||
boolean anyMoved = gl_frontsector->moved;
|
||||
|
||||
if (anyMoved == false)
|
||||
{
|
||||
for (rover = gl_frontsector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *controlSec = §ors[rover->secnum];
|
||||
if (controlSec->moved == true)
|
||||
{
|
||||
anyMoved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMoved == true)
|
||||
{
|
||||
gl_frontsector->numlights = sub->sector->numlights = 0;
|
||||
R_Prep3DFloors(gl_frontsector);
|
||||
|
|
@ -3189,7 +3206,6 @@ static void HWR_Subsector(size_t num)
|
|||
if (gl_frontsector->ffloors)
|
||||
{
|
||||
/// \todo fix light, xoffs, yoffs, extracolormap ?
|
||||
ffloor_t * rover;
|
||||
for (rover = gl_frontsector->ffloors;
|
||||
rover; rover = rover->next)
|
||||
{
|
||||
|
|
@ -3703,9 +3719,17 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
fixed_t slopez;
|
||||
pslope_t *groundslope;
|
||||
|
||||
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
|
|
@ -3717,17 +3741,17 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
mul = -mul;
|
||||
}
|
||||
|
||||
interpx += FixedMul(thing->momx, mul);
|
||||
interpy += FixedMul(thing->momy, mul);
|
||||
interpz += FixedMul(thing->momz, mul);
|
||||
interp.x += FixedMul(thing->momx, mul);
|
||||
interp.y += FixedMul(thing->momy, mul);
|
||||
interp.z += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
// sprite offset
|
||||
interpx += thing->sprxoff;
|
||||
interpy += thing->spryoff;
|
||||
interpz += thing->sprzoff;
|
||||
interp.x += thing->sprxoff;
|
||||
interp.y += thing->spryoff;
|
||||
interp.z += thing->sprzoff;
|
||||
|
||||
groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz);
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE);
|
||||
if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return;
|
||||
|
|
@ -3738,8 +3762,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
ph = (float)gpatch->height;
|
||||
|
||||
fscale = FIXED_TO_FLOAT(scalemul);
|
||||
fx = FIXED_TO_FLOAT(interpx);
|
||||
fy = FIXED_TO_FLOAT(interpy);
|
||||
fx = FIXED_TO_FLOAT(interp.x);
|
||||
fy = FIXED_TO_FLOAT(interp.y);
|
||||
|
||||
if (fscale > 0.0)
|
||||
{
|
||||
|
|
@ -5146,33 +5170,22 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
#endif
|
||||
|
||||
// uncapped/interpolation
|
||||
fixed_t interpx;
|
||||
fixed_t interpy;
|
||||
fixed_t interpz;
|
||||
angle_t interpangle;
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (thing->spritexscale < 1 || thing->spriteyscale < 1)
|
||||
return;
|
||||
|
||||
dispoffset = thing->info->dispoffset;
|
||||
|
||||
interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
interpangle = ANGLE_MAX;
|
||||
|
||||
if (thing->player)
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle);
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
interpangle = R_InterpolateAngle(thing->old_angle, thing->angle);
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
dispoffset = thing->info->dispoffset;
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
|
|
@ -5183,23 +5196,26 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
mul = -mul;
|
||||
}
|
||||
|
||||
interpx += FixedMul(thing->momx, mul);
|
||||
interpy += FixedMul(thing->momy, mul);
|
||||
interpz += FixedMul(thing->momz, mul);
|
||||
interp.x += FixedMul(thing->momx, mul);
|
||||
interp.y += FixedMul(thing->momy, mul);
|
||||
interp.z += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
// sprite offset
|
||||
interpx += thing->sprxoff;
|
||||
interpy += thing->spryoff;
|
||||
interpz += thing->sprzoff;
|
||||
interp.x += thing->sprxoff;
|
||||
interp.y += thing->spryoff;
|
||||
interp.z += thing->sprzoff;
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(thing->scale);
|
||||
spritexscale = FIXED_TO_FLOAT(thing->spritexscale);
|
||||
spriteyscale = FIXED_TO_FLOAT(thing->spriteyscale);
|
||||
if (interp.spritexscale < 1 || interp.spriteyscale < 1)
|
||||
return;
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
spritexscale = FIXED_TO_FLOAT(interp.spritexscale);
|
||||
spriteyscale = FIXED_TO_FLOAT(interp.spriteyscale);
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(interpx) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interpy) - gl_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin);
|
||||
|
|
@ -5222,8 +5238,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
|
||||
// The above can stay as it works for cutting sprites that are too close
|
||||
tr_x = FIXED_TO_FLOAT(interpx);
|
||||
tr_y = FIXED_TO_FLOAT(interpy);
|
||||
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
|
||||
|
|
@ -5271,7 +5287,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
|
||||
#endif
|
||||
|
||||
ang = R_PointToAngle (interpx, interpy) - interpangle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
if (mirrored)
|
||||
ang = InvAngle(ang);
|
||||
|
||||
|
|
@ -5342,8 +5358,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
|
||||
{
|
||||
spr_offset = thing->spritexoffset;
|
||||
spr_topoffset = thing->spriteyoffset;
|
||||
spr_offset = interp.spritexoffset;
|
||||
spr_topoffset = interp.spriteyoffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5352,14 +5368,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
|
||||
flipoffset = -1;
|
||||
|
||||
spr_offset += thing->spritexoffset * flipoffset;
|
||||
spr_topoffset += thing->spriteyoffset * flipoffset;
|
||||
spr_offset += interp.spritexoffset * flipoffset;
|
||||
spr_topoffset += interp.spriteyoffset * flipoffset;
|
||||
}
|
||||
|
||||
if (papersprite)
|
||||
{
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE((interpangle)>>ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE((interpangle)>>ANGLETOFINESHIFT));
|
||||
rightsin = FIXED_TO_FLOAT(FINESINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
rightcos = FIXED_TO_FLOAT(FINECOSINE(interp.angle >> ANGLETOFINESHIFT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5372,14 +5388,24 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (thing->renderflags & RF_SHADOWEFFECTS)
|
||||
{
|
||||
mobj_t *caster = thing->target;
|
||||
interpmobjstate_t casterinterp = {};
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(caster, rendertimefrac, &casterinterp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(caster, FRACUNIT, &casterinterp);
|
||||
}
|
||||
|
||||
if (caster && !P_MobjWasRemoved(caster))
|
||||
{
|
||||
fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz);
|
||||
fixed_t floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + caster->z - groundz);
|
||||
fixed_t groundz = R_GetShadowZ(thing, NULL);
|
||||
fixed_t floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + casterinterp.z - groundz);
|
||||
|
||||
shadowheight = FIXED_TO_FLOAT(floordiff);
|
||||
shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, caster->scale));
|
||||
shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale));
|
||||
|
||||
if (splat)
|
||||
spritexscale *= shadowscale;
|
||||
|
|
@ -5420,12 +5446,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (vflip)
|
||||
{
|
||||
gz = FIXED_TO_FLOAT(interpz + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = FIXED_TO_FLOAT(interpz) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gzt = FIXED_TO_FLOAT(interp.z) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
}
|
||||
|
||||
|
|
@ -5444,24 +5470,35 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
|
||||
{
|
||||
if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
|
||||
FIXED_TO_FLOAT(interpz) >= 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 (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
|
||||
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
|
||||
FIXED_TO_FLOAT(interpz) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
|
||||
return;
|
||||
}
|
||||
|
||||
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer)
|
||||
{
|
||||
interpmobjstate_t tracer_interp = {};
|
||||
|
||||
if (! R_ThingVisible(thing->tracer))
|
||||
return;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing->tracer, rendertimefrac, &tracer_interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing->tracer, FRACUNIT, &tracer_interp);
|
||||
}
|
||||
|
||||
// calculate tz for tracer, same way it is calculated for this sprite
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(thing->tracer->x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(thing->tracer->y) - gl_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(tracer_interp.x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(tracer_interp.y) - gl_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tracertz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin);
|
||||
|
|
@ -5588,21 +5625,25 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
unsigned rot = 0;
|
||||
UINT8 flip;
|
||||
|
||||
// uncapped/interpolation
|
||||
fixed_t interpx;
|
||||
fixed_t interpy;
|
||||
fixed_t interpz;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
// 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 = FIXED_TO_FLOAT(interpx) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interpy) - gl_viewy;
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
|
||||
|
||||
// rotation around vertical axis
|
||||
tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin);
|
||||
|
|
@ -5611,8 +5652,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (tz < ZCLIP_PLANE)
|
||||
return;
|
||||
|
||||
tr_x = FIXED_TO_FLOAT(interpx);
|
||||
tr_y = FIXED_TO_FLOAT(interpy);
|
||||
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)
|
||||
|
|
@ -5679,7 +5720,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
#endif
|
||||
|
||||
// set top/bottom coords
|
||||
vis->gzt = FIXED_TO_FLOAT(interpz + spritecachedinfo[lumpoff].topoffset);
|
||||
vis->gzt = FIXED_TO_FLOAT(interp.z + spritecachedinfo[lumpoff].topoffset);
|
||||
vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height);
|
||||
|
||||
vis->precip = true;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -1360,8 +1361,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
{
|
||||
patch_t *gpatch, *blendgpatch;
|
||||
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
|
||||
INT32 durs = spr->mobj->state->tics;
|
||||
INT32 tics = spr->mobj->tics;
|
||||
float durs = (float)spr->mobj->state->tics;
|
||||
float tics = (float)spr->mobj->tics;
|
||||
const boolean papersprite = (R_ThingIsPaperSprite(spr->mobj) && !R_ThingIsFloorSprite(spr->mobj));
|
||||
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj));
|
||||
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj));
|
||||
|
|
@ -1369,6 +1370,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
spriteframe_t *sprframe;
|
||||
INT32 mod;
|
||||
float finalscale;
|
||||
interpmobjstate_t interp;
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
fixed_t interpx = R_InterpolateFixed(spr->mobj->old_x, spr->mobj->x);
|
||||
fixed_t interpy = R_InterpolateFixed(spr->mobj->old_y, spr->mobj->y);
|
||||
|
|
@ -1543,8 +1554,8 @@ boolean HWR_DrawModel(gl_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;
|
||||
}
|
||||
|
||||
frame = (spr->mobj->frame & FF_FRAMEMASK);
|
||||
|
|
@ -1568,6 +1579,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
}
|
||||
|
||||
#ifdef USE_MODEL_NEXTFRAME
|
||||
// Interpolate the model interpolation. (lol)
|
||||
tics -= FixedToFloat(rendertimefrac);
|
||||
|
||||
#define INTERPOLERATION_LIMIT TICRATE/4
|
||||
if (
|
||||
#ifdef BAD_MODEL_OPTIONS
|
||||
|
|
@ -1620,13 +1634,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
#endif
|
||||
|
||||
//Hurdler: it seems there is still a small problem with mobj angle
|
||||
p.x = FIXED_TO_FLOAT(interpx);
|
||||
p.y = FIXED_TO_FLOAT(interpy) + md2->offset;
|
||||
p.x = FIXED_TO_FLOAT(interp.x);
|
||||
p.y = FIXED_TO_FLOAT(interp.y) + md2->offset;
|
||||
|
||||
if (flip)
|
||||
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(interpz);
|
||||
p.z = FIXED_TO_FLOAT(interp.z);
|
||||
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2];
|
||||
|
|
@ -1637,22 +1651,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
|
||||
if (sprframe->rotate || papersprite)
|
||||
{
|
||||
fixed_t anglef = INT32_MAX;
|
||||
|
||||
if (spr->mobj->player)
|
||||
{
|
||||
anglef = AngleFixed(R_InterpolateAngle(spr->mobj->player->old_drawangle, spr->mobj->player->drawangle));
|
||||
}
|
||||
else
|
||||
{
|
||||
anglef = AngleFixed(R_InterpolateAngle(spr->mobj->old_angle, spr->mobj->angle));
|
||||
}
|
||||
fixed_t anglef = AngleFixed(interp.angle);
|
||||
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
else
|
||||
{
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(interpx, interpy))-ANGLE_180);
|
||||
const fixed_t anglef = AngleFixed((R_PointToAngle(interp.x, interp.y))-ANGLE_180);
|
||||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2702,7 +2702,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
|
|||
|
||||
#define BUFFER_OFFSET(i) ((void*)(i))
|
||||
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
static GLRGBAFloat poly = {0,0,0,0};
|
||||
static GLRGBAFloat tint = {0,0,0,0};
|
||||
|
|
@ -2732,11 +2732,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
|
|||
scaley = vscale;
|
||||
scalez = hscale;
|
||||
|
||||
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;
|
||||
|
|
@ -2988,7 +2988,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 hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
|
||||
{
|
||||
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#endif
|
||||
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hook.h"
|
||||
|
||||
// SRB2Kart
|
||||
|
|
@ -169,6 +170,8 @@ static INT32 cechoflags = 0;
|
|||
|
||||
static tic_t resynch_ticker = 0;
|
||||
|
||||
static huddrawlist_h luahuddrawlist_scores;
|
||||
|
||||
//======================================================================
|
||||
// HEADS UP INIT
|
||||
//======================================================================
|
||||
|
|
@ -304,6 +307,8 @@ void HU_Init(void)
|
|||
}
|
||||
|
||||
HU_LoadGraphics();
|
||||
|
||||
luahuddrawlist_scores = LUA_HUD_CreateDrawList();
|
||||
}
|
||||
|
||||
patch_t *HU_CachePatch(const char *format, ...)
|
||||
|
|
@ -369,12 +374,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.
|
||||
|
|
@ -387,10 +392,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
|
||||
|
||||
|
|
@ -971,12 +976,8 @@ void HU_Ticker(void)
|
|||
if (chat_scrolltime > 0)
|
||||
chat_scrolltime--;
|
||||
}
|
||||
else
|
||||
{
|
||||
chat_scrolltime = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
if (netgame)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
|
|
@ -2082,6 +2083,8 @@ void HU_Drawer(void)
|
|||
else
|
||||
{
|
||||
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.
|
||||
}
|
||||
|
|
@ -2104,7 +2107,12 @@ void HU_Drawer(void)
|
|||
{
|
||||
if (LUA_HudEnabled(hud_rankings))
|
||||
HU_DrawRankings();
|
||||
LUAh_ScoresHUD();
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_scores);
|
||||
LUAh_ScoresHUD(luahuddrawlist_scores);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_scores);
|
||||
}
|
||||
|
||||
if (demo.playback)
|
||||
|
|
|
|||
|
|
@ -42,27 +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 Get the current time in tics including fractions.
|
||||
*/
|
||||
float I_GetTimeFrac(void);
|
||||
|
||||
/** \brief Returns precise time value for performance measurement.
|
||||
/** \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 Converts a precise_t to microseconds and casts it to a 32 bit integer.
|
||||
/** \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.
|
||||
*/
|
||||
int I_PreciseToMicros(precise_t d);
|
||||
UINT64 I_GetPrecisePrecision(void);
|
||||
|
||||
/** \brief The I_Sleep function
|
||||
/** \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);
|
||||
|
||||
boolean I_CheckFrameCap(precise_t start, precise_t end);
|
||||
|
||||
|
|
|
|||
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 = CVAR_INIT ("timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, 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__
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
#include "m_menu.h" // Player Setup menu color stuff
|
||||
#include "m_misc.h" // M_MapNumber
|
||||
#include "p_spec.h" // P_StartQuake
|
||||
#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros
|
||||
#include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
|
@ -1444,7 +1444,7 @@ static int lib_pTeleportMove(lua_State *L)
|
|||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin");
|
||||
lua_pushboolean(L, P_SetOrigin(thing, x, y, z));
|
||||
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
|
||||
LUA_PushUserdata(L, tmthing, META_MOBJ);
|
||||
P_SetTarget(&tmthing, ptmthing);
|
||||
return 2;
|
||||
|
|
@ -1484,42 +1484,6 @@ static int lib_pMoveOrigin(lua_State *L)
|
|||
return 2;
|
||||
}
|
||||
|
||||
static int lib_pInitAngle(lua_State *L)
|
||||
{
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
angle_t newValue = luaL_checkangle(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_InitAngle(thing, newValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pInitPitch(lua_State *L)
|
||||
{
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
angle_t newValue = luaL_checkangle(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_InitPitch(thing, newValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pInitRoll(lua_State *L)
|
||||
{
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
angle_t newValue = luaL_checkangle(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_InitRoll(thing, newValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pSlideMove(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
|
@ -3844,7 +3808,7 @@ static int lib_kDeclareWeakspot(lua_State *L)
|
|||
|
||||
static int lib_getTimeMicros(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, I_PreciseToMicros(I_GetPreciseTime()));
|
||||
lua_pushinteger(L, I_GetPreciseTime() / (I_GetPrecisePrecision() / 1000000));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -3955,9 +3919,6 @@ static luaL_Reg lib[] = {
|
|||
{"P_TeleportMove",lib_pTeleportMove},
|
||||
{"P_SetOrigin",lib_pSetOrigin},
|
||||
{"P_MoveOrigin",lib_pMoveOrigin},
|
||||
{"P_InitAngle",lib_pInitAngle},
|
||||
{"P_InitPitch",lib_pInitPitch},
|
||||
{"P_InitRoll",lib_pInitRoll},
|
||||
{"P_SlideMove",lib_pSlideMove},
|
||||
{"P_BounceMove",lib_pBounceMove},
|
||||
{"P_CheckSight", lib_pCheckSight},
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "r_defs.h"
|
||||
#include "d_player.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
enum hook {
|
||||
hook_NetVars=0,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -42,8 +47,10 @@ extern boolean hud_running;
|
|||
|
||||
boolean LUA_HudEnabled(enum hud option);
|
||||
|
||||
void LUAh_GameHUD(player_t *stplyr);
|
||||
void LUAh_ScoresHUD(void);
|
||||
void LUAh_TitleHUD(void);
|
||||
void LUAh_TitleCardHUD(player_t *stplayr);
|
||||
void LUAh_IntermissionHUD(void);
|
||||
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
|
||||
void LUAh_ScoresHUD(huddrawlist_h list);
|
||||
void LUAh_TitleHUD(huddrawlist_h list);
|
||||
void LUAh_TitleCardHUD(player_t *stplayr, huddrawlist_h list);
|
||||
void LUAh_IntermissionHUD(huddrawlist_h list);
|
||||
|
||||
#endif // __LUA_HUD_H__
|
||||
|
|
|
|||
168
src/lua_hudlib.c
168
src/lua_hudlib.c
|
|
@ -572,7 +572,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);
|
||||
|
|
@ -586,7 +587,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;
|
||||
}
|
||||
|
||||
|
|
@ -595,7 +603,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);
|
||||
|
|
@ -612,7 +621,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;
|
||||
}
|
||||
|
||||
|
|
@ -621,7 +637,8 @@ static int libd_drawStretched(lua_State *L)
|
|||
fixed_t x, y, hscale, vscale;
|
||||
INT32 flags;
|
||||
patch_t *patch;
|
||||
const UINT8 *colormap = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
|
|
@ -639,7 +656,14 @@ static int libd_drawStretched(lua_State *L)
|
|||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
V_DrawStretchyFixedPatch(x, y, hscale, vscale, 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_AddDrawStretched(list, x, y, hscale, vscale, patch, flags, colormap);
|
||||
else
|
||||
V_DrawStretchyFixedPatch(x, y, hscale, vscale, flags, patch, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -650,6 +674,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;
|
||||
|
|
@ -812,13 +837,22 @@ 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);
|
||||
|
|
@ -826,13 +860,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);
|
||||
|
|
@ -841,7 +884,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;
|
||||
}
|
||||
|
||||
|
|
@ -849,6 +899,7 @@ static int libd_drawPingNum(lua_State *L)
|
|||
{
|
||||
INT32 x, y, flags, num;
|
||||
const UINT8 *colormap = NULL;
|
||||
huddrawlist_h list;
|
||||
HUDONLY
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
|
|
@ -858,12 +909,20 @@ static int libd_drawPingNum(lua_State *L)
|
|||
if (!lua_isnoneornil(L, 5))
|
||||
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
|
||||
|
||||
V_DrawPingNum(x, y, flags, num, 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_AddDrawPingNum(list, x, y, flags, num, colormap);
|
||||
else
|
||||
V_DrawPingNum(x, y, flags, num, colormap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -871,7 +930,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;
|
||||
}
|
||||
|
||||
|
|
@ -880,6 +947,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
|
||||
|
||||
|
|
@ -889,18 +957,29 @@ 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);
|
||||
|
|
@ -910,6 +989,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
|
||||
|
|
@ -956,11 +1044,19 @@ static int libd_drawTitleCardString(lua_State *L)
|
|||
boolean rightalign = lua_optboolean(L, 5);
|
||||
INT32 timer = luaL_optinteger(L, 6, 0);
|
||||
INT32 threshold = luaL_optinteger(L, 7, 0);
|
||||
huddrawlist_h list;
|
||||
|
||||
flags &= ~V_PARAMMASK; // Don't let crashes happen.
|
||||
|
||||
HUDONLY
|
||||
V_DrawTitleCardString(x, y, str, flags, rightalign, timer, threshold);
|
||||
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_AddDrawTitleCardString(list, x, y, flags, str, rightalign, timer, threshold);
|
||||
else
|
||||
V_DrawTitleCardString(x, y, str, flags, rightalign, timer, threshold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -970,11 +1066,19 @@ 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;
|
||||
}
|
||||
|
||||
|
|
@ -1172,6 +1276,14 @@ static int libd_getusertransflag(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[] = {
|
||||
// cache
|
||||
{"patchExists", libd_patchExists},
|
||||
|
|
@ -1211,6 +1323,7 @@ static luaL_Reg lib_draw[] = {
|
|||
{"localTransFlag", libd_getlocaltransflag},
|
||||
{"drawOnMinimap", libd_drawOnMinimap},
|
||||
{"userTransFlag", libd_getusertransflag},
|
||||
{"getDeltaTime", libd_getDeltaTime},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -1358,11 +1471,14 @@ 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_settop(gL, 0);
|
||||
|
||||
|
|
@ -1410,11 +1526,14 @@ void LUAh_GameHUD(player_t *stplayr)
|
|||
hud_running = false;
|
||||
}
|
||||
|
||||
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_settop(gL, 0);
|
||||
|
||||
|
|
@ -1437,11 +1556,14 @@ void LUAh_ScoresHUD(void)
|
|||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_TitleHUD(void)
|
||||
void LUAh_TitleHUD(huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_title)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
|
|
@ -1464,11 +1586,14 @@ void LUAh_TitleHUD(void)
|
|||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_TitleCardHUD(player_t *stplayr)
|
||||
void LUAh_TitleCardHUD(player_t *stplayr, huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_titlecard)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
|
|
@ -1500,11 +1625,14 @@ void LUAh_TitleCardHUD(player_t *stplayr)
|
|||
hud_running = false;
|
||||
}
|
||||
|
||||
void LUAh_IntermissionHUD(void)
|
||||
void LUAh_IntermissionHUD(huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
|
||||
return;
|
||||
|
||||
lua_pushlightuserdata(gL, list);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
|
||||
|
||||
hud_running = true;
|
||||
lua_settop(gL, 0);
|
||||
|
||||
|
|
|
|||
463
src/lua_hudlib_drawlist.c
Normal file
463
src/lua_hudlib_drawlist.c
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
// 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_DrawStretched,
|
||||
DI_DrawNum,
|
||||
DI_DrawPaddedNum,
|
||||
DI_DrawPingNum,
|
||||
DI_DrawFill,
|
||||
DI_DrawString,
|
||||
DI_FadeScreen,
|
||||
DI_DrawTitleCardString,
|
||||
DI_DrawKartString,
|
||||
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;
|
||||
INT32 timer;
|
||||
INT32 threshold;
|
||||
boolean bossmode;
|
||||
} 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_small,
|
||||
align_smallcenter,
|
||||
align_smallright,
|
||||
align_thin,
|
||||
align_thincenter,
|
||||
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_AddDrawStretched(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t hscale,
|
||||
fixed_t vscale,
|
||||
patch_t *patch,
|
||||
INT32 flags,
|
||||
UINT8 *colormap
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawStretched;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->hscale = hscale;
|
||||
item->vscale = vscale;
|
||||
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_AddDrawPingNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 flags,
|
||||
INT32 num,
|
||||
const UINT8 *colormap
|
||||
)
|
||||
{
|
||||
*(int*)(NULL + 1);
|
||||
}
|
||||
|
||||
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_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_AddDrawTitleCardString(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 flags,
|
||||
const char *str,
|
||||
boolean bossmode,
|
||||
INT32 timer,
|
||||
INT32 threshold
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawTitleCardString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->flags = flags;
|
||||
item->str = CopyString(list, str);
|
||||
item->bossmode = bossmode;
|
||||
item->timer = timer;
|
||||
item->threshold = threshold;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
INT32 flags,
|
||||
const char *str
|
||||
)
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->type = DI_DrawKartString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->flags = flags;
|
||||
item->str = CopyString(list, str);
|
||||
}
|
||||
|
||||
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_DrawStretched:
|
||||
V_DrawStretchyFixedPatch(item->x, item->y, item->hscale, item->vscale, 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_DrawPingNum:
|
||||
V_DrawPingNum(item->x, item->y, item->flags, item->num, item->colormap);
|
||||
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;
|
||||
// hu_font, 0.5x scale
|
||||
case align_small:
|
||||
V_DrawSmallString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
case align_smallcenter:
|
||||
V_DrawCenteredSmallString(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_thincenter:
|
||||
V_DrawCenteredThinString(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_FadeScreen:
|
||||
V_DrawFadeScreen(item->color, item->strength);
|
||||
break;
|
||||
case DI_DrawTitleCardString:
|
||||
V_DrawTitleCardString(item->x, item->y, item->str, item->flags, item->bossmode, item->timer, item->threshold);
|
||||
break;
|
||||
case DI_DrawKartString:
|
||||
V_DrawKartString(item->x, item->y, item->flags, item->str);
|
||||
break;
|
||||
default:
|
||||
I_Error("can't draw draw list item: invalid draw list item type");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
133
src/lua_hudlib_drawlist.h
Normal file
133
src/lua_hudlib_drawlist.h
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
// 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_AddDrawStretched(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t hscale,
|
||||
fixed_t vscale,
|
||||
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_AddDrawPingNum(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 flags,
|
||||
INT32 num,
|
||||
const UINT8 *colormap
|
||||
);
|
||||
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_AddFadeScreen(
|
||||
huddrawlist_h list,
|
||||
UINT16 color,
|
||||
UINT8 strength
|
||||
);
|
||||
void LUA_HUD_AddDrawTitleCardString(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
INT32 y,
|
||||
INT32 flags,
|
||||
const char *str,
|
||||
boolean bossmode,
|
||||
INT32 timer,
|
||||
INT32 threshold
|
||||
);
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
huddrawlist_h list,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
INT32 flags,
|
||||
const char *str
|
||||
);
|
||||
|
||||
// Draws the given draw list
|
||||
void LUA_HUD_DrawList(huddrawlist_h list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __LUA_HUDLIB_DRAWLIST__
|
||||
|
|
@ -778,6 +778,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:
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ static void GIF_framewrite(void)
|
|||
{
|
||||
// golden's attempt at creating a "dynamic delay"
|
||||
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
|
||||
gif_delayus += I_PreciseToMicros(I_GetPreciseTime() - gif_prevframetime); // increase delay by how much time was spent between last measurement
|
||||
gif_delayus += (I_GetPreciseTime() - gif_prevframetime) / (I_GetPrecisePrecision() / 1000000); // increase delay by how much time was spent between last measurement
|
||||
|
||||
if (gif_delayus/1000 >= mingifdelay) // delay is big enough to be able to effect gif frame delay?
|
||||
{
|
||||
|
|
@ -621,7 +621,7 @@ static void GIF_framewrite(void)
|
|||
{
|
||||
float delayf = ceil(100.0f/NEWTICRATE);
|
||||
|
||||
delay = (UINT16)I_PreciseToMicros((I_GetPreciseTime() - gif_prevframetime))/10/1000;
|
||||
delay = (UINT16)((I_GetPreciseTime() - gif_prevframetime)) / (I_GetPrecisePrecision() / 1000000) /10/1000;
|
||||
|
||||
if (delay < (UINT16)(delayf))
|
||||
delay = (UINT16)(delayf);
|
||||
|
|
|
|||
15
src/m_menu.c
15
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"
|
||||
|
||||
|
|
@ -6958,6 +6960,7 @@ static void M_DrawLoad(void)
|
|||
INT32 ymod = 0, offset = 0;
|
||||
|
||||
M_DrawMenuTitle();
|
||||
fixed_t scrollfrac = FixedDiv(2, 3);
|
||||
|
||||
if (menumovedir != 0) //movement illusion
|
||||
{
|
||||
|
|
@ -9340,7 +9343,7 @@ static void M_HandleConnectIP(INT32 choice)
|
|||
// Tails 03-02-2002
|
||||
|
||||
// used for skin display on player setup menu
|
||||
static INT32 multi_tics;
|
||||
static fixed_t multi_tics;
|
||||
static state_t *multi_state;
|
||||
static UINT8 multi_spr2;
|
||||
|
||||
|
|
@ -9570,7 +9573,8 @@ static void M_DrawSetupMultiPlayerMenu(void)
|
|||
#undef iconwidth
|
||||
|
||||
// anim the player in the box
|
||||
if (--multi_tics <= 0)
|
||||
multi_tics -= renderdeltatics;
|
||||
if (multi_tics <= 0)
|
||||
{
|
||||
st = multi_state->nextstate;
|
||||
if (st != S_NULL)
|
||||
|
|
@ -9860,7 +9864,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[0].string);
|
||||
|
||||
|
|
@ -9904,7 +9908,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_playername[1].string);
|
||||
|
||||
// set for splitscreen secondary player
|
||||
|
|
@ -11426,7 +11430,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"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "d_netcmd.h"
|
||||
#include "r_main.h"
|
||||
#include "i_system.h"
|
||||
#include "i_time.h"
|
||||
#include "z_zone.h"
|
||||
#include "p_local.h"
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ static void M_DrawPerfString(perfstatcol_t *col, int type)
|
|||
for (row = col->rows; row->lores_label; ++row)
|
||||
{
|
||||
if (type == PERF_TIME)
|
||||
value = I_PreciseToMicros(*(precise_t *)row->value);
|
||||
value = (*(precise_t *)row->value) / (I_GetPrecisePrecision() / 1000000);
|
||||
else
|
||||
value = *(int *)row->value;
|
||||
|
||||
|
|
@ -565,7 +566,7 @@ void M_DrawPerfStats(void)
|
|||
len = (int)strlen(str);
|
||||
if (len > 20)
|
||||
str += len - 20;
|
||||
snprintf(s, sizeof s - 1, "%20s: %d", str, I_PreciseToMicros(thinkframe_hooks[i].time_taken));
|
||||
snprintf(s, sizeof s - 1, "%20s: %lld", str, (thinkframe_hooks[i].time_taken) / (I_GetPrecisePrecision() / 1000000));
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s);
|
||||
y += 4; // repeated code!
|
||||
if (y > 192)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -602,6 +603,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
ceiling->tag = tag;
|
||||
ceiling->type = type;
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
@ -679,6 +683,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
|
||||
ceiling->tag = tag;
|
||||
ceiling->type = type;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "p_slopes.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_state.h"
|
||||
#include "s_sound.h"
|
||||
#include "z_zone.h"
|
||||
|
|
@ -573,6 +574,8 @@ void T_ContinuousFalling(continuousfall_t *faller)
|
|||
{
|
||||
faller->sector->ceilingheight = faller->ceilingstartheight;
|
||||
faller->sector->floorheight = faller->floorstartheight;
|
||||
|
||||
R_ClearLevelInterpolatorState(&faller->thinker);
|
||||
}
|
||||
|
||||
P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong
|
||||
|
|
@ -1948,6 +1951,9 @@ void EV_DoFloor(line_t *line, floor_e floortype)
|
|||
}
|
||||
|
||||
firstone = 0;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2078,6 +2084,10 @@ void 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2232,6 +2242,10 @@ void EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
|
|||
bouncer->speed = momz/2;
|
||||
bouncer->distance = FRACUNIT;
|
||||
bouncer->low = true;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, true);
|
||||
}
|
||||
|
||||
// For T_ContinuousFalling special
|
||||
|
|
@ -2257,6 +2271,10 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole
|
|||
|
||||
faller->destheight = backwards ? backsector->ceilingheight : backsector->floorheight;
|
||||
faller->direction = backwards ? 1 : -1;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, true);
|
||||
}
|
||||
|
||||
// Some other 3dfloor special things Tails 03-11-2002 (Search p_mobj.c for description)
|
||||
|
|
@ -2309,6 +2327,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
|
||||
crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&crumble->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&crumble->thinker, sec, true);
|
||||
|
||||
TAG_ITER_SECTORS(tag, i)
|
||||
{
|
||||
foundsec = §ors[i];
|
||||
|
|
@ -2360,6 +2382,10 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
block->ceilingstartheight = block->sector->ceilingheight;
|
||||
block->tag = (INT16)Tag_FGet(§or->tags);
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversec, false);
|
||||
R_CreateInterpolator_SectorPlane(&block->thinker, roversec, true);
|
||||
|
||||
if (itsamonitor)
|
||||
{
|
||||
oldx = thing->x;
|
||||
|
|
@ -2368,9 +2394,9 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
}
|
||||
|
||||
P_UnsetThingPosition(thing);
|
||||
thing->x = sector->soundorg.x;
|
||||
thing->y = sector->soundorg.y;
|
||||
thing->z = topheight;
|
||||
thing->x = thing->old_x = sector->soundorg.x;
|
||||
thing->y = thing->old_y = sector->soundorg.y;
|
||||
thing->z = thing->old_z = topheight;
|
||||
thing->momz = FixedMul(6*FRACUNIT, thing->scale);
|
||||
P_SetThingPosition(thing);
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
|
|
@ -2391,9 +2417,9 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
if (itsamonitor && thing)
|
||||
{
|
||||
P_UnsetThingPosition(thing);
|
||||
thing->x = oldx;
|
||||
thing->y = oldy;
|
||||
thing->z = oldz;
|
||||
thing->x = thing->old_x = oldx;
|
||||
thing->y = thing->old_y = oldy;
|
||||
thing->z = thing->old_z = oldz;
|
||||
thing->momx = 1;
|
||||
thing->momy = 1;
|
||||
P_SetThingPosition(thing);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -181,6 +182,7 @@ void P_InitRoll(mobj_t *thing, angle_t newValue)
|
|||
thing->roll = thing->old_roll = newValue;
|
||||
}
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// MOVEMENT ITERATOR FUNCTIONS
|
||||
// =========================================================================
|
||||
|
|
@ -654,9 +656,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);
|
||||
P_SetOrigin(thing, thing->x, thing->y, tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale));
|
||||
else
|
||||
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
|
||||
P_SetOrigin(thing, thing->x, thing->y, tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale));
|
||||
if (thing->flags & MF_SHOOTABLE)
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
|
||||
return true;
|
||||
|
|
|
|||
76
src/p_mobj.c
76
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_skins.h"
|
||||
#include "r_sky.h"
|
||||
|
|
@ -3818,13 +3819,7 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
|
|||
|
||||
void P_PrecipThinker(precipmobj_t *mobj)
|
||||
{
|
||||
// reset old state (for interpolation)
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
|
|
@ -3872,12 +3867,14 @@ void P_PrecipThinker(precipmobj_t *mobj)
|
|||
if ((mobj->info->deathstate == S_NULL) || (mobj->precipflags & PCF_PIT)) // no splashes on sky or bottomless pits
|
||||
{
|
||||
mobj->z = mobj->ceilingz;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetPrecipMobjState(mobj, mobj->info->deathstate);
|
||||
mobj->z = mobj->floorz;
|
||||
mobj->precipflags |= PCF_SPLASH;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5431,6 +5428,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale);
|
||||
else
|
||||
mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height;
|
||||
|
||||
mobj->old_z = mobj->z;
|
||||
|
||||
break;
|
||||
case MT_LOCKONINF:
|
||||
if (!(mobj->flags2 & MF2_STRONGBOX))
|
||||
|
|
@ -5442,6 +5442,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale);
|
||||
else
|
||||
mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale);
|
||||
|
||||
mobj->old_z = mobj->z;
|
||||
|
||||
break;
|
||||
case MT_FLAMEJET:
|
||||
P_FlameJetSceneryThink(mobj);
|
||||
|
|
@ -10322,13 +10325,7 @@ 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);
|
||||
|
||||
// set initial old positions (for interpolation)
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
|
@ -10381,13 +10378,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
|| mobj->subsector->sector->floorpic == skyflatnum)
|
||||
mobj->precipflags |= PCF_PIT;
|
||||
|
||||
// set initial old positions (for interpolation)
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
|
@ -10519,6 +10510,8 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
|
||||
#endif
|
||||
|
||||
R_RemoveMobjInterpolator(mobj);
|
||||
|
||||
// free block
|
||||
if (!mobj->thinker.next)
|
||||
{ // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through!
|
||||
|
|
@ -13479,18 +13472,43 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
|
|||
newmobj->eflags |= MFE_VERTICALFLIP;
|
||||
newmobj->flags2 |= MF2_OBJECTFLIP;
|
||||
newmobj->z = mobj->z + mobj->height - zofs - newmobj->height;
|
||||
|
||||
newmobj->old_z = mobj->old_z + mobj->height - zofs - newmobj->height;
|
||||
newmobj->old_z2 = mobj->old_z2 + mobj->height - zofs - newmobj->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj->old_z = mobj->old_z + zofs;
|
||||
newmobj->old_z2 = mobj->old_z2 + zofs;
|
||||
}
|
||||
|
||||
// EXPERIMENT: Let all objects set their interp values relative to their owner's old values.
|
||||
// This will hopefully create a lot less mobj-specific spawn cases,
|
||||
// but if there's any weird scenarios feel free to remove again.
|
||||
newmobj->destscale = mobj->destscale;
|
||||
P_SetScale(newmobj, mobj->scale);
|
||||
|
||||
newmobj->old_x2 = mobj->old_x2 + xofs;
|
||||
newmobj->old_y2 = mobj->old_y2 + yofs;
|
||||
newmobj->old_x = mobj->old_x + xofs;
|
||||
newmobj->old_y = mobj->old_y + yofs;
|
||||
newmobj->old_z = mobj->old_z + zofs;
|
||||
/*
|
||||
newmobj->angle = mobj->angle;
|
||||
newmobj->old_angle = mobj->old_angle;
|
||||
*/
|
||||
|
||||
// This angle hack is needed for Lua scripts that set the angle after
|
||||
// spawning, to avoid erroneous interpolation.
|
||||
if (mobj->player)
|
||||
{
|
||||
newmobj->old_angle2 = mobj->player->old_drawangle2;
|
||||
newmobj->old_angle = mobj->player->old_drawangle;
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj->old_angle2 = mobj->old_angle2;
|
||||
newmobj->old_angle = mobj->old_angle;
|
||||
}
|
||||
|
||||
newmobj->old_scale2 = mobj->old_scale2;
|
||||
newmobj->old_scale = mobj->old_scale;
|
||||
newmobj->old_spritexscale = mobj->old_spritexscale;
|
||||
newmobj->old_spriteyscale = mobj->old_spriteyscale;
|
||||
newmobj->old_spritexoffset = mobj->old_spritexoffset;
|
||||
newmobj->old_spriteyoffset = mobj->old_spriteyoffset;
|
||||
|
||||
return newmobj;
|
||||
}
|
||||
|
|
|
|||
11
src/p_mobj.h
11
src/p_mobj.h
|
|
@ -282,6 +282,7 @@ 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;
|
||||
|
|
@ -290,6 +291,7 @@ typedef struct mobj_s
|
|||
// More drawing info: to determine current sprite.
|
||||
angle_t angle, pitch, roll; // orientation
|
||||
angle_t old_angle, old_pitch, old_roll; // orientation interpolation
|
||||
angle_t old_angle2, old_pitch2, old_roll2;
|
||||
angle_t rollangle;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
|
|
@ -299,6 +301,8 @@ typedef struct mobj_s
|
|||
UINT32 renderflags; // render flags
|
||||
fixed_t spritexscale, spriteyscale;
|
||||
fixed_t spritexoffset, spriteyoffset;
|
||||
fixed_t old_spritexscale, old_spriteyscale;
|
||||
fixed_t old_spritexoffset, old_spriteyoffset;
|
||||
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
|
||||
|
||||
struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
|
||||
|
|
@ -377,6 +381,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;
|
||||
|
||||
|
|
@ -391,6 +397,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
|
||||
boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left
|
||||
|
||||
|
|
@ -423,6 +430,7 @@ 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;
|
||||
|
|
@ -431,6 +439,7 @@ typedef struct precipmobj_s
|
|||
// More drawing info: to determine current sprite.
|
||||
angle_t angle, pitch, roll; // orientation
|
||||
angle_t old_angle, old_pitch, old_roll; // orientation interpolation
|
||||
angle_t old_angle2, old_pitch2, old_roll2;
|
||||
angle_t rollangle;
|
||||
spritenum_t sprite; // used to find patch_t and flip value
|
||||
UINT32 frame; // frame number, plus bits see p_pspr.h
|
||||
|
|
@ -440,6 +449,8 @@ typedef struct precipmobj_s
|
|||
UINT32 renderflags; // render flags
|
||||
fixed_t spritexscale, spriteyscale;
|
||||
fixed_t spritexoffset, spriteyoffset;
|
||||
fixed_t old_spritexscale, old_spriteyscale;
|
||||
fixed_t old_spritexoffset, old_spriteyoffset;
|
||||
struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
|
||||
|
||||
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -2051,6 +2052,9 @@ boolean 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
|
||||
|
|
@ -2112,6 +2116,9 @@ boolean 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)))
|
||||
|
|
@ -2127,8 +2134,10 @@ boolean EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
||||
{
|
||||
polyobj_t *po;
|
||||
polyobj_t *oldpo;
|
||||
polywaypoint_t *th;
|
||||
mobj_t *first = NULL;
|
||||
INT32 start;
|
||||
|
||||
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
|
||||
{
|
||||
|
|
@ -2179,6 +2188,26 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
th->continuous = false;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
th->pointnum = first->health;
|
||||
|
||||
return true;
|
||||
|
|
@ -2227,6 +2256,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)))
|
||||
|
|
@ -2267,6 +2299,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)))
|
||||
|
|
@ -2338,6 +2373,9 @@ boolean 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)))
|
||||
|
|
@ -2384,6 +2422,9 @@ boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_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)))
|
||||
|
|
@ -2488,6 +2529,9 @@ boolean EV_DoPolyObjFlag(polyflagdata_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)))
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
#include "r_data.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_textures.h"
|
||||
#include "r_things.h"
|
||||
#include "r_skins.h"
|
||||
|
|
@ -3156,6 +3157,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
|
||||
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
|
||||
|
||||
R_AddMobjInterpolator(mobj);
|
||||
|
||||
return &mobj->thinker;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "p_saveg.h"
|
||||
|
||||
#include "i_time.h"
|
||||
#include "i_video.h" // for I_FinishUpdate()..
|
||||
#include "r_sky.h"
|
||||
#include "i_system.h"
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
#include "r_picformats.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"
|
||||
|
|
@ -4159,7 +4161,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
while (nowtime < endtime) \
|
||||
{ \
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic)) \
|
||||
I_Sleep(); \
|
||||
{ \
|
||||
I_Sleep(cv_sleep.value); \
|
||||
I_UpdateTime(cv_timescale.value); \
|
||||
} \
|
||||
lastwipetic = nowtime; \
|
||||
if (moviemode) \
|
||||
M_SaveFrame(); \
|
||||
|
|
@ -4296,7 +4301,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
Patch_FreeTag(PU_PATCH_ROTATED);
|
||||
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
|
||||
|
||||
R_InitializeLevelInterpolators();
|
||||
|
||||
P_InitThinkers();
|
||||
R_InitMobjInterpolators();
|
||||
P_InitCachedActions();
|
||||
|
||||
if (!fromnetsave && savedata.lives > 0)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "r_main.h"
|
||||
#include "p_maputl.h"
|
||||
#include "w_wad.h"
|
||||
#include "r_fps.h"
|
||||
#include "k_kart.h" // K_PlayerEBrake
|
||||
|
||||
pslope_t *slopelist = NULL;
|
||||
|
|
@ -241,6 +242,9 @@ static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, l
|
|||
th->type = type;
|
||||
|
||||
P_AddThinker(THINK_DYNSLOPE, &th->thinker);
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_DynSlope(&th->thinker, slope);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
36
src/p_spec.c
36
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 "r_textures.h"
|
||||
#include "m_random.h"
|
||||
#include "p_mobj.h"
|
||||
|
|
@ -5512,6 +5513,10 @@ static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline)
|
|||
floater->sector = sec;
|
||||
floater->tag = (INT16)tag;
|
||||
floater->sourceline = sourceline;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5541,6 +5546,9 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
|
|||
displace->speed = speed;
|
||||
displace->type = type;
|
||||
displace->reverse = reverse;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&displace->thinker, §ors[affectee], false);
|
||||
}
|
||||
|
||||
/** Adds a Mario block thinker, which changes the block's texture between blank
|
||||
|
|
@ -5600,6 +5608,10 @@ static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t c
|
|||
raise->flags |= RF_REVERSE;
|
||||
if (spindash)
|
||||
raise->flags |= RF_SPINDASH;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, true);
|
||||
}
|
||||
|
||||
static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic)
|
||||
|
|
@ -5625,6 +5637,10 @@ static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, b
|
|||
airbob->flags |= RF_SPINDASH;
|
||||
if (dynamic)
|
||||
airbob->flags |= RF_DYNAMIC;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a thwomp thinker.
|
||||
|
|
@ -5665,6 +5681,10 @@ static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t
|
|||
sec->ceilingdata = thwomp;
|
||||
// Start with 'resting' texture
|
||||
sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture;
|
||||
|
||||
// interpolation
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, false);
|
||||
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, true);
|
||||
}
|
||||
|
||||
/** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area.
|
||||
|
|
@ -7285,6 +7305,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(THINK_MAIN, &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;
|
||||
}
|
||||
}
|
||||
|
||||
/** Initializes the scrollers.
|
||||
|
|
|
|||
|
|
@ -171,7 +171,5 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
|
|||
P_FlashPal(thing->player, PAL_MIXUP, 10);
|
||||
}
|
||||
|
||||
P_InitAngle(thing, angle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
15
src/p_tick.c
15
src/p_tick.c
|
|
@ -261,6 +261,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
|
|||
* thinker->prev->next = thinker->next */
|
||||
(next->prev = currentthinker = thinker->prev)->next = next;
|
||||
|
||||
R_DestroyLevelInterpolators(thinker);
|
||||
Z_Free(thinker);
|
||||
}
|
||||
|
||||
|
|
@ -545,6 +546,8 @@ void P_Ticker(boolean run)
|
|||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
if (demo.recording)
|
||||
{
|
||||
G_WriteDemoExtraData();
|
||||
|
|
@ -737,6 +740,12 @@ void P_Ticker(boolean run)
|
|||
LUAh_PostThinkFrame();
|
||||
}
|
||||
|
||||
if (run)
|
||||
{
|
||||
R_UpdateLevelInterpolators();
|
||||
R_UpdateViewInterpolation();
|
||||
}
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
if (demo.playback)
|
||||
|
|
@ -770,6 +779,8 @@ void P_PreTicker(INT32 frames)
|
|||
{
|
||||
P_MapStart();
|
||||
|
||||
R_UpdateMobjInterpolators();
|
||||
|
||||
// First loop: Ensure all players' distance to the finish line are all accurate
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
|
|
@ -814,6 +825,10 @@ void P_PreTicker(INT32 frames)
|
|||
|
||||
LUAh_PostThinkFrame();
|
||||
|
||||
R_UpdateLevelInterpolators();
|
||||
R_UpdateViewInterpolation();
|
||||
R_ResetViewInterpolation(0);
|
||||
|
||||
P_MapEnd();
|
||||
|
||||
hook_defrosting--;
|
||||
|
|
|
|||
13
src/p_user.c
13
src/p_user.c
|
|
@ -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_skins.h"
|
||||
|
|
@ -1204,12 +1205,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
|
|||
}
|
||||
|
||||
// Copy interpolation data :)
|
||||
ghost->old_x = mobj->old_x;
|
||||
ghost->old_y = mobj->old_y;
|
||||
ghost->old_z = mobj->old_z;
|
||||
ghost->old_angle = (mobj->player ? mobj->player->old_drawangle : mobj->old_angle);
|
||||
ghost->old_pitch = mobj->old_pitch;
|
||||
ghost->old_roll = mobj->old_roll;
|
||||
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_drawangle2 : mobj->old_angle2);
|
||||
ghost->old_pitch = mobj->old_pitch2;
|
||||
ghost->old_roll = mobj->old_roll2;
|
||||
|
||||
return ghost;
|
||||
}
|
||||
|
|
|
|||
20
src/r_bsp.c
20
src/r_bsp.c
|
|
@ -904,6 +904,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)
|
||||
|
|
@ -930,7 +931,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);
|
||||
|
|
@ -983,7 +1000,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)
|
||||
|
|
|
|||
665
src/r_fps.c
665
src/r_fps.c
|
|
@ -20,42 +20,45 @@
|
|||
#include "r_plane.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_state.h"
|
||||
#include "z_zone.h"
|
||||
#include "console.h" // con_startup_loadprogress
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h" // for cv_glshearing
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t fpscap_cons_t[] = {
|
||||
{-1, "Match refresh rate"},
|
||||
{0, "Unlimited"},
|
||||
#ifdef DEVELOP
|
||||
// Lower values are actually pretty useful for debugging interp problems!
|
||||
{1, "One Singular Frame"},
|
||||
{10, "10"},
|
||||
{20, "20"},
|
||||
{25, "25"},
|
||||
{30, "30"},
|
||||
{1, "MIN"},
|
||||
#else
|
||||
{TICRATE, "MIN"},
|
||||
#endif
|
||||
{35, "35"},
|
||||
{50, "50"},
|
||||
{60, "60"},
|
||||
{70, "70"},
|
||||
{75, "75"},
|
||||
{90, "90"},
|
||||
{100, "100"},
|
||||
{120, "120"},
|
||||
{144, "144"},
|
||||
{200, "200"},
|
||||
{240, "240"},
|
||||
{300, "MAX"},
|
||||
{-1, "Unlimited"},
|
||||
{0, "Match refresh rate"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_fpscap = CVAR_INIT ("fpscap", "Match refresh rate", CV_SAVE, fpscap_cons_t, 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)
|
||||
{
|
||||
return I_GetRefreshRate();
|
||||
// -1: Unlimited
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cv_fpscap.value;
|
||||
|
|
@ -63,7 +66,7 @@ UINT32 R_GetFramerateCap(void)
|
|||
|
||||
boolean R_UsingFrameInterpolation(void)
|
||||
{
|
||||
return (R_GetFramerateCap() != TICRATE); // maybe use ">" instead?
|
||||
return (R_GetFramerateCap() != TICRATE || cv_timescale.value < FRACUNIT);
|
||||
}
|
||||
|
||||
static viewvars_t pview_old[MAXSPLITSCREENPLAYERS];
|
||||
|
|
@ -72,18 +75,41 @@ static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS];
|
|||
static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
static viewvars_t *oldview = &pview_old[0];
|
||||
static int oldview_invalid[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 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 FixedMul(frac, to - from);
|
||||
return from + FixedMul(frac, to - from);
|
||||
}
|
||||
|
||||
static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac)
|
||||
{
|
||||
return FixedMul(frac, to - from);
|
||||
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
|
||||
|
|
@ -129,20 +155,44 @@ void R_InterpolateViewRollAngle(fixed_t frac)
|
|||
|
||||
void R_InterpolateView(fixed_t frac)
|
||||
{
|
||||
if (frac < 0)
|
||||
viewvars_t* prevview = oldview;
|
||||
UINT8 i;
|
||||
|
||||
if (FIXED_TO_FLOAT(frac) < 0)
|
||||
frac = 0;
|
||||
#if 0
|
||||
if (frac > FRACUNIT)
|
||||
frac = FRACUNIT;
|
||||
#endif
|
||||
|
||||
viewx = oldview->x + R_LerpFixed(oldview->x, newview->x, frac);
|
||||
viewy = oldview->y + R_LerpFixed(oldview->y, newview->y, frac);
|
||||
viewz = oldview->z + R_LerpFixed(oldview->z, newview->z, frac);
|
||||
if (viewcontext == VIEWCONTEXT_SKY1 || viewcontext == VIEWCONTEXT_PLAYER1)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
else if (viewcontext == VIEWCONTEXT_SKY2 || viewcontext == VIEWCONTEXT_PLAYER2)
|
||||
{
|
||||
i = 1;
|
||||
}
|
||||
else if (viewcontext == VIEWCONTEXT_SKY3 || viewcontext == VIEWCONTEXT_PLAYER3)
|
||||
{
|
||||
i = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 3;
|
||||
}
|
||||
|
||||
viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac);
|
||||
aimingangle = oldview->aim + R_LerpAngle(oldview->aim, newview->aim, frac);
|
||||
R_InterpolateViewRollAngle(frac);
|
||||
if (oldview_invalid[i] != 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);
|
||||
viewroll = R_LerpAngle(prevview->roll, newview->roll, frac);
|
||||
|
||||
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
|
||||
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
|
||||
|
|
@ -161,6 +211,23 @@ void R_UpdateViewInterpolation(void)
|
|||
{
|
||||
pview_old[i] = pview_new[i];
|
||||
skyview_old[i] = skyview_new[i];
|
||||
if (oldview_invalid[i] > 0) oldview_invalid[i]--;
|
||||
}
|
||||
}
|
||||
|
||||
void R_ResetViewInterpolation(UINT8 p)
|
||||
{
|
||||
if (p == 0)
|
||||
{
|
||||
UINT8 i;
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
oldview_invalid[i]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldview_invalid[p - 1]++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +270,7 @@ fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
|
|||
return to;
|
||||
}
|
||||
|
||||
return (from + R_LerpFixed(from, to, rendertimefrac));
|
||||
return (R_LerpFixed(from, to, rendertimefrac));
|
||||
}
|
||||
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to)
|
||||
|
|
@ -213,5 +280,537 @@ angle_t R_InterpolateAngle(angle_t from, angle_t to)
|
|||
return to;
|
||||
}
|
||||
|
||||
return (from + R_LerpAngle(from, to, rendertimefrac));
|
||||
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->drawangle : mobj->angle;
|
||||
out->spritexscale = mobj->spritexscale;
|
||||
out->spriteyscale = mobj->spriteyscale;
|
||||
out->spritexoffset = mobj->spritexoffset;
|
||||
out->spriteyoffset = mobj->spriteyoffset;
|
||||
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->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
|
||||
out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
|
||||
|
||||
// Sprite offsets are not interpolated until we have a way to interpolate them explicitly in Lua.
|
||||
// It seems existing mods visually break more often than not if it is interpolated.
|
||||
out->spritexoffset = mobj->spritexoffset;
|
||||
out->spriteyoffset = mobj->spriteyoffset;
|
||||
|
||||
out->subsector = R_PointInSubsector(out->x, out->y);
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
out->angle = mobj->resetinterp ? mobj->player->drawangle : R_LerpAngle(mobj->player->old_drawangle, mobj->player->drawangle, 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;
|
||||
out->spritexscale = mobj->spritexscale;
|
||||
out->spriteyscale = mobj->spriteyscale;
|
||||
out->spritexoffset = mobj->spritexoffset;
|
||||
out->spriteyoffset = mobj->spriteyoffset;
|
||||
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->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
|
||||
out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
|
||||
out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
|
||||
out->spriteyoffset = R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac);
|
||||
|
||||
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_pitch2 = mobj->old_pitch;
|
||||
mobj->old_roll2 = mobj->old_roll;
|
||||
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_pitch = mobj->pitch;
|
||||
mobj->old_roll = mobj->roll;
|
||||
mobj->old_scale = mobj->scale;
|
||||
mobj->old_spritexscale = mobj->spritexscale;
|
||||
mobj->old_spriteyscale = mobj->spriteyscale;
|
||||
mobj->old_spritexoffset = mobj->spritexoffset;
|
||||
mobj->old_spriteyoffset = mobj->spriteyoffset;
|
||||
|
||||
if (mobj->player)
|
||||
{
|
||||
mobj->player->old_drawangle2 = mobj->player->old_drawangle;
|
||||
mobj->player->old_drawangle = mobj->player->drawangle;
|
||||
}
|
||||
|
||||
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_pitch2 = mobj->old_pitch;
|
||||
mobj->old_roll2 = mobj->old_roll;
|
||||
mobj->old_x = mobj->x;
|
||||
mobj->old_y = mobj->y;
|
||||
mobj->old_z = mobj->z;
|
||||
mobj->old_angle = mobj->angle;
|
||||
mobj->old_spritexscale = mobj->spritexscale;
|
||||
mobj->old_spriteyscale = mobj->spriteyscale;
|
||||
mobj->old_spritexoffset = mobj->spritexoffset;
|
||||
mobj->old_spriteyoffset = mobj->spriteyoffset;
|
||||
}
|
||||
|
|
|
|||
96
src/r_fps.h
96
src/r_fps.h
|
|
@ -54,16 +54,112 @@ typedef struct {
|
|||
|
||||
extern viewvars_t *newview;
|
||||
|
||||
typedef struct {
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
subsector_t *subsector;
|
||||
angle_t angle;
|
||||
fixed_t scale;
|
||||
fixed_t spritexscale;
|
||||
fixed_t spriteyscale;
|
||||
fixed_t spritexoffset;
|
||||
fixed_t spriteyoffset;
|
||||
} 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);
|
||||
// Special function just for software
|
||||
void R_InterpolateViewRollAngle(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(UINT8 p);
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ int r_splitscreen;
|
|||
|
||||
fixed_t rendertimefrac;
|
||||
fixed_t renderdeltatics;
|
||||
boolean renderisnewtic;
|
||||
|
||||
//
|
||||
// precalculated math tables
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ extern size_t validcount, linecount, loopcount, framecount;
|
|||
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.
|
||||
|
|
|
|||
285
src/r_things.c
285
src/r_things.c
|
|
@ -23,6 +23,7 @@
|
|||
#include "info.h" // spr2names
|
||||
#include "i_video.h" // rendermode
|
||||
#include "i_system.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_things.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_patchrotation.h"
|
||||
|
|
@ -1176,19 +1177,34 @@ static void R_SplitSprite(vissprite_t *sprite)
|
|||
// shadowslope is filled with the floor's slope, if provided
|
||||
//
|
||||
fixed_t R_GetShadowZ(
|
||||
mobj_t *thing, pslope_t **shadowslope,
|
||||
fixed_t interpx, fixed_t interpy, fixed_t interpz)
|
||||
mobj_t *thing, pslope_t **shadowslope)
|
||||
{
|
||||
fixed_t halfHeight = interpz + (thing->height >> 1);
|
||||
fixed_t halfHeight;
|
||||
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
|
||||
fixed_t floorz = P_GetFloorZ(thing, thing->subsector->sector, interpx, interpy, NULL);
|
||||
fixed_t ceilingz = P_GetCeilingZ(thing, thing->subsector->sector, interpx, interpy, NULL);
|
||||
fixed_t floorz;
|
||||
fixed_t ceilingz;
|
||||
fixed_t z, groundz = isflipped ? INT32_MAX : INT32_MIN;
|
||||
pslope_t *slope, *groundslope = NULL;
|
||||
msecnode_t *node;
|
||||
sector_t *sector;
|
||||
ffloor_t *rover;
|
||||
|
||||
// for frame interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
halfHeight = interp.z + (thing->height >> 1);
|
||||
floorz = P_GetFloorZ(thing, interp.subsector->sector, interp.x, interp.y, NULL);
|
||||
ceilingz = P_GetCeilingZ(thing, interp.subsector->sector, interp.x, interp.y, NULL);
|
||||
|
||||
#define CHECKZ (isflipped ? z > halfHeight && z < groundz : z < halfHeight && z > groundz)
|
||||
|
||||
for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
|
|
@ -1200,7 +1216,7 @@ fixed_t R_GetShadowZ(
|
|||
if (sector->heightsec != -1)
|
||||
z = isflipped ? sectors[sector->heightsec].ceilingheight : sectors[sector->heightsec].floorheight;
|
||||
else
|
||||
z = isflipped ? P_GetSectorCeilingZAt(sector, interpx, interpy) : P_GetSectorFloorZAt(sector, interpx, interpy);
|
||||
z = isflipped ? P_GetSectorCeilingZAt(sector, interp.x, interp.y) : P_GetSectorFloorZAt(sector, interp.x, interp.y);
|
||||
|
||||
if CHECKZ
|
||||
{
|
||||
|
|
@ -1214,8 +1230,7 @@ fixed_t R_GetShadowZ(
|
|||
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
|
||||
continue;
|
||||
|
||||
z = isflipped ? P_GetFFloorBottomZAt(rover, interpx, interpy) : P_GetFFloorTopZAt(rover, interpx, interpy);
|
||||
|
||||
z = isflipped ? P_GetFFloorBottomZAt(rover, interp.x, interp.y) : P_GetFFloorTopZAt(rover, interp.x, interp.y);
|
||||
if CHECKZ
|
||||
{
|
||||
groundz = z;
|
||||
|
|
@ -1231,65 +1246,6 @@ fixed_t R_GetShadowZ(
|
|||
groundslope = NULL;
|
||||
}
|
||||
|
||||
#if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
|
||||
// NOTE: this section was not updated to reflect reverse gravity support
|
||||
// Check polyobjects and see if groundz needs to be altered, for rings only because they don't update floorz
|
||||
if (thing->type == MT_RING)
|
||||
{
|
||||
INT32 xl, xh, yl, yh, bx, by;
|
||||
|
||||
xl = (unsigned)(interpx - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
xh = (unsigned)(interpx + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
|
||||
yl = (unsigned)(interpy - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
yh = (unsigned)(interpy + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
|
||||
|
||||
BMBOUNDFIX(xl, xh, yl, yh);
|
||||
|
||||
validcount++;
|
||||
|
||||
for (by = yl; by <= yh; by++)
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
{
|
||||
INT32 offset;
|
||||
polymaplink_t *plink; // haleyjd 02/22/06
|
||||
|
||||
if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight)
|
||||
continue;
|
||||
|
||||
offset = by*bmapwidth + bx;
|
||||
|
||||
// haleyjd 02/22/06: consider polyobject lines
|
||||
plink = polyblocklinks[offset];
|
||||
|
||||
while (plink)
|
||||
{
|
||||
polyobj_t *po = plink->po;
|
||||
|
||||
if (po->validcount != validcount) // if polyobj hasn't been checked
|
||||
{
|
||||
po->validcount = validcount;
|
||||
|
||||
if (!P_MobjInsidePolyobj(po, thing) || !(po->flags & POF_RENDERPLANES))
|
||||
{
|
||||
plink = (polymaplink_t *)(plink->link.next);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're inside it! Yess...
|
||||
z = po->lines[0]->backsector->ceilingheight;
|
||||
|
||||
if (z < halfHeight && z > groundz)
|
||||
{
|
||||
groundz = z;
|
||||
groundslope = NULL;
|
||||
}
|
||||
}
|
||||
plink = (polymaplink_t *)(plink->link.next);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shadowslope != NULL)
|
||||
*shadowslope = groundslope;
|
||||
|
||||
|
|
@ -1301,12 +1257,26 @@ fixed_t R_GetShadowZ(
|
|||
static void R_SkewShadowSprite(
|
||||
mobj_t *thing, pslope_t *groundslope,
|
||||
fixed_t groundz, INT32 spriteheight, fixed_t scalemul,
|
||||
fixed_t *shadowyscale, fixed_t *shadowskew,
|
||||
fixed_t interpx, fixed_t interpy)
|
||||
fixed_t *shadowyscale, fixed_t *shadowskew)
|
||||
{
|
||||
|
||||
// haha let's try some dumb stuff
|
||||
fixed_t xslope, zslope;
|
||||
angle_t sloperelang = (R_PointToAngle(interpx, interpy) - groundslope->xydirection) >> ANGLETOFINESHIFT;
|
||||
angle_t sloperelang;
|
||||
|
||||
// for frame interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
sloperelang = (R_PointToAngle(interp.x, interp.y) - groundslope->xydirection) >> ANGLETOFINESHIFT;
|
||||
|
||||
xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta);
|
||||
zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta);
|
||||
|
|
@ -1324,8 +1294,7 @@ static void R_SkewShadowSprite(
|
|||
|
||||
static void R_ProjectDropShadow(
|
||||
mobj_t *thing, vissprite_t *vis,
|
||||
fixed_t scale, fixed_t tx, fixed_t tz,
|
||||
fixed_t interpx, fixed_t interpy, fixed_t interpz)
|
||||
fixed_t scale, fixed_t tx, fixed_t tz)
|
||||
{
|
||||
vissprite_t *shadow;
|
||||
patch_t *patch;
|
||||
|
|
@ -1333,11 +1302,21 @@ static void R_ProjectDropShadow(
|
|||
INT32 light = 0;
|
||||
fixed_t groundz;
|
||||
pslope_t *groundslope;
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz);
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
|
||||
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
patch = W_CachePatchName("DSHADOW", PU_SPRITE);
|
||||
xscale = FixedDiv(projection[viewssnum], tz);
|
||||
yscale = FixedDiv(projectiony[viewssnum], tz);
|
||||
|
|
@ -1353,8 +1332,7 @@ static void R_ProjectDropShadow(
|
|||
thing,
|
||||
groundslope, groundz,
|
||||
patch->height, FRACUNIT,
|
||||
&shadowyscale, &shadowskew,
|
||||
interpx, interpy);
|
||||
&shadowyscale, &shadowskew);
|
||||
}
|
||||
|
||||
tx -= patch->width * shadowxscale/2;
|
||||
|
|
@ -1374,11 +1352,11 @@ static void R_ProjectDropShadow(
|
|||
shadow->mobjflags = 0;
|
||||
shadow->sortscale = vis->sortscale;
|
||||
shadow->dispoffset = vis->dispoffset - 5;
|
||||
shadow->gx = interpx;
|
||||
shadow->gy = interpy;
|
||||
shadow->gx = interp.x;
|
||||
shadow->gy = interp.y;
|
||||
shadow->gzt = groundz + patch->height * shadowyscale / 2;
|
||||
shadow->gz = shadow->gzt - patch->height * shadowyscale;
|
||||
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
|
||||
shadow->texturemid = FixedMul(interp.scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
|
||||
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||
shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale);
|
||||
shadow->scalestep = 0;
|
||||
|
|
@ -1391,7 +1369,7 @@ static void R_ProjectDropShadow(
|
|||
|
||||
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
|
||||
shadow->scale = FixedMul(yscale, shadowyscale);
|
||||
shadow->thingscale = thing->scale;
|
||||
shadow->thingscale = interp.scale;
|
||||
shadow->sector = vis->sector;
|
||||
shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS);
|
||||
shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS);
|
||||
|
|
@ -1419,7 +1397,7 @@ static void R_ProjectDropShadow(
|
|||
|
||||
// R_GetPlaneLight won't work on sloped lights!
|
||||
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y);
|
||||
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interp.x, interp.y);
|
||||
if (h <= shadow->gzt) {
|
||||
light = lightnum - 1;
|
||||
break;
|
||||
|
|
@ -1499,7 +1477,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
fixed_t gz = 0, gzt = 0;
|
||||
INT32 heightsec, phs;
|
||||
INT32 light = 0;
|
||||
fixed_t this_scale = thing->scale;
|
||||
fixed_t this_scale;
|
||||
fixed_t spritexscale, spriteyscale;
|
||||
|
||||
// rotsprite
|
||||
|
|
@ -1513,20 +1491,20 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
#endif
|
||||
|
||||
// uncapped/interpolation
|
||||
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
angle_t interpangle = ANGLE_MAX;
|
||||
interpmobjstate_t interp = {0};
|
||||
|
||||
if (thing->player)
|
||||
// do interpolation
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle);
|
||||
R_InterpolateMobjState(oldthing, rendertimefrac, &interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
interpangle = R_InterpolateAngle(thing->old_angle, thing->angle);
|
||||
R_InterpolateMobjState(oldthing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = interp.scale;
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
|
|
@ -1537,19 +1515,19 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
mul = -mul;
|
||||
}
|
||||
|
||||
interpx += FixedMul(thing->momx, mul);
|
||||
interpy += FixedMul(thing->momy, mul);
|
||||
interpz += FixedMul(thing->momz, mul);
|
||||
interp.x += FixedMul(thing->momx, mul);
|
||||
interp.y += FixedMul(thing->momy, mul);
|
||||
interp.z += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
// sprite offset
|
||||
interpx += thing->sprxoff;
|
||||
interpy += thing->spryoff;
|
||||
interpz += thing->sprzoff;
|
||||
interp.x += thing->sprxoff;
|
||||
interp.y += thing->spryoff;
|
||||
interp.z += thing->sprzoff;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = interpx - viewx;
|
||||
tr_y = interpy - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
basetz = tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
|
||||
|
||||
|
|
@ -1626,7 +1604,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (sprframe->rotate != SRF_SINGLE || papersprite)
|
||||
{
|
||||
ang = R_PointToAngle (interpx, interpy) - interpangle;
|
||||
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
|
||||
if (mirrored)
|
||||
ang = InvAngle(ang);
|
||||
}
|
||||
|
|
@ -1641,7 +1619,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
else
|
||||
{
|
||||
// choose a different rotation based on player view
|
||||
//ang = R_PointToAngle (interpx, interpy) - interpangle;
|
||||
//ang = R_PointToAngle (interp.x, interp.y) - interpangle;
|
||||
|
||||
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
|
||||
rot = 6; // F7 slot
|
||||
|
|
@ -1704,15 +1682,15 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
flip = !flip != !hflip;
|
||||
|
||||
// calculate edges of the shape
|
||||
spritexscale = thing->spritexscale;
|
||||
spriteyscale = thing->spriteyscale;
|
||||
spritexscale = interp.spritexscale;
|
||||
spriteyscale = interp.spriteyscale;
|
||||
if (spritexscale < 1 || spriteyscale < 1)
|
||||
return;
|
||||
|
||||
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
|
||||
{
|
||||
spr_offset = thing->spritexoffset;
|
||||
spr_topoffset = thing->spriteyoffset;
|
||||
spr_offset = interp.spritexoffset;
|
||||
spr_topoffset = interp.spriteyoffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1721,8 +1699,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if ((thing->renderflags & RF_FLIPOFFSETS) && flip)
|
||||
flipoffset = -1;
|
||||
|
||||
spr_offset += thing->spritexoffset * flipoffset;
|
||||
spr_topoffset += thing->spriteyoffset * flipoffset;
|
||||
spr_offset += interp.spritexoffset * flipoffset;
|
||||
spr_topoffset += interp.spriteyoffset * flipoffset;
|
||||
}
|
||||
|
||||
if (flip)
|
||||
|
|
@ -1744,8 +1722,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);
|
||||
|
|
@ -1761,7 +1739,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
paperoffset = -paperoffset;
|
||||
paperdistance = -paperdistance;
|
||||
}
|
||||
centerangle = viewangle - thing->angle;
|
||||
centerangle = viewangle - interp.angle;
|
||||
|
||||
tr_x += FixedMul(offset2, cosmul);
|
||||
tr_y += FixedMul(offset2, sinmul);
|
||||
|
|
@ -1853,13 +1831,19 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY)
|
||||
{
|
||||
interpmobjstate_t tracer_interp = {0};
|
||||
fixed_t linkscale;
|
||||
|
||||
thing = thing->tracer;
|
||||
|
||||
interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
if (R_UsingFrameInterpolation() && !paused)
|
||||
{
|
||||
R_InterpolateMobjState(thing, rendertimefrac, &tracer_interp);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_InterpolateMobjState(thing, FRACUNIT, &tracer_interp);
|
||||
}
|
||||
|
||||
// hitlag vibrating (todo: interp somehow?)
|
||||
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
|
||||
|
|
@ -1871,21 +1855,21 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
mul = -mul;
|
||||
}
|
||||
|
||||
interpx += FixedMul(thing->momx, mul);
|
||||
interpy += FixedMul(thing->momy, mul);
|
||||
interpz += FixedMul(thing->momz, mul);
|
||||
tracer_interp.x += FixedMul(thing->momx, mul);
|
||||
tracer_interp.y += FixedMul(thing->momy, mul);
|
||||
tracer_interp.z += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
// sprite offset
|
||||
interpx += thing->sprxoff;
|
||||
interpy += thing->spryoff;
|
||||
interpz += thing->sprzoff;
|
||||
tracer_interp.x += thing->sprxoff;
|
||||
tracer_interp.y += thing->spryoff;
|
||||
tracer_interp.z += thing->sprzoff;
|
||||
|
||||
if (! R_ThingVisible(thing))
|
||||
return;
|
||||
|
||||
tr_x = (interpx + sort_x) - viewx;
|
||||
tr_y = (interpy + sort_y) - viewy;
|
||||
tr_x = (tracer_interp.x + sort_x) - viewx;
|
||||
tr_y = (tracer_interp.y + sort_y) - viewy;
|
||||
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
|
||||
linkscale = FixedDiv(projectiony[viewssnum], tz);
|
||||
|
||||
|
|
@ -1900,8 +1884,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
else if (splat)
|
||||
{
|
||||
tr_x = (interpx + sort_x) - viewx;
|
||||
tr_y = (interpy + sort_y) - viewy;
|
||||
tr_x = (interp.x + sort_x) - viewx;
|
||||
tr_y = (interp.y + sort_y) - viewy;
|
||||
sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
|
||||
sortscale = FixedDiv(projectiony[viewssnum], sort_z);
|
||||
}
|
||||
|
|
@ -1909,8 +1893,8 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
// Calculate the splat's sortscale
|
||||
if (splat)
|
||||
{
|
||||
tr_x = (thing->x - sort_x) - viewx;
|
||||
tr_y = (thing->y - sort_y) - viewy;
|
||||
tr_x = (interp.x - sort_x) - viewx;
|
||||
tr_y = (interp.y - sort_y) - viewy;
|
||||
sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
|
||||
sortsplat = FixedDiv(projectiony[viewssnum], sort_z);
|
||||
}
|
||||
|
|
@ -1921,7 +1905,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 >= portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(interpx, interpy, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1949,7 +1933,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (shadowdraw || shadoweffects)
|
||||
{
|
||||
fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz);
|
||||
fixed_t groundz = R_GetShadowZ(thing, NULL);
|
||||
boolean isflipped = (thing->eflags & MFE_VERTICALFLIP);
|
||||
|
||||
if (shadoweffects)
|
||||
|
|
@ -1973,9 +1957,9 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (shadowskew)
|
||||
{
|
||||
R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan, interpx, interpy);
|
||||
R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan);
|
||||
|
||||
gzt = (isflipped ? (thing->z + thing->height) : thing->z) + patch->height * spriteyscale / 2;
|
||||
gzt = (isflipped ? (interp.z + thing->height) : interp.z) + patch->height * spriteyscale / 2;
|
||||
gz = gzt - patch->height * spriteyscale;
|
||||
|
||||
cut |= SC_SHEAR;
|
||||
|
|
@ -1990,12 +1974,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 = interpz + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
|
||||
gz = interp.z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
|
||||
gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale));
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = interpz + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
|
||||
gzt = interp.z + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
|
||||
gz = gzt - FixedMul(spr_height, FixedMul(spriteyscale, this_scale));
|
||||
}
|
||||
}
|
||||
|
|
@ -2014,7 +1998,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
// R_GetPlaneLight won't work on sloped lights!
|
||||
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
|
||||
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interpx, interpy);
|
||||
fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interp.x, interp.y);
|
||||
if (h <= top) {
|
||||
light = lightnum - 1;
|
||||
break;
|
||||
|
|
@ -2040,12 +2024,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
|
||||
{
|
||||
if (viewz < sectors[phs].floorheight ?
|
||||
interpz >= sectors[heightsec].floorheight :
|
||||
interp.z >= sectors[heightsec].floorheight :
|
||||
gzt < sectors[heightsec].floorheight)
|
||||
return;
|
||||
if (viewz > sectors[phs].ceilingheight ?
|
||||
gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
|
||||
interpz >= sectors[heightsec].ceilingheight)
|
||||
interp.z >= sectors[heightsec].ceilingheight)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2058,12 +2042,12 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->sortscale = sortscale;
|
||||
vis->sortsplat = sortsplat;
|
||||
vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15
|
||||
vis->gx = interpx;
|
||||
vis->gy = interpy;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = thing->height;
|
||||
vis->pz = interpz;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = FixedDiv(gzt - viewz, spriteyscale);
|
||||
vis->scalestep = scalestep;
|
||||
|
|
@ -2094,7 +2078,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000
|
||||
vis->scale = FixedMul(spriteyscale, yscale); //<<detailshift;
|
||||
vis->thingscale = oldthing->scale;
|
||||
vis->thingscale = interp.scale;
|
||||
|
||||
vis->spritexscale = spritexscale;
|
||||
vis->spriteyscale = spriteyscale;
|
||||
|
|
@ -2176,8 +2160,7 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
|
||||
if (oldthing->shadowscale && cv_shadow.value)
|
||||
{
|
||||
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz,
|
||||
interpx, interpy, interpz);
|
||||
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz);
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
|
@ -2204,13 +2187,21 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
fixed_t gz, gzt;
|
||||
|
||||
// uncapped/interpolation
|
||||
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
|
||||
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
|
||||
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
|
||||
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 = interpx - viewx;
|
||||
tr_y = interpy - viewy;
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
||||
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
|
||||
|
||||
|
|
@ -2274,12 +2265,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
if (x2 < portalclipstart || x1 >= portalclipend)
|
||||
return;
|
||||
|
||||
if (P_PointOnLineSide(interpx, interpy, portalclipline) != 0)
|
||||
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
//SoM: 3/17/2000: Disregard sprites that are out of view..
|
||||
gzt = interpz + spritecachedinfo[lump].topoffset;
|
||||
gzt = interp.z + spritecachedinfo[lump].topoffset;
|
||||
gz = gzt - spritecachedinfo[lump].height;
|
||||
|
||||
if (thing->subsector->sector->cullheight)
|
||||
|
|
@ -2292,12 +2283,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 = interpx;
|
||||
vis->gy = interpy;
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = 4*FRACUNIT;
|
||||
vis->pz = interpz;
|
||||
vis->pz = interp.z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = 0;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap);
|
|||
extern INT16 negonearray[MAXVIDWIDTH];
|
||||
extern INT16 screenheightarray[MAXVIDWIDTH];
|
||||
|
||||
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope, fixed_t interpx, fixed_t interpy, fixed_t interpz);
|
||||
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
|
||||
|
||||
//SoM: 6/5/2000: Light sprites correctly!
|
||||
void R_AddSprites(sector_t *sec, INT32 lightlevel);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -549,12 +550,12 @@ void SCR_CalculateFPS(void)
|
|||
return;
|
||||
}
|
||||
|
||||
updateElapsed = I_PreciseToMicros(endTime - updateTime);
|
||||
updateElapsed = (endTime - updateTime) / (I_GetPrecisePrecision() / 1000000);
|
||||
|
||||
if (updateElapsed >= FPS_SAMPLE_RATE)
|
||||
{
|
||||
static int sampleIndex = 0;
|
||||
int frameElapsed = I_PreciseToMicros(endTime - startTime);
|
||||
int frameElapsed = (endTime - startTime) / (I_GetPrecisePrecision() / 1000000);
|
||||
|
||||
fps_samples[sampleIndex] = frameElapsed / 1000.0f;
|
||||
|
||||
|
|
@ -581,7 +582,7 @@ void SCR_DisplayTicRate(void)
|
|||
UINT32 cap = R_GetFramerateCap();
|
||||
UINT32 benchmark = (cap == 0) ? I_GetRefreshRate() : cap;
|
||||
INT32 x = 318;
|
||||
double fps = ceil(averageFPS);
|
||||
double fps = round(averageFPS);
|
||||
|
||||
// draw "FPS"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ extern consvar_t cv_vhseffect, cv_shittyscreen;
|
|||
|
||||
// wait for page flipping to end or not
|
||||
extern consvar_t cv_vidwait;
|
||||
extern consvar_t cv_timescale;
|
||||
|
||||
// Initialize the screen
|
||||
void SCR_Startup(void);
|
||||
|
|
|
|||
|
|
@ -165,6 +165,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"
|
||||
|
|
@ -1641,115 +1642,78 @@ ticcmd_t *I_BaseTiccmd4(void)
|
|||
|
||||
static Uint64 timer_frequency;
|
||||
|
||||
static double tic_frequency;
|
||||
static Uint64 tic_epoch;
|
||||
static double elapsed_tics;
|
||||
|
||||
static void UpdateElapsedTics(void)
|
||||
{
|
||||
const Uint64 now = SDL_GetPerformanceCounter();
|
||||
|
||||
elapsed_tics += (now - tic_epoch) / tic_frequency;
|
||||
tic_epoch = now; // moving epoch
|
||||
}
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
double f = 0.0;
|
||||
UpdateElapsedTics();
|
||||
f = floor(elapsed_tics);
|
||||
return (tic_t)f;
|
||||
}
|
||||
|
||||
float I_GetTimeFrac(void)
|
||||
{
|
||||
UpdateElapsedTics();
|
||||
return elapsed_tics;
|
||||
}
|
||||
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
return SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
int I_PreciseToMicros(precise_t d)
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
// d is going to be converted into a double. So remove the highest bits
|
||||
// to avoid loss of precision in the lower bits, for the (probably rare) case
|
||||
// that the higher bits are actually used.
|
||||
d &= ((precise_t)1 << 53) - 1; // The mantissa of a double can handle 53 bits at most.
|
||||
// The resulting double from the calculation is converted first to UINT64 to avoid overflow,
|
||||
// which is undefined behaviour when converting floating point values to integers.
|
||||
return (int)(UINT64)(d / (timer_frequency / 1000000.0));
|
||||
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)
|
||||
{
|
||||
// Shouldn't be used, but just in case...?
|
||||
frame_frequency = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
frame_frequency = timer_frequency / (double)frame_rate;
|
||||
}
|
||||
|
||||
double I_GetFrameTime(void)
|
||||
{
|
||||
const UINT64 now = SDL_GetPerformanceCounter();
|
||||
const UINT32 cap = R_GetFramerateCap();
|
||||
|
||||
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
|
||||
{
|
||||
elapsed_frames += (now - frame_epoch) / frame_frequency;
|
||||
}
|
||||
|
||||
frame_epoch = now; // moving epoch
|
||||
return elapsed_frames;
|
||||
}
|
||||
|
||||
//
|
||||
//I_StartupTimer
|
||||
// I_StartupTimer
|
||||
//
|
||||
void I_StartupTimer(void)
|
||||
{
|
||||
timer_frequency = SDL_GetPerformanceFrequency();
|
||||
tic_epoch = SDL_GetPerformanceCounter();
|
||||
|
||||
tic_frequency = timer_frequency / (double)NEWTICRATE;
|
||||
elapsed_tics = 0.0;
|
||||
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);
|
||||
}
|
||||
|
||||
boolean I_CheckFrameCap(precise_t start, precise_t end)
|
||||
{
|
||||
UINT32 capFrames = R_GetFramerateCap();
|
||||
int capMicros = 0;
|
||||
|
||||
int elapsed;
|
||||
|
||||
if (capFrames == 0)
|
||||
{
|
||||
// We don't want to cap.
|
||||
return false;
|
||||
}
|
||||
|
||||
elapsed = I_PreciseToMicros(end - start);
|
||||
capMicros = 1000000 / capFrames;
|
||||
|
||||
if (elapsed < capMicros)
|
||||
{
|
||||
// Wait to draw the next frame.
|
||||
UINT32 wait = ((capMicros - elapsed) / 1000);
|
||||
|
||||
if (cv_sleep.value > 1)
|
||||
{
|
||||
// 1 is the default, and in non-interpolated mode is just the bare minimum wait.
|
||||
// Since we're already adding some wait with an FPS cap, only apply when it's above 1.
|
||||
wait += cv_sleep.value - 1;
|
||||
}
|
||||
|
||||
// If the wait's greater than our granularity value,
|
||||
// we'll just burn the couple extra cycles in the main loop
|
||||
// in order to get to the next frame.
|
||||
// This makes us get to the exact FPS cap more often.
|
||||
|
||||
// Higher values have more wasted CPU cycles, but the in-game frame performance is better.
|
||||
// 10ms is the average clock tick of most OS scheduling.
|
||||
// 15ms is a little more than that, for leniency on slow machines. (This helps mine reach a stable 60, at least!)
|
||||
// (https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdldelay.html)
|
||||
#define DELAY_GRANULARITY 15
|
||||
if (wait >= DELAY_GRANULARITY)
|
||||
{
|
||||
SDL_Delay(wait);
|
||||
}
|
||||
#undef DELAY_GRANULARITY
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Waited enough to draw again.
|
||||
return false;
|
||||
SDL_Delay(ms);
|
||||
}
|
||||
|
||||
#ifdef NEWSIGNALHANDLER
|
||||
|
|
|
|||
|
|
@ -1293,7 +1293,7 @@ void I_FinishUpdate(void)
|
|||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
//SCR_CalculateFPS(); // Moved to main loop
|
||||
SCR_CalculateFPS();
|
||||
|
||||
if (I_SkipFrame())
|
||||
return;
|
||||
|
|
@ -1710,6 +1710,27 @@ boolean VID_CheckRenderer(void)
|
|||
return rendererchanged;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
INT32 VID_SetMode(INT32 modeNum)
|
||||
{
|
||||
SDLdoUngrabMouse();
|
||||
|
|
@ -1729,6 +1750,8 @@ INT32 VID_SetMode(INT32 modeNum)
|
|||
src_rect.w = vid.width;
|
||||
src_rect.h = vid.height;
|
||||
|
||||
refresh_rate = VID_GetRefreshRate();
|
||||
|
||||
//Impl_SetWindowName("SRB2Kart "VERSIONSTRING);
|
||||
VID_CheckRenderer();
|
||||
return SDL_TRUE;
|
||||
|
|
@ -2074,20 +2097,10 @@ void I_ShutdownGraphics(void)
|
|||
|
||||
UINT32 I_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_GetDesktopDisplayMode(index, &m) != 0)
|
||||
{
|
||||
// Error has occurred.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m.refresh_rate;
|
||||
// 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "hardware/hw_main.h"
|
||||
#endif
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hud.h"
|
||||
|
||||
// SRB2Kart
|
||||
|
|
@ -51,6 +52,8 @@
|
|||
#include "v_video.h"
|
||||
#include "r_skins.h" // NUMFACES
|
||||
|
||||
#include "r_fps.h"
|
||||
|
||||
UINT16 objectsdrawn = 0;
|
||||
|
||||
//
|
||||
|
|
@ -175,6 +178,9 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
|
|||
{ 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS
|
||||
};
|
||||
|
||||
static huddrawlist_h luahuddrawlist_game;
|
||||
static huddrawlist_h luahuddrawlist_titlecard;
|
||||
|
||||
//
|
||||
// STATUS BAR CODE
|
||||
//
|
||||
|
|
@ -448,6 +454,9 @@ void ST_Init(void)
|
|||
return;
|
||||
|
||||
ST_LoadGraphics();
|
||||
|
||||
luahuddrawlist_game = LUA_HUD_CreateDrawList();
|
||||
luahuddrawlist_titlecard = LUA_HUD_CreateDrawList();
|
||||
}
|
||||
|
||||
// change the status bar too, when pressing F12 while viewing a demo.
|
||||
|
|
@ -1166,8 +1175,12 @@ void ST_drawTitleCard(void)
|
|||
lt_lasttic = lt_ticker;
|
||||
|
||||
luahook:
|
||||
LUAh_TitleCardHUD(stplyr);
|
||||
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_titlecard);
|
||||
LUAh_TitleCardHUD(stplyr, luahuddrawlist_titlecard);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_titlecard);
|
||||
}
|
||||
|
||||
// Clear defined coordinates, we don't need them anymore
|
||||
|
|
@ -1236,7 +1249,14 @@ static void ST_overlayDrawer(void)
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!hu_showscores && netgame && !mapreset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#include "r_textures.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_picformats.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "md5.h"
|
||||
#include "lua_script.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"
|
||||
|
|
@ -262,15 +263,25 @@ tic_t I_GetTime(void)
|
|||
return newtics;
|
||||
}
|
||||
|
||||
fixed_t I_GetTimeFrac(void)
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
void I_Sleep(void)
|
||||
UINT64 I_GetPrecisePrecision(void)
|
||||
{
|
||||
if (cv_sleep.value > 0)
|
||||
Sleep(cv_sleep.value);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "lua_hook.h" // IntermissionThinker hook
|
||||
|
||||
#include "lua_hud.h"
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
|
||||
#include "m_random.h" // M_RandomKey
|
||||
#include "g_input.h" // PlayerInputDown
|
||||
|
|
@ -113,7 +114,10 @@ static INT32 sorttic = -1;
|
|||
intertype_t intertype = int_none;
|
||||
intertype_t intermissiontypes[NUMGAMETYPES];
|
||||
|
||||
static huddrawlist_h luahuddrawlist_intermission;
|
||||
|
||||
static void Y_FollowIntermission(void);
|
||||
|
||||
static void Y_RescaleScreenBuffer(void);
|
||||
static void Y_UnloadData(void);
|
||||
|
||||
|
|
@ -472,7 +476,13 @@ void Y_IntermissionDrawer(void)
|
|||
else if (bgtile)
|
||||
V_DrawPatchFill(bgtile);
|
||||
|
||||
LUAh_IntermissionHUD();
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_intermission);
|
||||
LUAh_IntermissionHUD(luahuddrawlist_intermission);
|
||||
}
|
||||
LUA_HUD_DrawList(luahuddrawlist_intermission);
|
||||
|
||||
if (!LUA_HudEnabled(hud_intermissiontally))
|
||||
goto skiptallydrawer;
|
||||
|
||||
|
|
@ -1133,6 +1143,9 @@ void Y_StartIntermission(void)
|
|||
break;
|
||||
}
|
||||
|
||||
LUA_HUD_DestroyDrawList(luahuddrawlist_intermission);
|
||||
luahuddrawlist_intermission = LUA_HUD_CreateDrawList();
|
||||
|
||||
if (powertype != PWRLV_DISABLED)
|
||||
{
|
||||
K_UpdatePowerLevels();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue