Merge branch 'uncapped-next' into 'next'

Uncapped

See merge request KartKrew/Kart-Public!276
This commit is contained in:
Sal 2022-05-22 01:28:01 +00:00
commit d0addde847
69 changed files with 3034 additions and 711 deletions

View file

@ -81,6 +81,7 @@ set(SRB2_CORE_HEADERS
i_sound.h
i_system.h
i_tcp.h
i_time.h
i_video.h
info.h
keys.h
@ -118,6 +119,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_bsp.c
r_data.c
r_draw.c
r_fps.c
r_main.c
r_plane.c
r_segs.c
@ -129,6 +131,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_data.h
r_defs.h
r_draw.h
r_fps.h
r_local.h
r_main.h
r_plane.h
@ -158,6 +161,7 @@ set(SRB2_CORE_GAME_SOURCES
p_tick.c
p_user.c
k_kart.c
i_time.c
p_local.h
p_maputl.h
@ -248,6 +252,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
lua_consolelib.c
lua_hooklib.c
lua_hudlib.c
lua_hudlib_drawlist.c
lua_infolib.c
lua_maplib.c
lua_mathlib.c
@ -260,6 +265,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
set(SRB2_LUA_HEADERS
lua_hook.h
lua_hud.h
lua_hudlib_drawlist.h
lua_libs.h
lua_script.h
)

View file

@ -587,6 +587,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_bsp.o \
$(OBJDIR)/r_data.o \
$(OBJDIR)/r_draw.o \
$(OBJDIR)/r_fps.o \
$(OBJDIR)/r_main.o \
$(OBJDIR)/r_plane.o \
$(OBJDIR)/r_segs.o \
@ -602,6 +603,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/mserv.o \
$(OBJDIR)/http-mserv.o\
$(OBJDIR)/i_tcp.o \
$(OBJDIR)/i_time.o \
$(OBJDIR)/lzf.o \
$(OBJDIR)/vid_copy.o \
$(OBJDIR)/b_bot.o \

View file

@ -82,13 +82,17 @@ INT64 current_time_in_ps() {
return (t.tv_sec * (INT64)1000000) + t.tv_usec;
}
tic_t I_GetTime(void)
void I_Sleep(UINT32 ms){}
precise_t I_GetPreciseTime(void)
{
INT64 since_start = current_time_in_ps() - start_time;
return (since_start*TICRATE)/1000000;
return 0;
}
void I_Sleep(void){}
UINT64 I_GetPrecisePrecision(void)
{
return 1000000;
}
void I_GetEvent(void){}

View file

@ -270,8 +270,8 @@ void B_RespawnBot(INT32 playernum)
player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots];
player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
P_TeleportMove(tails, x, y, z);
P_SetOrigin(tails, x, y, z);
P_SetPlayerMobjState(tails, S_KART_STND1); // SRB2kart - was S_PLAY_FALL1
P_SetScale(tails, sonic->scale);
tails->destscale = sonic->destscale;
tails->destscale = tails->old_scale = sonic->destscale;
}

View file

@ -50,4 +50,5 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/lua_hudlib.o
$(OBJDIR)/lua_hudlib.o \
$(OBJDIR)/lua_hudlib_drawlist.o

View file

@ -1231,7 +1231,7 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
// search for other
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (!stricmp(var->PossibleValue[i].strvalue, valstr))
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
@ -1616,6 +1616,9 @@ void CV_AddValue(consvar_t *var, INT32 increment)
{
INT32 newvalue, max;
if (!increment)
return;
// count pointlimit better
/*if (var == &cv_pointlimit && (gametype == GT_MATCH))
increment *= 50;*/
@ -1628,7 +1631,6 @@ void CV_AddValue(consvar_t *var, INT32 increment)
// Special case for the nextmap variable, used only directly from the menu
INT32 oldvalue = var->value - 1, gt;
gt = cv_newgametype.value;
if (increment != 0) // Going up!
{
newvalue = var->value - 1;
do
@ -1670,21 +1672,35 @@ void CV_AddValue(consvar_t *var, INT32 increment)
{
INT32 currentindice = -1, newindice;
for (max = MAXVAL+1; var->PossibleValue[max].strvalue; max++)
if (var->PossibleValue[max].value == var->value)
currentindice = max;
if (currentindice == -1 && max != MAXVAL+1)
newindice = ((increment > 0) ? MAXVAL : max) + increment;
else
newindice = currentindice + increment;
if (newindice >= max || newindice <= MAXVAL)
{
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
CV_SetValue(var, newvalue);
if (var->PossibleValue[max].value == newvalue)
{
increment = 0;
currentindice = max;
break; // The value we definitely want, stop here.
}
else if (var->PossibleValue[max].value == var->value)
currentindice = max; // The value we maybe want.
}
if (increment)
{
increment = (increment > 0) ? 1 : -1;
if (currentindice == -1 && max != MAXVAL+1)
newindice = ((increment > 0) ? MAXVAL : max) + increment;
else
newindice = currentindice + increment;
if (newindice >= max || newindice <= MAXVAL)
{
newvalue = var->PossibleValue[((increment > 0) ? MINVAL : MAXVAL)].value;
CV_SetValue(var, newvalue);
}
else
CV_Set(var, var->PossibleValue[newindice].strvalue);
}
else
CV_Set(var, var->PossibleValue[newindice].strvalue);
CV_Set(var, var->PossibleValue[currentindice].strvalue);
}
else
CV_SetValue(var, newvalue);

View file

@ -17,6 +17,7 @@
#include <unistd.h> //for unlink
#endif
#include "i_time.h"
#include "i_net.h"
#include "i_system.h"
#include "i_video.h"
@ -2502,7 +2503,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
#endif
}
else
I_Sleep();
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
return true;
}
@ -4014,10 +4018,6 @@ boolean SV_SpawnServer(void)
if (netgame && I_NetOpenSocket)
{
I_NetOpenSocket();
#ifdef MASTERSERVER
if (cv_advertise.value)
RegisterServer();
#endif
}
// non dedicated server just connect to itself
@ -5540,8 +5540,10 @@ static void SV_Maketic(void)
maketic++;
}
void TryRunTics(tic_t realtics)
boolean TryRunTics(tic_t realtics)
{
boolean ticking;
// the machine has lagged but it is not so bad
if (realtics > TICRATE/7) // FIXME: consistency failure!!
{
@ -5593,10 +5595,12 @@ void TryRunTics(tic_t realtics)
if (player_joining)
{
hu_stopped = true;
return;
return false;
}
if (neededtic > gametic)
ticking = neededtic > gametic;
if (ticking)
{
if (advancedemo)
D_StartTitle();
@ -5620,6 +5624,8 @@ void TryRunTics(tic_t realtics)
{
hu_stopped = true;
}
return ticking;
}

View file

@ -595,7 +595,7 @@ boolean Playing(void);
void D_QuitNetGame(void);
//? How many ticks to run?
void TryRunTics(tic_t realtic);
boolean TryRunTics(tic_t realtic);
// extra data for lmps
// these functions scare me. they contain magic.

View file

@ -50,6 +50,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "hu_stuff.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_time.h"
#include "i_threads.h"
#include "i_video.h"
#include "m_argv.h"
@ -73,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "dehacked.h" // Dehacked list test
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "r_fps.h" // Frame interpolation/uncapped
#include "keys.h"
#include "filesrch.h" // refreshdirmenu
@ -430,6 +432,8 @@ static void D_Display(void)
// draw the view directly
if (cv_renderview.value && !automapactive)
{
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
for (i = 0; i <= splitscreen; i++)
{
if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
@ -502,6 +506,8 @@ static void D_Display(void)
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
}
}
R_RestoreLevelInterpolators();
}
if (lastdraw)
@ -619,7 +625,12 @@ tic_t rendergametic;
void D_SRB2Loop(void)
{
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
tic_t entertic = 0, oldentertics = 0, realtics = 0, rendertimeout = INFTICS;
double deltatics = 0.0;
double deltasecs = 0.0;
boolean interp = false;
boolean doDisplay = false;
if (dedicated)
server = true;
@ -631,6 +642,7 @@ void D_SRB2Loop(void)
I_DoStartupMouse();
#endif
I_UpdateTime(cv_timescale.value);
oldentertics = I_GetTime();
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
@ -657,6 +669,19 @@ void D_SRB2Loop(void)
for (;;)
{
// capbudget is the minimum precise_t duration of a single loop iteration
precise_t capbudget;
precise_t enterprecise = I_GetPreciseTime();
precise_t finishprecise = enterprecise;
{
// Casting the return value of a function is bad practice (apparently)
double budget = round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision());
capbudget = (precise_t) budget;
}
I_UpdateTime(cv_timescale.value);
if (lastwipetic)
{
oldentertics = lastwipetic;
@ -668,7 +693,11 @@ void D_SRB2Loop(void)
realtics = entertic - oldentertics;
oldentertics = entertic;
refreshdirmenu = 0; // not sure where to put this, here as good as any?
if (demo.playback && gamestate == GS_LEVEL)
{
// Nicer place to put this.
realtics = realtics * cv_playbackspeed.value;
}
#ifdef DEBUGFILE
if (!realtics)
@ -676,47 +705,74 @@ void D_SRB2Loop(void)
debugload--;
#endif
if (!realtics && !singletics)
{
I_Sleep();
continue;
}
interp = R_UsingFrameInterpolation() && !dedicated;
doDisplay = false;
#ifdef HW3SOUND
HW3S_BeginFrameUpdate();
#endif
// don't skip more than 10 frames at a time
// (fadein / fadeout cause massive frame skip!)
if (realtics > 8)
realtics = 1;
refreshdirmenu = 0; // not sure where to put this, here as good as any?
// process tics (but maybe not if realtic == 0)
TryRunTics(realtics);
if (lastdraw || singletics || gametic > rendergametic)
if (realtics > 0 || singletics)
{
rendergametic = gametic;
rendertimeout = entertic+TICRATE/17;
// don't skip more than 10 frames at a time
// (fadein / fadeout cause massive frame skip!)
if (realtics > 8)
realtics = 1;
// Update display, next frame, with current state.
D_Display();
// process tics (but maybe not if realtic == 0)
TryRunTics(realtics);
if (moviemode)
M_SaveFrame();
if (takescreenshot) // Only take screenshots after drawing.
M_DoScreenShot();
if (lastdraw || singletics || gametic > rendergametic)
{
rendergametic = gametic;
rendertimeout = entertic + TICRATE/17;
doDisplay = true;
}
else if (rendertimeout < entertic) // in case the server hang or netsplit
{
doDisplay = true;
}
renderisnewtic = true;
}
else if (rendertimeout < entertic) // in case the server hang or netsplit
else
{
renderisnewtic = false;
}
if (interp)
{
renderdeltatics = FLOAT_TO_FIXED(deltatics);
if (!(paused || P_AutoPause()) && !hu_stopped)
{
rendertimefrac = g_time.timefrac;
}
else
{
rendertimefrac = FRACUNIT;
}
}
else
{
renderdeltatics = realtics * FRACUNIT;
rendertimefrac = FRACUNIT;
}
if (interp || doDisplay)
{
D_Display();
if (moviemode)
M_SaveFrame();
if (takescreenshot) // Only take screenshots after drawing.
M_DoScreenShot();
}
// Only take screenshots after drawing.
if (moviemode)
M_SaveFrame();
if (takescreenshot)
M_DoScreenShot();
// consoleplayer -> displayplayers (hear sounds from viewpoint)
S_UpdateSounds(); // move positional sounds
@ -737,6 +793,21 @@ void D_SRB2Loop(void)
Discord_RunCallbacks();
}
#endif
// 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;
}
}
@ -1189,8 +1260,8 @@ void D_SRB2Main(void)
//---------------------------------------------------- READY TIME
// we need to check for dedicated before initialization of some subsystems
CONS_Printf("I_StartupTimer()...\n");
I_StartupTimer();
CONS_Printf("I_InitializeTime()...\n");
I_InitializeTime();
// Make backups of some SOCcable tables.
P_BackupTables();
@ -1520,6 +1591,8 @@ void D_SRB2Main(void)
// as having been modified for the first game.
M_PushSpecialParameters(); // push all "+" parameter at the command buffer
COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin)
strncpy(connectedservername, cv_servername.string, MAXSERVERNAME);
if (M_CheckParm("-gametype") && M_IsNextParm())

View file

@ -18,6 +18,7 @@
#include "doomdef.h"
#include "g_game.h"
#include "i_time.h"
#include "i_net.h"
#include "i_system.h"
#include "m_argv.h"
@ -614,7 +615,10 @@ void Net_WaitAllAckReceived(UINT32 timeout)
while (timeout > I_GetTime() && !Net_AllAcksReceived())
{
while (tictac == I_GetTime())
I_Sleep();
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
tictac = I_GetTime();
HGetPacket();
Net_AckTicker();

View file

@ -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"
@ -2445,7 +2446,6 @@ void D_PickVote(void)
SINT8 templevels[MAXPLAYERS];
SINT8 votecompare = -1;
UINT8 numvotes = 0, key = 0;
boolean force = true;
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
@ -2459,8 +2459,6 @@ void D_PickVote(void)
numvotes++;
if (votecompare == -1)
votecompare = votes[i];
else if (votes[i] != votecompare)
force = false;
}
}

View file

@ -50,6 +50,7 @@
#include "doomstat.h"
#include "d_main.h"
#include "g_game.h"
#include "i_time.h"
#include "i_net.h"
#include "i_system.h"
#include "m_argv.h"

View file

@ -388,6 +388,7 @@ typedef struct player_s
// SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles
angle_t old_frameangle, old_frameangle2;
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right

View file

@ -405,4 +405,6 @@ typedef UINT32 tic_t;
#define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24)
#endif
typedef UINT64 precise_t;
#endif //__DOOMTYPE__

View file

@ -11,12 +11,15 @@ UINT32 I_GetFreeMem(UINT32 *total)
return 0;
}
tic_t I_GetTime(void)
{
void I_Sleep(UINT32 ms){}
precise_t I_GetPreciseTime(void) {
return 0;
}
void I_Sleep(void){}
UINT64 I_GetPrecisePrecision(void) {
return 1000000;
}
void I_GetEvent(void){}

View file

@ -19,6 +19,7 @@
#include "hu_stuff.h"
#include "r_local.h"
#include "s_sound.h"
#include "i_time.h"
#include "i_video.h"
#include "v_video.h"
#include "w_wad.h"
@ -77,7 +78,6 @@ static INT32 cutscene_textcount = 0;
static INT32 cutscene_textspeed = 0;
static UINT8 cutscene_boostspeed = 0;
static tic_t cutscene_lasttextwrite = 0;
//
// This alters the text string cutscene_disptext.
// Use the typical string drawing functions to display it.
@ -249,9 +249,9 @@ void F_StartIntro(void)
}
//
// F_IntroDrawScene
// F_IntroDrawer
//
static void F_IntroDrawScene(void)
void F_IntroDrawer(void)
{
boolean highres = false;
INT32 cx = 8, cy = 128;
@ -261,16 +261,6 @@ static void F_IntroDrawScene(void)
// DRAW A FULL PIC INSTEAD OF FLAT!
if (intro_scenenum == 0)
{
if (finalecount == 8)
S_StartSound(NULL, sfx_vroom);
else if (finalecount == 47)
{
// Need to use M_Random otherwise it always uses the same sound
INT32 rskin = M_RandomKey(numskins);
UINT8 rtaunt = M_RandomKey(2);
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
S_StartSound(NULL, rsound);
}
background = W_CachePatchName("KARTKREW", PU_CACHE);
highres = true;
}
@ -293,64 +283,6 @@ static void F_IntroDrawScene(void)
V_DrawString(cx, cy, 0, cutscene_disptext);
}
//
// F_IntroDrawer
//
void F_IntroDrawer(void)
{
if (timetonext <= 0)
{
if (intro_scenenum == 0)
{
if (rendermode != render_none)
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
F_WipeEndScreen();
F_RunWipe(99,true);
}
// Stay on black for a bit. =)
{
tic_t quittime;
quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds
while (quittime > I_GetTime())
{
I_OsPolling();
I_UpdateNoBlit();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
}
}
D_StartTitle();
// Yes, this is a weird hack, we need to force a wipe for this because the game state has changed in the middle of where it would normally wipe
// Need to set the wipe start and then draw the first frame of the title screen to get it working
F_WipeStartScreen();
F_TitleScreenDrawer();
wipegamestate = -1; // force a wipe
return;
}
F_NewCutscene(introtext[++intro_scenenum]);
timetonext = introscenetime[intro_scenenum];
F_WipeStartScreen();
wipegamestate = -1;
animtimer = stoptimer = 0;
}
intro_curtime = introscenetime[intro_scenenum] - timetonext;
F_IntroDrawScene();
}
//
// F_IntroTicker
//
@ -364,6 +296,20 @@ void F_IntroTicker(void)
timetonext--;
if (intro_scenenum == 0)
{
if (finalecount == 8)
S_StartSound(NULL, sfx_vroom);
else if (finalecount == 47)
{
// Need to use M_Random otherwise it always uses the same sound
INT32 rskin = M_RandomKey(numskins);
UINT8 rtaunt = M_RandomKey(2);
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
S_StartSound(NULL, rsound);
}
}
F_WriteText();
// check for skipping
@ -1318,6 +1264,22 @@ static boolean runningprecutscene = false, precutresetplayer = false;
static void F_AdvanceToNextScene(void)
{
if (rendermode != render_none)
{
F_WipeStartScreen();
// Fade to any palette color you want.
if (cutscenes[cutnum]->scene[scenenum].fadecolor)
{
V_DrawFill(0,0,BASEVIDWIDTH,BASEVIDHEIGHT,cutscenes[cutnum]->scene[scenenum].fadecolor);
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeinid, true);
F_WipeStartScreen();
}
}
// Don't increment until after endcutscene check
// (possible overflow / bad patch names from the one tic drawn before the fade)
if (scenenum+1 >= cutscenes[cutnum]->numscenes)
@ -1325,6 +1287,7 @@ static void F_AdvanceToNextScene(void)
F_EndCutScene();
return;
}
++scenenum;
timetonext = 0;
@ -1340,7 +1303,6 @@ static void F_AdvanceToNextScene(void)
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
// Fade to the next
dofadenow = true;
F_NewCutscene(cutscenes[cutnum]->scene[scenenum].text);
picnum = 0;
@ -1350,6 +1312,14 @@ static void F_AdvanceToNextScene(void)
textypos = cutscenes[cutnum]->scene[scenenum].textypos;
animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum];
if (rendermode != render_none)
{
F_CutsceneDrawer();
F_WipeEndScreen();
F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true);
}
}
void F_EndCutScene(void)
@ -1468,8 +1438,6 @@ void F_CutsceneTicker(void)
finalecount++;
cutscene_boostspeed = 0;
dofadenow = false;
for (i = 0; i < MAXPLAYERS; i++)
{
if (netgame && i != serverplayer && !IsPlayerAdmin(i))

View file

@ -21,6 +21,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "i_time.h"
#include "i_system.h"
#include "i_threads.h"
#include "m_menu.h"
@ -365,7 +366,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
lastwipetic = nowtime;
#ifdef HWRENDER

View file

@ -20,6 +20,7 @@
#include "filesrch.h" // for refreshdirmenu
#include "p_setup.h"
#include "p_saveg.h"
#include "i_time.h"
#include "i_system.h"
#include "am_map.h"
#include "m_random.h"
@ -50,6 +51,7 @@
#include "m_cond.h" // condition sets
#include "md5.h" // demo checksums
#include "k_kart.h" // SRB2kart
#include "r_fps.h" // frame interpolation/uncapped
#ifdef HAVE_DISCORDRPC
#include "discord.h"
@ -6131,7 +6133,7 @@ void G_ReadMetalTic(mobj_t *metal)
// Read changes from the tic
if (ziptic & GZT_XYZ)
{
P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
P_MoveOrigin(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
oldmetal.x = metal->x;
oldmetal.y = metal->y;
oldmetal.z = metal->z;

View file

@ -46,7 +46,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);

View file

@ -27,6 +27,7 @@
#include "../v_video.h"
#include "../p_local.h"
#include "../p_setup.h"
#include "../r_fps.h"
#include "../r_local.h"
#include "../r_bsp.h" // R_NoEncore
#include "../r_main.h" // cv_fov
@ -2389,6 +2390,7 @@ void HWR_Subsector(size_t num)
INT32 light = 0;
extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap;
ffloor_t *rover;
#ifdef PARANOIA //no risk while developing, enough debugging nights!
if (num >= addsubsector)
@ -2525,7 +2527,6 @@ void HWR_Subsector(size_t num)
if (gr_frontsector->ffloors)
{
/// \todo fix light, xoffs, yoffs, extracolormap ?
ffloor_t * rover;
for (rover = gr_frontsector->ffloors;
rover; rover = rover->next)
{
@ -4139,14 +4140,26 @@ void HWR_ProjectSprite(mobj_t *thing)
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
INT32 heightsec, phs;
// uncapped/interpolation
interpmobjstate_t interp = {0};
if (!thing)
return;
if (R_UsingFrameInterpolation() && !paused)
{
R_InterpolateMobjState(thing, rendertimefrac, &interp);
}
else
this_scale = FIXED_TO_FLOAT(thing->scale);
{
R_InterpolateMobjState(thing, FRACUNIT, &interp);
}
this_scale = FIXED_TO_FLOAT(interp.scale);
// transform the origin point
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
// rotation around vertical axis
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
@ -4156,8 +4169,8 @@ void HWR_ProjectSprite(mobj_t *thing)
return;
// The above can stay as it works for cutting sprites that are too close
tr_x = FIXED_TO_FLOAT(thing->x);
tr_y = FIXED_TO_FLOAT(thing->y);
tr_x = FIXED_TO_FLOAT(interp.x);
tr_y = FIXED_TO_FLOAT(interp.y);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
@ -4192,10 +4205,7 @@ void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (thing->player)
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
else
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
if (sprframe->rotate == SRF_SINGLE)
{
@ -4240,8 +4250,8 @@ void HWR_ProjectSprite(mobj_t *thing)
if (papersprite)
{
rightsin = FIXED_TO_FLOAT(FINESINE((thing->angle)>>ANGLETOFINESHIFT));
rightcos = FIXED_TO_FLOAT(FINECOSINE((thing->angle)>>ANGLETOFINESHIFT));
rightsin = FIXED_TO_FLOAT(FINESINE(interp.angle >> ANGLETOFINESHIFT));
rightcos = FIXED_TO_FLOAT(FINECOSINE(interp.angle >> ANGLETOFINESHIFT));
}
else
{
@ -4268,12 +4278,12 @@ void HWR_ProjectSprite(mobj_t *thing)
if (thing->eflags & MFE_VERTICALFLIP)
{
gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
gz = FIXED_TO_FLOAT(interp.z + thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
}
else
{
gzt = FIXED_TO_FLOAT(thing->z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
gzt = FIXED_TO_FLOAT(interp.z) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
gz = gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
}
@ -4292,12 +4302,12 @@ void HWR_ProjectSprite(mobj_t *thing)
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
if (gr_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) :
gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight))
return;
if (gr_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gr_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
FIXED_TO_FLOAT(thing->z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
FIXED_TO_FLOAT(interp.z) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight))
return;
}
@ -4375,9 +4385,25 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
unsigned rot = 0;
UINT8 flip;
// uncapped/interpolation
interpmobjstate_t interp = {0};
if (!thing)
return;
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
}
else
{
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
}
// transform the origin point
tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx;
tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy;
tr_x = FIXED_TO_FLOAT(interp.x) - gr_viewx;
tr_y = FIXED_TO_FLOAT(interp.y) - gr_viewy;
// rotation around vertical axis
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
@ -4386,8 +4412,8 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
if (tz < ZCLIP_PLANE)
return;
tr_x = FIXED_TO_FLOAT(thing->x);
tr_y = FIXED_TO_FLOAT(thing->y);
tr_x = FIXED_TO_FLOAT(interp.x);
tr_y = FIXED_TO_FLOAT(interp.y);
// decide which patch to use for sprite relative to player
if ((unsigned)thing->sprite >= numsprites)
@ -4912,7 +4938,8 @@ void HWR_DoPostProcessor(player_t *player)
{
// 10 by 10 grid. 2 coordinates (xy)
float v[SCREENVERTS][SCREENVERTS][2];
double disStart = leveltime;
static double disStart = 0;
UINT8 x, y;
INT32 WAVELENGTH;
INT32 AMPLITUDE;
@ -4921,15 +4948,15 @@ void HWR_DoPostProcessor(player_t *player)
// Modifies the wave.
if (*type == postimg_water)
{
WAVELENGTH = 20; // Lower is longer
AMPLITUDE = 20; // Lower is bigger
FREQUENCY = 16; // Lower is faster
WAVELENGTH = 5;
AMPLITUDE = 20;
FREQUENCY = 8;
}
else
{
WAVELENGTH = 10; // Lower is longer
AMPLITUDE = 30; // Lower is bigger
FREQUENCY = 4; // Lower is faster
WAVELENGTH = 10;
AMPLITUDE = 60;
FREQUENCY = 4;
}
for (x = 0; x < SCREENVERTS; x++)
@ -4942,6 +4969,8 @@ void HWR_DoPostProcessor(player_t *player)
}
}
HWD.pfnPostImgRedraw(v);
if (!(paused || P_AutoPause()))
disStart += FIXED_TO_FLOAT(renderdeltatics);
// Capture the screen again for screen waving on the intermission
if(gamestate != GS_INTERMISSION)

View file

@ -30,6 +30,7 @@
#include "hw_md2.h"
#include "../d_main.h"
#include "../r_bsp.h"
#include "../r_fps.h"
#include "../r_main.h"
#include "../m_misc.h"
#include "../w_wad.h"
@ -1128,6 +1129,16 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
spritedef_t *sprdef;
spriteframe_t *sprframe;
float finalscale;
interpmobjstate_t interp;
if (R_UsingFrameInterpolation() && !paused)
{
R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp);
}
else
{
R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp);
}
// Apparently people don't like jump frames like that, so back it goes
//if (tics > durs)
@ -1233,14 +1244,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (spr->mobj->frame & FF_ANIMATE)
{
// set duration and tics to be the correct values for FF_ANIMATE states
durs = spr->mobj->state->var2;
tics = spr->mobj->anim_duration;
durs = (float)spr->mobj->state->var2;
tics = (float)spr->mobj->anim_duration;
}
//FIXME: this is not yet correct
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
#ifdef USE_MODEL_NEXTFRAME
// Interpolate the model interpolation. (lol)
tics -= FixedToFloat(rendertimefrac);
if (cv_grmdls.value == 1 && tics <= durs)
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
@ -1265,13 +1279,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
#endif
//Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(spr->mobj->x);
p.y = FIXED_TO_FLOAT(spr->mobj->y)+md2->offset;
p.x = FIXED_TO_FLOAT(interp.x);
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
if (spr->mobj->eflags & MFE_VERTICALFLIP)
p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
else
p.z = FIXED_TO_FLOAT(spr->mobj->z);
p.z = FIXED_TO_FLOAT(interp.z);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
sprdef = &((skin_t *)spr->mobj->skin)->spritedef;
@ -1282,16 +1296,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (sprframe->rotate)
{
fixed_t anglef;
if (spr->mobj->player)
anglef = AngleFixed(spr->mobj->player->frameangle);
else
anglef = AngleFixed(spr->mobj->angle);
fixed_t anglef = AngleFixed(interp.angle);
p.angley = FIXED_TO_FLOAT(anglef);
}
else
{
const fixed_t anglef = AngleFixed((R_PointToAngle(spr->mobj->x, spr->mobj->y))-ANGLE_180);
const fixed_t anglef = AngleFixed((R_PointToAngle(interp.x, interp.y))-ANGLE_180);
p.angley = FIXED_TO_FLOAT(anglef);
}
p.anglex = 0.0f;
@ -1311,7 +1322,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
#endif
// SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
finalscale *= FIXED_TO_FLOAT(interp.scale);
p.flip = atransform.flip;
#ifdef USE_FTRANSFORM_MIRROR

View file

@ -2865,7 +2865,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
#define BUFFER_OFFSET(i) ((char*)(i))
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
{
static GLRGBAFloat poly = {0,0,0,0};
static GLRGBAFloat tint = {0,0,0,0};
@ -2884,11 +2884,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
scaley = scale;
scalez = scale;
if (duration != 0 && duration != -1 && tics != -1) // don't interpolate if instantaneous or infinite in length
if (duration > 0.0 && tics >= 0.0) // don't interpolate if instantaneous or infinite in length
{
UINT32 newtime = (duration - tics); // + 1;
float newtime = (duration - tics); // + 1;
pol = (newtime)/(float)duration;
pol = newtime / duration;
if (pol > 1.0f)
pol = 1.0f;
@ -3063,7 +3063,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
// -----------------+
// HWRAPI DrawModel : Draw a model
// -----------------+
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface)
{
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface);
}

View file

@ -48,6 +48,7 @@
#ifdef HAVE_BLUA
#include "lua_hud.h"
#include "lua_hudlib_drawlist.h"
#include "lua_hook.h"
#endif
@ -90,6 +91,10 @@ static boolean headsupactive = false;
boolean hu_showscores; // draw rankings
static char hu_tick;
#ifdef HAVE_BLUA
static huddrawlist_h luahuddrawlist_scores;
#endif
patch_t *rflagico;
patch_t *bflagico;
patch_t *rmatcico;
@ -176,6 +181,8 @@ static INT32 cechoflags = 0;
// HEADS UP INIT
//======================================================================
static tic_t resynch_ticker = 0;
#ifndef NONET
// just after
static void Command_Say_f(void);
@ -334,6 +341,10 @@ void HU_Init(void)
// set shift translation table
shiftxform = english_shiftxform;
#ifdef HAVE_BLUA
luahuddrawlist_scores = LUA_HUD_CreateDrawList();
#endif
HU_LoadGraphics();
}
@ -385,12 +396,12 @@ static INT16 addy = 0; // use this to make the messages scroll smoothly when one
static void HU_removeChatText_Mini(void)
{
// MPC: Don't create new arrays, just iterate through an existing one
// MPC: Don't create new arrays, just iterate through an existing one
size_t i;
for(i=0;i<chat_nummsg_min-1;i++) {
strcpy(chat_mini[i], chat_mini[i+1]);
chat_timers[i] = chat_timers[i+1];
}
for(i=0;i<chat_nummsg_min-1;i++) {
strcpy(chat_mini[i], chat_mini[i+1]);
chat_timers[i] = chat_timers[i+1];
}
chat_nummsg_min--; // lost 1 msg.
// use addy and make shit slide smoothly af.
@ -403,10 +414,10 @@ static void HU_removeChatText_Log(void)
{
// MPC: Don't create new arrays, just iterate through an existing one
size_t i;
for(i=0;i<chat_nummsg_log-1;i++) {
strcpy(chat_log[i], chat_log[i+1]);
}
chat_nummsg_log--; // lost 1 msg.
for(i=0;i<chat_nummsg_log-1;i++) {
strcpy(chat_log[i], chat_log[i+1]);
}
chat_nummsg_log--; // lost 1 msg.
}
#endif
@ -1071,6 +1082,38 @@ void HU_Ticker(void)
hu_showscores = !chat_on;
else
hu_showscores = false;
if (chat_on)
{
// count down the scroll timer.
if (chat_scrolltime > 0)
chat_scrolltime--;
}
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
{
size_t i = 0;
// handle spam while we're at it:
for(; (i<MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
}
// handle chat timers
for (i=0; (i<chat_nummsg_min); i++)
{
if (chat_timers[i] > 0)
chat_timers[i]--;
else
HU_removeChatText_Mini();
}
}
if (cechotimer > 0) --cechotimer;
HU_TickSongCredits();
}
#ifndef NONET
@ -2204,8 +2247,6 @@ static void HU_DrawCEcho(void)
echoptr = line;
echoptr++;
}
--cechotimer;
}
//
@ -2252,10 +2293,27 @@ static void HU_DrawDemoInfo(void)
//
// Song credits
//
void HU_TickSongCredits(void)
{
if (cursongcredit.anim)
{
if (cursongcredit.trans > 0)
cursongcredit.trans--;
cursongcredit.anim--;
}
else
{
if (cursongcredit.trans < NUMTRANSMAPS)
cursongcredit.trans++;
}
}
void HU_DrawSongCredits(void)
{
char *str;
INT32 len, destx;
INT32 len;
fixed_t destx;
INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
INT32 bgt;
@ -2264,33 +2322,31 @@ void HU_DrawSongCredits(void)
str = va("\x1F"" %s", cursongcredit.def->source);
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
destx = (len+7);
destx = (len + 7) * FRACUNIT;
if (cursongcredit.anim)
{
if (cursongcredit.trans > 0)
cursongcredit.trans--;
if (cursongcredit.x < destx)
cursongcredit.x += (destx - cursongcredit.x) / 2;
cursongcredit.x += FixedMul((destx - cursongcredit.x) / 2, renderdeltatics);
if (cursongcredit.x > destx)
cursongcredit.x = destx;
cursongcredit.anim--;
}
else
{
if (cursongcredit.trans < NUMTRANSMAPS)
cursongcredit.trans++;
if (cursongcredit.x > 0)
cursongcredit.x /= 2;
cursongcredit.x -= FixedMul(cursongcredit.x / 2, renderdeltatics);
if (cursongcredit.x < 0)
cursongcredit.x = 0;
}
bgt = (NUMTRANSMAPS/2)+(cursongcredit.trans/2);
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
// v1 does not have v2's font revamp, so there is no function for thin string at fixed_t
// sooo I'm just killing the precision.
if (bgt < NUMTRANSMAPS)
V_DrawScaledPatch(cursongcredit.x, y-2, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg);
V_DrawScaledPatch(cursongcredit.x / FRACUNIT, y-2, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg);
if (cursongcredit.trans < NUMTRANSMAPS)
V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
V_DrawRightAlignedThinString(cursongcredit.x / FRACUNIT, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
}
@ -2305,9 +2361,6 @@ void HU_Drawer(void)
// draw chat string plus cursor
if (chat_on)
{
// count down the scroll timer.
if (chat_scrolltime > 0)
chat_scrolltime--;
if (!OLDCHAT)
HU_DrawChat();
else
@ -2317,30 +2370,10 @@ void HU_Drawer(void)
{
typelines = 1;
chat_scrolltime = 0;
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden)
HU_drawMiniChat(); // draw messages in a cool fashion.
}
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
{
size_t i = 0;
// handle spam while we're at it:
for(; (i<MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
}
// handle chat timers
for (i=0; (i<chat_nummsg_min); i++)
{
if (chat_timers[i] > 0)
chat_timers[i]--;
else
HU_removeChatText_Mini();
}
}
#endif
if (cechotimer)
@ -2363,7 +2396,12 @@ void HU_Drawer(void)
#endif
HU_DrawRankings();
#ifdef HAVE_BLUA
LUAh_ScoresHUD();
if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_scores);
LUAh_ScoresHUD(luahuddrawlist_scores);
}
LUA_HUD_DrawList(luahuddrawlist_scores);
#endif
}
if (demo.playback)
@ -2398,12 +2436,9 @@ void HU_Drawer(void)
// draw desynch text
if (hu_resynching)
{
static UINT32 resynch_ticker = 0;
char resynch_text[14];
UINT32 i;
// Animate the dots
resynch_ticker++;
strcpy(resynch_text, "Resynching");
for (i = 0; i < (resynch_ticker / 16) % 4; i++)
strcat(resynch_text, ".");

View file

@ -109,6 +109,7 @@ void HU_Start(void);
boolean HU_Responder(event_t *ev);
void HU_Ticker(void);
void HU_TickSongCredits(void);
void HU_DrawSongCredits(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);

View file

@ -42,15 +42,32 @@ extern UINT8 keyboard_started;
*/
UINT32 I_GetFreeMem(UINT32 *total);
/** \brief Called by D_SRB2Loop, returns current time in tics.
*/
tic_t I_GetTime(void);
/** \brief Returns precise time value for performance measurement. The precise
time should be a monotonically increasing counter, and will wrap.
precise_t is internally represented as an unsigned integer and
integer arithmetic may be used directly between values of precise_t.
*/
precise_t I_GetPreciseTime(void);
/** \brief The I_Sleep function
/** \brief Get the precision of precise_t in units per second. Invocations of
this function for the program's duration MUST return the same value.
*/
UINT64 I_GetPrecisePrecision(void);
/** \brief Get the current time in rendering tics, including fractions.
*/
double I_GetFrameTime(void);
/** \brief Sleeps for the given duration in milliseconds. Depending on the
operating system's scheduler, the calling thread may give up its
time slice for a longer duration. The implementation should give a
best effort to sleep for the given duration, without spin-locking.
Calling code should check the current precise time after sleeping
and not assume the thread has slept for the expected duration.
\return void
*/
void I_Sleep(void);
void I_Sleep(UINT32 ms);
/** \brief Get events

123
src/i_time.c Normal file
View file

@ -0,0 +1,123 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_time.c
/// \brief Timing for the system layer.
#include "i_time.h"
#include <math.h>
#include "command.h"
#include "doomtype.h"
#include "d_netcmd.h"
#include "m_fixed.h"
#include "i_system.h"
timestate_t g_time;
static CV_PossibleValue_t timescale_cons_t[] = {{FRACUNIT/20, "MIN"}, {20*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_timescale = {"timescale", "1.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, timescale_cons_t, NULL, FRACUNIT, NULL, NULL, 0, 0, NULL};
static precise_t enterprecise, oldenterprecise;
static fixed_t entertic, oldentertics;
static double tictimer;
// A little more than the minimum sleep duration on Windows.
// May be incorrect for other platforms, but we don't currently have a way to
// query the scheduler granularity. SDL will do what's needed to make this as
// low as possible though.
#define MIN_SLEEP_DURATION_MS 2.1
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 * MIN_SLEEP_DURATION_MS));
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
View 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__

View file

@ -135,4 +135,6 @@ void I_BeginRead(void);
*/
void I_EndRead(void);
UINT32 I_GetRefreshRate(void);
#endif

View file

@ -182,10 +182,10 @@ state_t states[NUMSTATES] =
// 1-Up Box Sprites (uses player sprite)
// Kart: hide for now, fix for R2
{SPR_NULL, 0, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2
{SPR_NULL, 0, 2, {NULL}, 0, 18, S_PLAY_BOX2}, // S_PLAY_BOX1
{SPR_NULL, 0, 1, {NULL}, 0, 18, S_PLAY_BOX1}, // S_PLAY_BOX2
{SPR_NULL, 0, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1
{SPR_NULL, 0, 12, {NULL}, 0, 0, S_PLAY_ICON3}, // S_PLAY_ICON2
{SPR_NULL, 0, 12, {NULL}, 0, 4, S_PLAY_ICON3}, // S_PLAY_ICON2
{SPR_NULL, 0, 18, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3
// Level end sign (uses player sprite)

View file

@ -2027,9 +2027,15 @@ void K_DoInstashield(player_t *player)
S_StartSound(player->mo, sfx_cdpcm9);
layera = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDA);
layera->old_x = player->mo->old_x;
layera->old_y = player->mo->old_y;
layera->old_z = player->mo->old_z;
P_SetTarget(&layera->target, player->mo);
layerb = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDB);
layerb->old_x = player->mo->old_x;
layerb->old_y = player->mo->old_y;
layerb->old_z = player->mo->old_z;
P_SetTarget(&layerb->target, player->mo);
}
@ -2731,7 +2737,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
{
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
// This should set it for FOFs
P_TeleportMove(th, th->x, th->y, th->z);
P_SetOrigin(th, th->x, th->y, th->z);
// spawn on the ground if the player is on the ground
if (P_MobjFlip(source) < 0)
{
@ -3314,7 +3320,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
{
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
// This should set it for FOFs
P_TeleportMove(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
P_SetOrigin(mo, mo->x, mo->y, mo->z); // however, THIS can fuck up your day. just absolutely ruin you.
if (P_MobjWasRemoved(mo))
return NULL;
@ -3827,7 +3833,7 @@ void K_DropHnextList(player_t *player)
{
// floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn
// This should set it for FOFs
//P_TeleportMove(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
//P_SetOrigin(dropwork, dropwork->x, dropwork->y, dropwork->z); -- handled better by above floorz/ceilingz passing
if (flip == 1)
{
@ -4101,7 +4107,7 @@ static void K_MoveHeldObjects(player_t *player)
z = player->mo->z + player->mo->height - cur->height;
cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player
P_TeleportMove(cur, player->mo->x, player->mo->y, z);
P_MoveOrigin(cur, player->mo->x, player->mo->y, z);
cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1);
cur->flags &= ~MF_NOCLIPTHING;
@ -4203,7 +4209,7 @@ static void K_MoveHeldObjects(player_t *player)
P_SetObjectMomZ(cur, FixedMul(targz - cur->z, 7*FRACUNIT/8) - gravity, false);
if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT)
P_TeleportMove(cur, targx, targy, cur->z);
P_MoveOrigin(cur, targx, targy, cur->z);
cur = cur->hnext;
}
@ -4287,12 +4293,12 @@ static void K_MoveHeldObjects(player_t *player)
diffy = targy - cur->y;
diffz = targz - cur->z;
P_TeleportMove(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
P_MoveOrigin(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
cur->tracer->y + diffy + P_ReturnThrustY(cur, cur->angle + angoffset, 6*cur->scale), cur->tracer->z + diffz);
P_SetScale(cur->tracer, (cur->tracer->destscale = 3*cur->scale/4));
}
P_TeleportMove(cur, targx, targy, targz);
P_MoveOrigin(cur, targx, targy, targz);
K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks.
num = (num+1) % 2;
cur = cur->hnext;
@ -4951,6 +4957,9 @@ void K_KartPlayerAfterThink(player_t *player)
}
ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE);
ret->old_x = targ->mo->old_x;
ret->old_y = targ->mo->old_y;
ret->old_z = targ->mo->old_z;
P_SetTarget(&ret->target, targ->mo);
ret->frame |= ((leveltime % 10) / 2);
ret->tics = 1;

View file

@ -1026,7 +1026,40 @@ static int lib_pTeleportMove(lua_State *L)
NOHUD
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin");
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
LUA_PushUserdata(L, tmthing, META_MOBJ);
P_SetTarget(&tmthing, ptmthing);
return 2;
}
static int lib_pSetOrigin(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
NOHUD
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SetOrigin(thing, x, y, z));
LUA_PushUserdata(L, tmthing, META_MOBJ);
P_SetTarget(&tmthing, ptmthing);
return 2;
}
static int lib_pMoveOrigin(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
NOHUD
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_MoveOrigin(thing, x, y, z));
LUA_PushUserdata(L, tmthing, META_MOBJ);
P_SetTarget(&tmthing, ptmthing);
return 2;
@ -3038,6 +3071,8 @@ static luaL_Reg lib[] = {
{"P_TryMove",lib_pTryMove},
{"P_Move",lib_pMove},
{"P_TeleportMove",lib_pTeleportMove},
{"P_SetOrigin",lib_pSetOrigin},
{"P_MoveOrigin",lib_pMoveOrigin},
{"P_SlideMove",lib_pSlideMove},
{"P_BounceMove",lib_pBounceMove},
{"P_CheckSight", lib_pCheckSight},

View file

@ -10,6 +10,11 @@
/// \file lua_hud.h
/// \brief HUD enable/disable flags for Lua scripting
#ifndef __LUA_HUD_H__
#define __LUA_HUD_H__
#include "lua_hudlib_drawlist.h"
enum hud {
hud_stagetitle = 0,
hud_textspectator,
@ -36,5 +41,7 @@ extern boolean hud_running;
boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr);
void LUAh_ScoresHUD(void);
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
void LUAh_ScoresHUD(huddrawlist_h list);
#endif // __LUA_HUD_H__

View file

@ -344,7 +344,8 @@ static int libd_draw(lua_State *L)
{
INT32 x, y, flags;
patch_t *patch;
const UINT8 *colormap = NULL;
UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY
x = luaL_checkinteger(L, 1);
@ -356,7 +357,14 @@ static int libd_draw(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDraw(list, x, y, patch, flags, colormap);
else
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
return 0;
}
@ -365,7 +373,8 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale;
INT32 flags;
patch_t *patch;
const UINT8 *colormap = NULL;
UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY
x = luaL_checkinteger(L, 1);
@ -380,7 +389,14 @@ static int libd_drawScaled(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawScaled(list, x, y, scale, patch, flags, colormap);
else
V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
return 0;
}
@ -389,8 +405,9 @@ static int libd_drawOnMinimap(lua_State *L)
{
fixed_t x, y, scale; // coordinates of the object
patch_t *patch; // patch we want to draw
const UINT8 *colormap = NULL; // do we want to colormap this patch?
UINT8 *colormap = NULL; // do we want to colormap this patch?
boolean centered; // the patch is centered and doesn't need readjusting on x/y coordinates.
huddrawlist_h list;
// variables used to replicate k_kart's mmap drawer:
INT32 lumpnum;
@ -553,13 +570,24 @@ static int libd_drawOnMinimap(lua_State *L)
amypos = amnumypos + ((my + AutomapPic->height/2)<<FRACBITS) - patchh;
// and NOW we can FINALLY DRAW OUR GOD DAMN PATCH :V
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawScaled(list, amxpos, amypos, scale, patch, splitflags, colormap);
else
V_DrawFixedPatch(amxpos, amypos, scale, splitflags, patch, colormap);
return 0;
}
static int libd_drawNum(lua_State *L)
{
INT32 x, y, flags, num;
huddrawlist_h list;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
@ -567,13 +595,22 @@ static int libd_drawNum(lua_State *L)
flags = luaL_optinteger(L, 4, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawTallNum(x, y, flags, num);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawNum(list, x, y, num, flags);
else
V_DrawTallNum(x, y, flags, num);
return 0;
}
static int libd_drawPaddedNum(lua_State *L)
{
INT32 x, y, flags, num, digits;
huddrawlist_h list;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
@ -582,7 +619,14 @@ static int libd_drawPaddedNum(lua_State *L)
flags = luaL_optinteger(L, 5, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
V_DrawPaddedTallNum(x, y, flags, num, digits);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawPaddedNum(list, x, y, num, digits, flags);
else
V_DrawPaddedTallNum(x, y, flags, num, digits);
return 0;
}
@ -606,6 +650,7 @@ static int libd_drawPingNum(lua_State *L)
static int libd_drawFill(lua_State *L)
{
huddrawlist_h list;
INT32 x = luaL_optinteger(L, 1, 0);
INT32 y = luaL_optinteger(L, 2, 0);
INT32 w = luaL_optinteger(L, 3, BASEVIDWIDTH);
@ -613,36 +658,58 @@ 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;
}
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);
UINT16 color = luaL_checkinteger(L, 1);
UINT8 strength = luaL_checkinteger(L, 2);
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
huddrawlist_h list;
HUDONLY
HUDONLY
if (!strength)
return 0;
if (!strength)
return 0;
if (strength > maxstrength)
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
if (strength > maxstrength)
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
if (strength == maxstrength) // Allow as a shortcut for drawfill...
{
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
return 0;
}
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
V_DrawFadeScreen(color, strength);
return 0;
if (strength == maxstrength) // Allow as a shortcut for drawfill...
{
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;
}
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddFadeScreen(list, color, strength);
else
V_DrawFadeScreen(color, strength);
return 0;
}
static int libd_drawString(lua_State *L)
{
huddrawlist_h list;
fixed_t x = luaL_checkinteger(L, 1);
fixed_t y = luaL_checkinteger(L, 2);
const char *str = luaL_checkstring(L, 3);
@ -652,6 +719,15 @@ static int libd_drawString(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen.
HUDONLY
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
// okay, sorry, this is kind of ugly
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawString(list, x, y, str, flags, align);
else
switch(align)
{
// hu_font
@ -691,11 +767,20 @@ static int libd_drawKartString(lua_State *L)
fixed_t y = luaL_checkinteger(L, 2);
const char *str = luaL_checkstring(L, 3);
INT32 flags = luaL_optinteger(L, 4, V_ALLOWLOWERCASE);
huddrawlist_h list;
flags &= ~V_PARAMMASK; // Don't let crashes happen.
HUDONLY
V_DrawKartString(x, y, flags, str);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawKartString(list, x, y, str, flags);
else
V_DrawKartString(x, y, flags, str);
return 0;
}
@ -956,10 +1041,13 @@ boolean LUA_HudEnabled(enum hud option)
}
// Hook for HUD rendering
void LUAh_GameHUD(player_t *stplayr)
void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
{
if (!gL || !(hudAvailable & (1<<hudhook_game)))
return;
lua_pushlightuserdata(gL, list);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
hud_running = true;
lua_pop(gL, -1);
@ -1004,12 +1092,18 @@ void LUAh_GameHUD(player_t *stplayr)
}
lua_pop(gL, -1);
hud_running = false;
lua_pushlightuserdata(gL, NULL);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
}
void LUAh_ScoresHUD(void)
void LUAh_ScoresHUD(huddrawlist_h list)
{
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
return;
lua_pushlightuserdata(gL, list);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
hud_running = true;
lua_pop(gL, -1);
@ -1029,6 +1123,9 @@ void LUAh_ScoresHUD(void)
}
lua_pop(gL, -1);
hud_running = false;
lua_pushlightuserdata(gL, NULL);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
}
#endif

410
src/lua_hudlib_drawlist.c Normal file
View file

@ -0,0 +1,410 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2014-2016 by John "JTE" Muniz.
// Copyright (C) 2014-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_hudlib_drawlist.c
/// \brief a data structure for managing cached drawlists for the Lua hud lib
#include "lua_hudlib_drawlist.h"
#include <string.h>
#include "v_video.h"
#include "z_zone.h"
enum drawitem_e {
DI_Draw = 0,
DI_DrawScaled,
DI_DrawNum,
DI_DrawPaddedNum,
DI_DrawFill,
DI_DrawString,
DI_DrawKartString,
DI_DrawLevelTitle,
DI_FadeScreen,
DI_MAX,
};
// A single draw item with all possible arguments needed for a draw call.
typedef struct drawitem_s {
enum drawitem_e type;
fixed_t x;
fixed_t y;
fixed_t w;
fixed_t h;
INT32 c;
fixed_t scale;
fixed_t hscale;
fixed_t vscale;
patch_t *patch;
INT32 flags;
UINT16 basecolor;
UINT16 outlinecolor;
UINT8 *colormap;
UINT8 *basecolormap;
UINT8 *outlinecolormap;
fixed_t sx;
fixed_t sy;
INT32 num;
INT32 digits;
const char *str;
UINT16 color;
UINT8 strength;
INT32 align;
} drawitem_t;
// The internal structure of a drawlist.
struct huddrawlist_s {
drawitem_t *items;
size_t items_capacity;
size_t items_len;
char *strbuf;
size_t strbuf_capacity;
size_t strbuf_len;
};
// alignment types for v.drawString
enum align {
align_left = 0,
align_center,
align_right,
align_fixed,
align_small,
align_smallright,
align_thin,
align_thinright
};
huddrawlist_h LUA_HUD_CreateDrawList(void)
{
huddrawlist_h drawlist;
drawlist = (huddrawlist_h) Z_CallocAlign(sizeof(struct huddrawlist_s), PU_STATIC, NULL, 64);
drawlist->items = NULL;
drawlist->items_capacity = 0;
drawlist->items_len = 0;
drawlist->strbuf = NULL;
drawlist->strbuf_capacity = 0;
drawlist->strbuf_len = 0;
return drawlist;
}
void LUA_HUD_ClearDrawList(huddrawlist_h list)
{
// rather than deallocate, we'll just save the existing allocation and empty
// it out for reuse
// this memset probably isn't necessary
if (list->items)
{
memset(list->items, 0, sizeof(drawitem_t) * list->items_capacity);
}
list->items_len = 0;
if (list->strbuf)
{
list->strbuf[0] = 0;
}
list->strbuf_len = 0;
}
void LUA_HUD_DestroyDrawList(huddrawlist_h list)
{
if (list == NULL) return;
if (list->items)
{
Z_Free(list->items);
}
Z_Free(list);
}
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
{
if (!list) return false;
// that's all we can really do to check the validity of the handle right now
return true;
}
static size_t AllocateDrawItem(huddrawlist_h list)
{
if (!list) I_Error("can't allocate draw item: invalid list");
if (list->items_capacity <= list->items_len + 1)
{
if (list->items_capacity == 0) list->items_capacity = 128;
else list->items_capacity *= 2;
list->items = (drawitem_t *) Z_ReallocAlign(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL, 64);
}
return list->items_len++;
}
// copy string to list's internal string buffer
// lua can deallocate the string before we get to use it, so it's important to
// keep our own copy
static const char *CopyString(huddrawlist_h list, const char* str)
{
size_t lenstr;
if (!list) I_Error("can't allocate string; invalid list");
lenstr = strlen(str);
if (list->strbuf_capacity <= list->strbuf_len + lenstr + 1)
{
if (list->strbuf_capacity == 0) list->strbuf_capacity = 256;
else list->strbuf_capacity *= 2;
list->strbuf = (char*) Z_ReallocAlign(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL, 8);
}
{
const char *result = (const char *) &list->strbuf[list->strbuf_len];
strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1);
list->strbuf_len += lenstr + 1;
return result;
}
}
void LUA_HUD_AddDraw(
huddrawlist_h list,
INT32 x,
INT32 y,
patch_t *patch,
INT32 flags,
UINT8 *colormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_Draw;
item->x = x;
item->y = y;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
}
void LUA_HUD_AddDrawScaled(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t scale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawScaled;
item->x = x;
item->y = y;
item->scale = scale;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
}
void LUA_HUD_AddDrawNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawNum;
item->x = x;
item->y = y;
item->num = num;
item->flags = flags;
}
void LUA_HUD_AddDrawPaddedNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 digits,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawPaddedNum;
item->x = x;
item->y = y;
item->num = num;
item->digits = digits;
item->flags = flags;
}
void LUA_HUD_AddDrawFill(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 w,
INT32 h,
INT32 c
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawFill;
item->x = x;
item->y = y;
item->w = w;
item->h = h;
item->c = c;
}
void LUA_HUD_AddDrawString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
INT32 align
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawString;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
item->align = align;
}
void LUA_HUD_AddDrawKartString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawKartString;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
}
void LUA_HUD_AddDrawLevelTitle(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawLevelTitle;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
}
void LUA_HUD_AddFadeScreen(
huddrawlist_h list,
UINT16 color,
UINT8 strength
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_FadeScreen;
item->color = color;
item->strength = strength;
}
void LUA_HUD_DrawList(huddrawlist_h list)
{
size_t i;
if (!list) I_Error("HUD drawlist invalid");
if (list->items_len <= 0) return;
if (!list->items) I_Error("HUD drawlist->items invalid");
for (i = 0; i < list->items_len; i++)
{
drawitem_t *item = &list->items[i];
switch (item->type)
{
case DI_Draw:
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
break;
case DI_DrawScaled:
V_DrawFixedPatch(item->x, item->y, item->scale, item->flags, item->patch, item->colormap);
break;
case DI_DrawNum:
V_DrawTallNum(item->x, item->y, item->flags, item->num);
break;
case DI_DrawPaddedNum:
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
break;
case DI_DrawFill:
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
break;
case DI_DrawString:
switch(item->align)
{
// hu_font
case align_left:
V_DrawString(item->x, item->y, item->flags, item->str);
break;
case align_center:
V_DrawCenteredString(item->x, item->y, item->flags, item->str);
break;
case align_right:
V_DrawRightAlignedString(item->x, item->y, item->flags, item->str);
break;
case align_fixed:
V_DrawStringAtFixed(item->x, item->y, item->flags, item->str);
break;
// hu_font, 0.5x scale
case align_small:
V_DrawSmallString(item->x, item->y, item->flags, item->str);
break;
case align_smallright:
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, item->str);
break;
// tny_font
case align_thin:
V_DrawThinString(item->x, item->y, item->flags, item->str);
break;
case align_thinright:
V_DrawRightAlignedThinString(item->x, item->y, item->flags, item->str);
break;
}
break;
case DI_DrawKartString:
V_DrawKartString(item->x, item->y, item->flags, item->str);
break;
case DI_DrawLevelTitle:
V_DrawLevelTitle(item->x, item->y, item->flags, item->str);
break;
case DI_FadeScreen:
V_DrawFadeScreen(item->color, item->strength);
break;
default:
I_Error("can't draw draw list item: invalid draw list item type");
continue;
}
}
}

112
src/lua_hudlib_drawlist.h Normal file
View file

@ -0,0 +1,112 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2022-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_hudlib_drawlist.h
/// \brief a data structure for managing cached drawlists for the Lua hud lib
// The idea behinds this module is to cache drawcall information into an ordered
// list to repeat the same draw operations in later frames. It's used to ensure
// that the HUD hooks from Lua are called at precisely 35hz to avoid problems
// with variable framerates in existing Lua addons.
#ifndef __LUA_HUDLIB_DRAWLIST__
#define __LUA_HUDLIB_DRAWLIST__
#include "doomtype.h"
#include "r_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct huddrawlist_s *huddrawlist_h;
// Create a new drawlist. Returns a handle to it.
huddrawlist_h LUA_HUD_CreateDrawList(void);
// Clears the draw list.
void LUA_HUD_ClearDrawList(huddrawlist_h list);
// Destroys the drawlist, invalidating the given handle
void LUA_HUD_DestroyDrawList(huddrawlist_h list);
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list);
void LUA_HUD_AddDraw(
huddrawlist_h list,
INT32 x,
INT32 y,
patch_t *patch,
INT32 flags,
UINT8 *colormap
);
void LUA_HUD_AddDrawScaled(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t scale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
);
void LUA_HUD_AddDrawNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 flags
);
void LUA_HUD_AddDrawPaddedNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 digits,
INT32 flags
);
void LUA_HUD_AddDrawFill(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 w,
INT32 h,
INT32 c
);
void LUA_HUD_AddDrawString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
INT32 align
);
void LUA_HUD_AddDrawKartString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags
);
void LUA_HUD_AddDrawLevelTitle(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags
);
void LUA_HUD_AddFadeScreen(
huddrawlist_h list,
UINT16 color,
UINT8 strength
);
// Draws the given draw list
void LUA_HUD_DrawList(huddrawlist_h list);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __LUA_HUDLIB_DRAWLIST__

View file

@ -373,7 +373,7 @@ static int mobj_get(lua_State *L)
}
#define NOSET luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly.", mobj_opt[field])
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_TeleportMove") " instead.", mobj_opt[field])
#define NOSETPOS luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " should not be set directly. Use " LUA_QL("P_Move") ", " LUA_QL("P_TryMove") ", or " LUA_QL("P_SetOrigin") ", or " LUA_QL("P_MoveOrigin") " instead.", mobj_opt[field])
static int mobj_set(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -639,6 +639,7 @@ static int mobj_set(lua_State *L)
scale = FRACUNIT/100;
mo->destscale = scale;
P_SetScale(mo, scale);
mo->old_scale = scale;
break;
}
case mobj_destscale:

View file

@ -495,7 +495,7 @@ void Command_RTeleport_f(void)
CONS_Printf(M_GetText("Teleporting by %d, %d, %d...\n"), intx, inty, FixedInt((intz-p->mo->z)));
P_MapStart();
if (!P_TeleportMove(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
if (!P_SetOrigin(p->mo, p->mo->x+intx*FRACUNIT, p->mo->y+inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
@ -562,7 +562,7 @@ void Command_Teleport_f(void)
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
P_MapStart();
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
if (!P_SetOrigin(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
@ -1107,13 +1107,13 @@ void OP_ObjectplaceMovement(player_t *player)
if (cmd->forwardmove != 0)
{
P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}
/*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed
{
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
P_MoveOrigin(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0;
}*/

View file

@ -22,6 +22,7 @@
#include "d_main.h"
#include "d_netcmd.h"
#include "console.h"
#include "r_fps.h"
#include "r_local.h"
#include "hu_stuff.h"
#include "g_game.h"
@ -31,6 +32,7 @@
// Data.
#include "sounds.h"
#include "s_sound.h"
#include "i_time.h"
#include "i_system.h"
#include "i_threads.h"
@ -1255,9 +1257,10 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90},
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100},
{IT_STRING | IT_CVAR, NULL, "FPS Cap", &cv_fpscap, 110},
#ifdef HWRENDER
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 120},
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 130},
#endif
};
@ -6912,6 +6915,7 @@ static void M_DrawLoad(void)
INT32 ymod = 0, offset = 0;
M_DrawMenuTitle();
fixed_t scrollfrac = FixedDiv(2, 3);
if (menumovedir != 0) //movement illusion
{
@ -9137,12 +9141,12 @@ Update the maxplayers label...
if (itemOn == 2 && i == setupm_pselect)
{
static UINT8 cursorframe = 0;
if (skullAnimCounter % 4 == 0)
cursorframe++;
if (cursorframe > 7)
cursorframe = 0;
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, 0, W_CachePatchName(va("K_BHILI%d", cursorframe+1), PU_CACHE), NULL);
static fixed_t cursorframe = 0;
cursorframe += renderdeltatics / 4;
for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {}
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, 0, W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE), NULL);
}
x += incrwidth;
@ -9337,7 +9341,7 @@ static void M_HandleConnectIP(INT32 choice)
// ========================
// Tails 03-02-2002
static INT32 multi_tics;
static fixed_t multi_tics;
static state_t *multi_state;
// this is set before entering the MultiPlayer setup menu,
@ -9483,16 +9487,14 @@ static void M_DrawSetupMultiPlayerMenu(void)
fixed_t scale = FRACUNIT/2;
INT32 offx = 8, offy = 8;
patch_t *cursor;
static UINT8 cursorframe = 0;
static fixed_t cursorframe = 0;
patch_t *face;
UINT8 *colmap;
if (skullAnimCounter % 4 == 0)
cursorframe++;
if (cursorframe > 7)
cursorframe = 0;
cursorframe += renderdeltatics / 4;
for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {}
cursor = W_CachePatchName(va("K_BHILI%d", cursorframe+1), PU_CACHE);
cursor = W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE);
if (col < 0)
col += numskins;
@ -9524,14 +9526,17 @@ static void M_DrawSetupMultiPlayerMenu(void)
#undef iconwidth
// anim the player in the box
if (--multi_tics <= 0)
multi_tics -= renderdeltatics;
while (multi_tics <= 0)
{
st = multi_state->nextstate;
if (st != S_NULL)
multi_state = &states[st];
multi_tics = multi_state->tics;
if (multi_tics == -1)
multi_tics = 15;
if (multi_state->tics <= -1)
multi_tics += 15*FRACUNIT;
else
multi_tics += multi_state->tics * FRACUNIT;
}
// skin 0 is default player sprite
@ -9692,7 +9697,7 @@ static void M_SetupMultiPlayer(INT32 choice)
(void)choice;
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics;
multi_tics = multi_state->tics*FRACUNIT;
strcpy(setupm_name, cv_playername.string);
// set for player 1
@ -9723,7 +9728,7 @@ static void M_SetupMultiPlayer2(INT32 choice)
(void)choice;
multi_state = &states[mobjinfo[MT_PLAYER].seestate];
multi_tics = multi_state->tics;
multi_tics = multi_state->tics*FRACUNIT;
strcpy (setupm_name, cv_playername2.string);
// set for splitscreen secondary player
@ -11226,7 +11231,8 @@ void M_QuitResponse(INT32 ch)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
I_Sleep();
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
}
I_Quit();

View file

@ -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"

View file

@ -13,6 +13,7 @@
#include "doomdef.h"
#include "p_local.h"
#include "r_fps.h"
#include "r_main.h"
#include "s_sound.h"
#include "z_zone.h"
@ -600,6 +601,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
ceiling->tag = sec->tag;
ceiling->type = type;
firstone = 0;
// interpolation
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
}
return rtn;
}
@ -676,6 +680,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
ceiling->tag = sec->tag;
ceiling->type = type;
// interpolation
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
}
return rtn;
}

View file

@ -8282,6 +8282,9 @@ void A_JawzChase(mobj_t *actor)
ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE);
P_SetTarget(&ret->target, actor->tracer);
ret->old_x = actor->tracer->old_x;
ret->old_y = actor->tracer->old_y;
ret->old_z = actor->tracer->old_z;
ret->frame |= ((leveltime % 10) / 2) + 5;
ret->color = actor->cvmem;
@ -8660,10 +8663,10 @@ void A_LightningFollowPlayer(mobj_t *actor)
{
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
P_TeleportMove(actor, sx, sy, actor->target->z);
P_MoveOrigin(actor, sx, sy, actor->target->z);
}
else // else just teleport to player directly
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z);
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
actor->momx = actor->target->momx;
@ -10731,7 +10734,7 @@ void A_VileAttack(mobj_t *actor)
// move the fire between the vile and the player
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
P_TeleportMove(fire,
P_MoveOrigin(fire,
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
fire->z);
@ -10776,7 +10779,7 @@ void A_VileAttack(mobj_t *actor)
// move the fire between the vile and the player
//fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
//fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
P_TeleportMove(fire,
P_MoveOrigin(fire,
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
fire->z);

View file

@ -14,6 +14,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "p_local.h"
#include "r_fps.h"
#include "r_state.h"
#include "s_sound.h"
#include "z_zone.h"
@ -705,6 +706,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
{
faller->sector->ceilingheight = faller->ceilingwasheight;
faller->sector->floorheight = faller->floorwasheight;
R_ClearLevelInterpolatorState(&faller->thinker);
}
}
else // Up
@ -713,6 +715,7 @@ void T_ContinuousFalling(levelspecthink_t *faller)
{
faller->sector->ceilingheight = faller->ceilingwasheight;
faller->sector->floorheight = faller->floorwasheight;
R_ClearLevelInterpolatorState(&faller->thinker);
}
}
@ -2862,6 +2865,9 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
}
firstone = 0;
// interpolation
R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false);
}
return rtn;
@ -2995,6 +3001,10 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
default:
break;
}
// interpolation
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
}
return rtn;
}
@ -3089,6 +3099,10 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
bouncer->distance = FRACUNIT;
bouncer->low = 1;
// interpolation
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&bouncer->thinker, sec, true);
return 1;
#undef speed
#undef distance
@ -3135,6 +3149,10 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
faller->direction = -1;
}
// interpolation
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, true);
return 1;
#undef speed
#undef direction
@ -3210,6 +3228,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ);
}
// interpolation
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
return 1;
}
@ -3250,6 +3272,10 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
block->vars[5] = FRACUNIT; // distance
block->vars[6] = 1; // low
// interpolation
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, false);
R_CreateInterpolator_SectorPlane(&block->thinker, roversector, true);
if (itsamonitor)
{
oldx = thing->x;
@ -3258,9 +3284,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
}
P_UnsetThingPosition(thing);
thing->x = roversector->soundorg.x;
thing->y = roversector->soundorg.y;
thing->z = topheight;
thing->x = thing->old_x = roversector->soundorg.x;
thing->y = thing->old_y = roversector->soundorg.y;
thing->z = thing->old_z = topheight;
thing->momz = FixedMul(6*FRACUNIT, thing->scale);
P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE)
@ -3289,9 +3315,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
if (itsamonitor)
{
P_UnsetThingPosition(tmthing);
tmthing->x = oldx;
tmthing->y = oldy;
tmthing->z = oldz;
tmthing->x = thing->old_x = oldx;
tmthing->y = thing->old_y = oldy;
tmthing->z = thing->old_z = oldz;
tmthing->momx = 1;
tmthing->momy = 1;
P_SetThingPosition(tmthing);

View file

@ -348,7 +348,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!special->target)
return; // foolproof crash prevention check!!!!!
P_TeleportMove(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
P_SetOrigin(player->mo, special->target->x, special->target->y, special->target->z + (48<<FRACBITS));
player->mo->angle = special->target->angle;
P_SetObjectMomZ(player->mo, 12<<FRACBITS, false);
P_InstaThrust(player->mo, player->mo->angle, 20<<FRACBITS);

View file

@ -348,7 +348,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
boolean P_Move(mobj_t *actor, fixed_t speed);
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
void P_SlideMove(mobj_t *mo, boolean forceslide);
void P_BouncePlayerMove(mobj_t *mo);
void P_BounceMove(mobj_t *mo);

View file

@ -19,6 +19,7 @@
#include "m_random.h"
#include "p_local.h"
#include "p_setup.h" // NiGHTS stuff
#include "r_fps.h"
#include "r_state.h"
#include "r_main.h"
#include "r_sky.h"
@ -75,7 +76,7 @@ camera_t *mapcampointer;
//
// P_TeleportMove
//
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
{
// the move is ok,
// so link the thing into its new position
@ -105,6 +106,30 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
return true;
}
// P_SetOrigin - P_TeleportMove which RESETS interpolation values.
//
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
{
boolean result = P_TeleportMove(thing, x, y, z);
if (result == true)
{
thing->old_x = thing->x;
thing->old_y = thing->y;
thing->old_z = thing->z;
}
return result;
}
//
// P_MoveOrigin - P_TeleportMove which KEEPS interpolation values.
//
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
{
return P_TeleportMove(thing, x, y, z);
}
// =========================================================================
// MOVEMENT ITERATOR FUNCTIONS
// =========================================================================
@ -599,9 +624,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; // underneath
if (tmthing->eflags & MFE_VERTICALFLIP)
thing->z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
thing->z = thing->old_z = tmthing->z - thing->height - FixedMul(FRACUNIT, tmthing->scale);
else
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
thing->z = thing->old_z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, tmthing, tmthing, 1);
return true;
@ -1904,7 +1929,6 @@ if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a
if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld)
== P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld))
return true; // the line doesn't cross between collider's start or end
}
// A line has been hit

View file

@ -18,6 +18,7 @@
#include "hu_stuff.h"
#include "p_local.h"
#include "p_setup.h"
#include "r_fps.h"
#include "r_main.h"
#include "r_things.h"
#include "r_sky.h"
@ -3795,15 +3796,22 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
void P_SnowThinker(precipmobj_t *mobj)
{
R_ResetPrecipitationMobjInterpolationState(mobj);
P_CycleStateAnimation((mobj_t *)mobj);
// adjust height
if ((mobj->z += mobj->momz) <= mobj->floorz)
{
mobj->z = mobj->ceilingz;
R_ResetPrecipitationMobjInterpolationState(mobj);
}
}
void P_RainThinker(precipmobj_t *mobj)
{
R_ResetPrecipitationMobjInterpolationState(mobj);
P_CycleStateAnimation((mobj_t *)mobj);
if (mobj->state != &states[S_RAIN1])
@ -3823,6 +3831,7 @@ void P_RainThinker(precipmobj_t *mobj)
return;
mobj->z = mobj->ceilingz;
R_ResetPrecipitationMobjInterpolationState(mobj);
P_SetPrecipMobjState(mobj, S_RAIN1);
return;
@ -4405,7 +4414,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
while ((base = base->tracer))
{
for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s)
P_TeleportMove(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
P_MoveOrigin(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<<FRACBITS, 9<<FRACBITS)));
angle += ANGLE_MAX/3;
}
}
@ -5151,7 +5160,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->health > 3) {
mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2);
P_SetScale(mobj->tracer, mobj->tracer->destscale);
P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
P_SetOrigin(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2);
mobj->tracer->momx = mobj->momx;
mobj->tracer->momy = mobj->momy;
mobj->tracer->momz = mobj->momz;
@ -5821,9 +5830,9 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
// place us on top of them then.
source->momx = source->momy = source->momz = 0;
P_UnsetThingPosition(source);
source->x = tx;
source->y = ty;
source->z = tz;
source->x = source->old_x = tx;
source->y = source->old_y = ty;
source->z = source->old_z = tz;
P_SetThingPosition(source);
}
}
@ -6101,7 +6110,7 @@ void P_RunShadows(void)
if (dest->type == MT_THUNDERSHIELD)
dest = dest->target;
P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z);
P_MoveOrigin(mobj, dest->x, dest->y, mobj->target->z);
if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height))
|| (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z)))
@ -6119,7 +6128,7 @@ void P_RunShadows(void)
P_SetScale(mobj, FixedDiv(mobj->scale, max(FRACUNIT, ((mobj->target->z-mobj->z)/200)+FRACUNIT)));
// Check new position to see if you should still be on that ledge
P_TeleportMove(mobj, dest->x, dest->y, mobj->z);
P_MoveOrigin(mobj, dest->x, dest->y, mobj->z);
mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz);
@ -7000,7 +7009,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->target->eflags & MFE_VERTICALFLIP)
z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height);
P_TeleportMove(mobj, x, y, z);
P_MoveOrigin(mobj, x, y, z);
}
break;
default:
@ -7400,7 +7409,7 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height);
break;
case MT_HAMMER:
if (mobj->z <= mobj->floorz)
@ -8027,7 +8036,7 @@ void P_MobjThinker(mobj_t *mobj)
}
mobj->angle = mobj->target->angle;
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
P_SetScale(mobj, mobj->target->scale);
@ -8076,7 +8085,7 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
P_SetOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
break;
case MT_BRAKEDRIFT:
if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target))
@ -8096,7 +8105,7 @@ void P_MobjThinker(mobj_t *mobj)
newx = mobj->target->x + P_ReturnThrustX(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
newy = mobj->target->y + P_ReturnThrustY(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale);
P_TeleportMove(mobj, newx, newy, mobj->target->z);
P_MoveOrigin(mobj, newx, newy, mobj->target->z);
mobj->angle = travelangle - ((ANGLE_90/5)*mobj->target->player->kartstuff[k_drift]);
P_SetScale(mobj, (mobj->destscale = mobj->target->scale));
@ -8124,7 +8133,7 @@ void P_MobjThinker(mobj_t *mobj)
P_RemoveMobj(mobj);
return;
}
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
break;
case MT_INSTASHIELDB:
mobj->flags2 ^= MF2_DONTDRAW;
@ -8137,7 +8146,7 @@ void P_MobjThinker(mobj_t *mobj)
}
K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
break;
case MT_BATTLEPOINT:
if (!mobj->target || P_MobjWasRemoved(mobj->target))
@ -8159,7 +8168,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->movefactor = mobj->target->height;
}
K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
break;
case MT_THUNDERSHIELD:
{
@ -8194,7 +8203,7 @@ void P_MobjThinker(mobj_t *mobj)
desty = mobj->target->y;
}
P_TeleportMove(mobj, destx, desty, mobj->target->z);
P_MoveOrigin(mobj, destx, desty, mobj->target->z);
break;
}
case MT_ROCKETSNEAKER:
@ -8230,7 +8239,7 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->angle = mobj->target->angle;
mobj->scalespeed = mobj->target->scalespeed;
mobj->destscale = mobj->target->destscale;
@ -8291,7 +8300,7 @@ void P_MobjThinker(mobj_t *mobj)
if (cur->lastlook == 2 || cur->lastlook == 3)
offy *= -1;
P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z);
P_MoveOrigin(cur, mobj->x + offx, mobj->y + offy, mobj->z);
cur->scalespeed = mobj->target->scalespeed;
cur->destscale = mobj->target->destscale;
P_SetScale(cur, mobj->target->scale);
@ -8416,7 +8425,7 @@ void P_MobjThinker(mobj_t *mobj)
while (cur && !P_MobjWasRemoved(cur))
{
cur->angle += FixedAngle(mobj->info->speed);
P_TeleportMove(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
P_MoveOrigin(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT),
mobj->y + FINESINE((cur->angle*8)>>ANGLETOFINESHIFT), mobj->z);
//P_SpawnGhostMobj(cur)->tics = 2;
@ -8549,7 +8558,7 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1));
if (cur && !P_MobjWasRemoved(cur))
P_TeleportMove(cur, wx, wy, wz);
P_MoveOrigin(cur, wx, wy, wz);
else
cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT);
@ -8660,7 +8669,7 @@ void P_MobjThinker(mobj_t *mobj)
continue;
}
else // Move into place
P_TeleportMove(cur, mobj->x, mobj->y, segz);
P_MoveOrigin(cur, mobj->x, mobj->y, segz);
}
else
{
@ -8734,7 +8743,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->extravalue1 = 1;
player->kartstuff[k_offroad] += 2<<FRACBITS;
P_TeleportMove(mobj,
P_MoveOrigin(mobj,
player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius)
+ P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<<FRACBITS),
player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius)
@ -9855,7 +9864,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_SIDE);
P_SetTarget(&cur->target, mobj);
cur->threshold = i;
P_TeleportMove(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)), cur->z);
cur->angle = ANGLE_90*(cur->threshold+1);
@ -9925,6 +9934,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP))
P_CheckGravity(mobj, false);
R_AddMobjInterpolator(mobj);
return mobj;
}
@ -10038,6 +10049,8 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
P_SetTarget(&mobj->target, caster); // set the shadow's caster as the target
R_AddMobjInterpolator(mobj);
return mobj;
}
@ -10086,6 +10099,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|| mobj->subsector->sector->floorpic == skyflatnum)
mobj->precipflags |= PCF_PIT;
R_ResetPrecipitationMobjInterpolationState(mobj);
return mobj;
}
@ -10237,6 +10252,8 @@ void P_RemoveMobj(mobj_t *mobj)
#endif
P_RemoveThinker((thinker_t *)mobj);
}
R_RemoveMobjInterpolator(mobj);
}
// This does not need to be added to Lua.

View file

@ -274,6 +274,8 @@ typedef struct mobj_s
// Info for drawing: position.
fixed_t x, y, z;
fixed_t old_x, old_y, old_z; // position interpolation
fixed_t old_x2, old_y2, old_z2;
// More list: links in sector (if needed)
struct mobj_s *snext;
@ -281,6 +283,8 @@ typedef struct mobj_s
// More drawing info: to determine current sprite.
angle_t angle; // orientation
angle_t old_angle; // orientation interpolation
angle_t old_angle2;
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT16 anim_duration; // for FF_ANIMATE states
@ -356,6 +360,8 @@ typedef struct mobj_s
UINT32 mobjnum; // A unique number for this mobj. Used for restoring pointers on save games.
fixed_t scale;
fixed_t old_scale; // interpolation
fixed_t old_scale2;
fixed_t destscale;
fixed_t scalespeed;
@ -370,6 +376,7 @@ typedef struct mobj_s
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation)
boolean colorized; // Whether the mobj uses the rainbow colormap
// WARNING: New fields must be added separately to savegame and Lua.
@ -389,6 +396,8 @@ typedef struct precipmobj_s
// Info for drawing: position.
fixed_t x, y, z;
fixed_t old_x, old_y, old_z; // position interpolation
fixed_t old_x2, old_y2, old_z2;
// More list: links in sector (if needed)
struct precipmobj_s *snext;
@ -396,6 +405,8 @@ typedef struct precipmobj_s
// More drawing info: to determine current sprite.
angle_t angle; // orientation
angle_t old_angle; // orientation interpolation
angle_t old_angle2;
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT16 anim_duration; // for FF_ANIMATE states

View file

@ -24,6 +24,7 @@
#include "p_tick.h"
#include "p_local.h"
#include "p_polyobj.h"
#include "r_fps.h"
#include "r_main.h"
#include "r_state.h"
#include "r_defs.h"
@ -2367,6 +2368,9 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
th->turnobjs = prdata->turnobjs;
// apply action to mirroring polyobjects as well
@ -2428,6 +2432,9 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
@ -2443,12 +2450,14 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
{
polyobj_t *po;
polyobj_t *oldpo;
polywaypoint_t *th;
mobj_t *mo2;
mobj_t *first = NULL;
mobj_t *last = NULL;
mobj_t *target = NULL;
thinker_t *wp;
INT32 start;
if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
{
@ -2594,6 +2603,26 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
return 0;
}
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// T_PolyObjWaypoint is the only polyobject movement
// that can adjust z, so we add these ones too.
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
// Most other polyobject functions handle children by recursively
// giving each child another thinker. T_PolyObjWaypoint handles
// it manually though, which means we need to manually give them
// interpolation here instead.
start = 0;
oldpo = po;
while ((po = Polyobj_GetChild(oldpo, &start)))
{
R_CreateInterpolator_Polyobj(&th->thinker, po);
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, false);
R_CreateInterpolator_SectorPlane(&th->thinker, po->lines[0]->backsector, true);
}
// Set pointnum
th->pointnum = target->health;
@ -2645,6 +2674,9 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// start action on mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
@ -2685,6 +2717,9 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// start action on mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
@ -2756,6 +2791,9 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))
@ -2859,6 +2897,9 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
oldpo = po;
// interpolation
R_CreateInterpolator_Polyobj(&th->thinker, po);
// apply action to mirroring polyobjects as well
start = 0;
while ((po = Polyobj_GetChild(oldpo, &start)))

View file

@ -21,6 +21,7 @@
#include "p_local.h"
#include "p_setup.h"
#include "p_saveg.h"
#include "r_fps.h"
#include "r_things.h"
#include "r_state.h"
#include "w_wad.h"
@ -2163,6 +2164,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
P_SetTarget(&waypointcap, mobj);
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
R_AddMobjInterpolator(mobj);
}
//

View file

@ -21,6 +21,7 @@
#include "p_spec.h"
#include "p_saveg.h"
#include "i_time.h"
#include "i_sound.h" // for I_PlayCD()..
#include "i_video.h" // for I_FinishUpdate()..
#include "r_sky.h"
@ -30,6 +31,7 @@
#include "r_things.h"
#include "r_sky.h"
#include "r_draw.h"
#include "r_fps.h" // R_ResetViewInterpolation in level load
#include "s_sound.h"
#include "st_stuff.h"
@ -2909,7 +2911,10 @@ boolean P_SetupLevel(boolean skipprecip)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
{
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
@ -2988,7 +2993,10 @@ boolean P_SetupLevel(boolean skipprecip)
R_ClearLevelSplats();
#endif
R_InitializeLevelInterpolators();
P_InitThinkers();
R_InitMobjInterpolators();
P_InitCachedActions();
/// \note for not spawning precipitation, etc. when loading netgame snapshots

View file

@ -20,6 +20,7 @@
#include "p_local.h"
#include "p_setup.h" // levelflats for flat animation
#include "r_data.h"
#include "r_fps.h"
#include "m_random.h"
#include "p_mobj.h"
#include "i_system.h"
@ -2384,7 +2385,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
UINT8 i;
if (bot) // This might put poor Tails in a wall if he's too far behind! D: But okay, whatever! >:3
P_TeleportMove(bot, bot->x + x, bot->y + y, bot->z + z);
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
for (i = 0; i <= splitscreen; i++)
{
@ -2846,7 +2847,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// Reset bot too.
if (bot) {
if (line->flags & ML_NOCLIMB)
P_TeleportMove(bot, mo->x, mo->y, mo->z);
P_SetOrigin(bot, mo->x, mo->y, mo->z);
bot->momx = bot->momy = bot->momz = 1;
bot->pmomz = 0;
bot->player->rmomx = bot->player->rmomy = 1;
@ -2890,7 +2891,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// (Teleport them to you so they don't break it.)
if (bot && (bot->flags2 & MF2_TWOD) != (mo->flags2 & MF2_TWOD)) {
bot->flags2 = (bot->flags2 & ~MF2_TWOD) | (mo->flags2 & MF2_TWOD);
P_TeleportMove(bot, mo->x, mo->y, mo->z);
P_SetOrigin(bot, mo->x, mo->y, mo->z);
}
}
break;
@ -5277,6 +5278,10 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
floater->sector = sec;
floater->vars[0] = tag;
floater->sourceline = sourceline;
// interpolation
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&floater->thinker, sec, true);
}
/** Adds a bridge thinker.
@ -5309,6 +5314,9 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
// Control sector tags should be End_Tag + (End_Tag - Start_Tag)
bridge->vars[4] = sourceline->tag; // Start tag
bridge->vars[5] = (sides[sourceline->sidenum[0]].textureoffset>>FRACBITS); // End tag
// interpolation
R_CreateInterpolator_SectorPlane(&bridge->thinker, &sectors[affectee], false);
}
*/
@ -5388,6 +5396,10 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
- (sec->ceilingheight - sec->floorheight);
raise->sourceline = sourceline;
// interpolation
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, true);
}
// Function to maintain backwards compatibility
@ -5430,6 +5442,10 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
- (sec->ceilingheight - sec->floorheight);
airbob->sourceline = sourceline;
// interpolation
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, true);
}
/** Adds a thwomp thinker.
@ -5471,6 +5487,11 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
thwomp->sourceline = sourceline;
thwomp->sector->floordata = thwomp;
thwomp->sector->ceilingdata = thwomp;
// interpolation
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, true);
return;
#undef speed
#undef direction
@ -7036,6 +7057,22 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
s->affectee = affectee;
P_AddThinker(&s->thinker);
// interpolation
switch (type)
{
case sc_side:
R_CreateInterpolator_SideScroll(&s->thinker, &sides[affectee]);
break;
case sc_floor:
R_CreateInterpolator_SectorScroll(&s->thinker, &sectors[affectee], false);
break;
case sc_ceiling:
R_CreateInterpolator_SectorScroll(&s->thinker, &sectors[affectee], true);
break;
default:
break;
}
}
/** Adds a wall scroller.

View file

@ -128,7 +128,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
{
UINT8 i;
if (!P_TeleportMove(thing, x, y, z))
if (!P_SetOrigin(thing, x, y, z))
return false;
thing->angle = angle;

View file

@ -23,6 +23,7 @@
#include "lua_script.h"
#include "lua_hook.h"
#include "k_kart.h"
#include "r_fps.h"
// Object place
#include "m_cheat.h"
@ -582,8 +583,10 @@ void P_Ticker(boolean run)
if (OP_FreezeObjectplace())
{
P_MapStart();
R_UpdateMobjInterpolators();
OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera[0], false);
R_UpdateViewInterpolation();
P_MapEnd();
return;
}
@ -610,6 +613,8 @@ void P_Ticker(boolean run)
if (run)
{
R_UpdateMobjInterpolators();
if (demo.recording)
{
G_WriteDemoExtraData();
@ -796,6 +801,12 @@ void P_Ticker(boolean run)
P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false);
}
if (run)
{
R_UpdateLevelInterpolators();
R_UpdateViewInterpolation();
}
P_MapEnd();
if (demo.playback)
@ -819,6 +830,8 @@ void P_PreTicker(INT32 frames)
{
P_MapStart();
R_UpdateMobjInterpolators();
#ifdef HAVE_BLUA
LUAh_PreThinkFrame();
#endif
@ -861,6 +874,10 @@ void P_PreTicker(INT32 frames)
LUAh_PostThinkFrame();
#endif
R_UpdateLevelInterpolators();
R_UpdateViewInterpolation();
R_ResetViewInterpolation(0);
P_MapEnd();
hook_defrosting--;

View file

@ -20,6 +20,7 @@
#include "d_net.h"
#include "g_game.h"
#include "p_local.h"
#include "r_fps.h"
#include "r_main.h"
#include "s_sound.h"
#include "r_things.h"
@ -1683,6 +1684,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
if (!(mobj->flags & MF_DONTENCOREMAP))
mobj->flags &= ~MF_DONTENCOREMAP;
// Copy interpolation data :)
ghost->old_x = mobj->old_x2;
ghost->old_y = mobj->old_y2;
ghost->old_z = mobj->old_z2;
ghost->old_angle = (mobj->player ? mobj->player->old_frameangle2 : mobj->old_angle2);
return ghost;
}
@ -7985,7 +7992,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
if (lookbackdown)
{
P_MoveChaseCamera(player, thiscam, false);
R_ResetViewInterpolation(num + 1);
R_ResetViewInterpolation(num + 1);
}
return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming);
}
@ -9102,7 +9113,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->momx = (player->mo->tracer->x - player->mo->x)*2;
player->mo->momy = (player->mo->tracer->y - player->mo->y)*2;
player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2;
P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
P_MoveOrigin(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
player->pflags |= PF_JUMPED;
player->secondjump = 0;
player->pflags &= ~PF_THOKKED;

View file

@ -831,6 +831,7 @@ static void R_Subsector(size_t num)
extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap;
fixed_t floorcenterz, ceilingcenterz;
ffloor_t *rover;
#ifdef RANGECHECK
if (num >= numsubsectors)
@ -862,7 +863,23 @@ static void R_Subsector(size_t num)
// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
if (frontsector->ffloors)
{
if (frontsector->moved)
boolean anyMoved = frontsector->moved;
if (anyMoved == false)
{
for (rover = frontsector->ffloors; rover; rover = rover->next)
{
sector_t *controlSec = &sectors[rover->secnum];
if (controlSec->moved == true)
{
anyMoved = true;
break;
}
}
}
if (anyMoved == true)
{
frontsector->numlights = sub->sector->numlights = 0;
R_Prep3DFloors(frontsector);
@ -919,7 +936,6 @@ static void R_Subsector(size_t num)
ffloor[numffloors].polyobj = NULL;
if (frontsector->ffloors)
{
ffloor_t *rover;
fixed_t heightcheck, planecenterz;
for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next)

762
src/r_fps.c Normal file
View file

@ -0,0 +1,762 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
// Copyright (C) 1999-2019 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_fps.h
/// \brief Uncapped framerate stuff.
#include "r_fps.h"
#include "r_main.h"
#include "g_game.h"
#include "i_video.h"
#include "r_plane.h"
#include "p_spec.h"
#include "r_state.h"
#include "z_zone.h"
#include "console.h" // con_startup_loadprogress
static CV_PossibleValue_t fpscap_cons_t[] = {
#ifdef DEVELOP
// Lower values are actually pretty useful for debugging interp problems!
{1, "MIN"},
#else
{TICRATE, "MIN"},
#endif
{300, "MAX"},
{-1, "Unlimited"},
{0, "Match refresh rate"},
{0, NULL}
};
consvar_t cv_fpscap = {"fpscap", "Match refresh rate", CV_SAVE, fpscap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
UINT32 R_GetFramerateCap(void)
{
if (rendermode == render_none)
{
// If we're not rendering (dedicated server),
// we shouldn't be using any interpolation.
return TICRATE;
}
if (cv_fpscap.value == 0)
{
// 0: Match refresh rate
return I_GetRefreshRate();
}
if (cv_fpscap.value < 0)
{
// -1: Unlimited
return 0;
}
return cv_fpscap.value;
}
boolean R_UsingFrameInterpolation(void)
{
return (R_GetFramerateCap() != TICRATE || cv_timescale.value < FRACUNIT);
}
static viewvars_t pview_old[MAXSPLITSCREENPLAYERS];
static viewvars_t pview_new[MAXSPLITSCREENPLAYERS];
static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS];
static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS];
static viewvars_t *oldview = &pview_old[0];
static int oldview_invalid[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 from + FixedMul(frac, to - from);
}
static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac)
{
return from + FixedMul(frac, to - from);
}
static vector2_t *R_LerpVector2(const vector2_t *from, const vector2_t *to, fixed_t frac, vector2_t *out)
{
FV2_SubEx(to, from, out);
FV2_MulEx(out, frac, out);
FV2_AddEx(from, out, out);
return out;
}
static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixed_t frac, vector3_t *out)
{
FV3_SubEx(to, from, out);
FV3_MulEx(out, frac, out);
FV3_AddEx(from, out, out);
return out;
}
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
static void R_SetupFreelook(player_t *player, boolean skybox)
{
(void)player;
(void)skybox;
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
if (rendermode == render_soft)
{
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
}
centeryfrac = (viewheight/2)<<FRACBITS;
if (rendermode == render_soft)
centeryfrac += FixedMul(AIMINGTODY(aimingangle), FixedDiv(viewwidth<<FRACBITS, BASEVIDWIDTH<<FRACBITS));
centery = FixedInt(FixedRound(centeryfrac));
if (rendermode == render_soft)
yslope = &yslopetab[viewheight*8 - centery];
}
#undef AIMINGTODY
void R_InterpolateView(fixed_t frac)
{
viewvars_t* prevview = oldview;
boolean skybox = 0;
UINT8 i;
if (FIXED_TO_FLOAT(frac) < 0)
frac = 0;
if (frac > FRACUNIT)
frac = FRACUNIT;
if (viewcontext >= VIEWCONTEXT_SKY1)
{
i = viewcontext - VIEWCONTEXT_SKY1;
}
else
{
i = viewcontext - VIEWCONTEXT_PLAYER1;
}
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);
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
// this is gonna create some interesting visual errors for long distance teleports...
// might want to recalculate the view sector every frame instead...
viewplayer = newview->player;
viewsector = R_PointInSubsector(viewx, viewy)->sector;
R_SetupFreelook(newview->player, skybox);
}
void R_UpdateViewInterpolation(void)
{
UINT8 i;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
pview_old[i] = pview_new[i];
skyview_old[i] = skyview_new[i];
if (oldview_invalid[i]) 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]++;
}
}
void R_SetViewContext(enum viewcontext_e _viewcontext)
{
UINT8 i = 0;
I_Assert(_viewcontext >= VIEWCONTEXT_PLAYER1
&& _viewcontext <= VIEWCONTEXT_SKY4);
viewcontext = _viewcontext;
switch (viewcontext)
{
case VIEWCONTEXT_PLAYER1:
case VIEWCONTEXT_PLAYER2:
case VIEWCONTEXT_PLAYER3:
case VIEWCONTEXT_PLAYER4:
i = viewcontext - VIEWCONTEXT_PLAYER1;
oldview = &pview_old[i];
newview = &pview_new[i];
break;
case VIEWCONTEXT_SKY1:
case VIEWCONTEXT_SKY2:
case VIEWCONTEXT_SKY3:
case VIEWCONTEXT_SKY4:
i = viewcontext - VIEWCONTEXT_SKY1;
oldview = &skyview_old[i];
newview = &skyview_new[i];
break;
default:
I_Error("viewcontext value is invalid: we should never get here without an assert!!");
break;
}
}
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
{
if (!R_UsingFrameInterpolation())
{
return to;
}
return (R_LerpFixed(from, to, rendertimefrac));
}
angle_t R_InterpolateAngle(angle_t from, angle_t to)
{
if (!R_UsingFrameInterpolation())
{
return to;
}
return (R_LerpAngle(from, to, rendertimefrac));
}
void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
{
if (frac == FRACUNIT)
{
out->x = mobj->x;
out->y = mobj->y;
out->z = mobj->z;
out->scale = mobj->scale;
out->subsector = mobj->subsector;
out->angle = mobj->player ? mobj->player->frameangle : mobj->angle;
return;
}
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
out->subsector = R_PointInSubsector(out->x, out->y);
if (mobj->player)
{
out->angle = mobj->resetinterp ? mobj->player->frameangle : R_LerpAngle(mobj->player->old_frameangle, mobj->player->frameangle, frac);
}
else
{
out->angle = mobj->resetinterp ? mobj->angle : R_LerpAngle(mobj->old_angle, mobj->angle, frac);
}
}
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
{
if (frac == FRACUNIT)
{
out->x = mobj->x;
out->y = mobj->y;
out->z = mobj->z;
out->scale = FRACUNIT;
out->subsector = mobj->subsector;
out->angle = mobj->angle;
return;
}
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->scale = FRACUNIT;
out->subsector = R_PointInSubsector(out->x, out->y);
out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac);
}
static void AddInterpolator(levelinterpolator_t* interpolator)
{
if (levelinterpolators_len >= levelinterpolators_size)
{
if (levelinterpolators_size == 0)
{
levelinterpolators_size = 128;
}
else
{
levelinterpolators_size *= 2;
}
levelinterpolators = Z_ReallocAlign(
(void*) levelinterpolators,
sizeof(levelinterpolator_t*) * levelinterpolators_size,
PU_LEVEL,
NULL,
sizeof(levelinterpolator_t*) * 8
);
}
levelinterpolators[levelinterpolators_len] = interpolator;
levelinterpolators_len += 1;
}
static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker)
{
levelinterpolator_t *ret = (levelinterpolator_t*) Z_CallocAlign(
sizeof(levelinterpolator_t),
PU_LEVEL,
NULL,
sizeof(levelinterpolator_t) * 8
);
ret->type = type;
ret->thinker = thinker;
AddInterpolator(ret);
return ret;
}
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorPlane, thinker);
interp->sectorplane.sector = sector;
interp->sectorplane.ceiling = ceiling;
if (ceiling)
{
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->ceilingheight;
}
else
{
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->floorheight;
}
}
void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorScroll, thinker);
interp->sectorscroll.sector = sector;
interp->sectorscroll.ceiling = ceiling;
if (ceiling)
{
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->ceiling_xoffs;
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->ceiling_yoffs;
}
else
{
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->floor_xoffs;
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->floor_yoffs;
}
}
void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SideScroll, thinker);
interp->sidescroll.side = side;
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset = side->textureoffset;
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset = side->rowoffset;
}
void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_Polyobj, thinker);
interp->polyobj.polyobj = polyobj;
interp->polyobj.vertices_size = polyobj->numVertices;
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
for (size_t i = 0; i < polyobj->numVertices; i++)
{
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1] = polyobj->vertices[i]->y;
}
interp->polyobj.oldcx = interp->polyobj.bakcx = polyobj->centerPt.x;
interp->polyobj.oldcy = interp->polyobj.bakcy = polyobj->centerPt.y;
}
void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_DynSlope, thinker);
interp->dynslope.slope = slope;
FV3_Copy(&interp->dynslope.oldo, &slope->o);
FV3_Copy(&interp->dynslope.bako, &slope->o);
FV2_Copy(&interp->dynslope.oldd, &slope->d);
FV2_Copy(&interp->dynslope.bakd, &slope->d);
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
}
void R_InitializeLevelInterpolators(void)
{
levelinterpolators_len = 0;
levelinterpolators_size = 0;
levelinterpolators = NULL;
}
static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
{
size_t i;
switch (interp->type)
{
case LVLINTERP_SectorPlane:
interp->sectorplane.oldheight = interp->sectorplane.bakheight;
interp->sectorplane.bakheight = interp->sectorplane.ceiling ? interp->sectorplane.sector->ceilingheight : interp->sectorplane.sector->floorheight;
break;
case LVLINTERP_SectorScroll:
interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs;
interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floor_xoffs;
interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs;
interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->floor_yoffs;
break;
case LVLINTERP_SideScroll:
interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset;
interp->sidescroll.baktextureoffset = interp->sidescroll.side->textureoffset;
interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset;
interp->sidescroll.bakrowoffset = interp->sidescroll.side->rowoffset;
break;
case LVLINTERP_Polyobj:
for (i = 0; i < interp->polyobj.vertices_size; i++)
{
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ];
interp->polyobj.oldvertices[i * 2 + 1] = interp->polyobj.bakvertices[i * 2 + 1];
interp->polyobj.bakvertices[i * 2 ] = interp->polyobj.polyobj->vertices[i]->x;
interp->polyobj.bakvertices[i * 2 + 1] = interp->polyobj.polyobj->vertices[i]->y;
}
interp->polyobj.oldcx = interp->polyobj.bakcx;
interp->polyobj.oldcy = interp->polyobj.bakcy;
interp->polyobj.bakcx = interp->polyobj.polyobj->centerPt.x;
interp->polyobj.bakcy = interp->polyobj.polyobj->centerPt.y;
break;
case LVLINTERP_DynSlope:
FV3_Copy(&interp->dynslope.oldo, &interp->dynslope.bako);
FV2_Copy(&interp->dynslope.oldd, &interp->dynslope.bakd);
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta;
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
break;
}
}
void R_UpdateLevelInterpolators(void)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
UpdateLevelInterpolatorState(interp);
}
}
void R_ClearLevelInterpolatorState(thinker_t *thinker)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
if (interp->thinker == thinker)
{
// Do it twice to make the old state match the new
UpdateLevelInterpolatorState(interp);
UpdateLevelInterpolatorState(interp);
}
}
}
void R_ApplyLevelInterpolators(fixed_t frac)
{
size_t i, ii;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
switch (interp->type)
{
case LVLINTERP_SectorPlane:
if (interp->sectorplane.ceiling)
{
interp->sectorplane.sector->ceilingheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
}
else
{
interp->sectorplane.sector->floorheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
}
interp->sectorplane.sector->moved = true;
break;
case LVLINTERP_SectorScroll:
if (interp->sectorscroll.ceiling)
{
interp->sectorscroll.sector->ceiling_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
interp->sectorscroll.sector->ceiling_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
}
else
{
interp->sectorscroll.sector->floor_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac);
interp->sectorscroll.sector->floor_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac);
}
break;
case LVLINTERP_SideScroll:
interp->sidescroll.side->textureoffset = R_LerpFixed(interp->sidescroll.oldtextureoffset, interp->sidescroll.baktextureoffset, frac);
interp->sidescroll.side->rowoffset = R_LerpFixed(interp->sidescroll.oldrowoffset, interp->sidescroll.bakrowoffset, frac);
break;
case LVLINTERP_Polyobj:
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
{
interp->polyobj.polyobj->vertices[ii]->x = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 ], interp->polyobj.bakvertices[ii * 2 ], frac);
interp->polyobj.polyobj->vertices[ii]->y = R_LerpFixed(interp->polyobj.oldvertices[ii * 2 + 1], interp->polyobj.bakvertices[ii * 2 + 1], frac);
}
interp->polyobj.polyobj->centerPt.x = R_LerpFixed(interp->polyobj.oldcx, interp->polyobj.bakcx, frac);
interp->polyobj.polyobj->centerPt.y = R_LerpFixed(interp->polyobj.oldcy, interp->polyobj.bakcy, frac);
break;
case LVLINTERP_DynSlope:
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
break;
}
}
}
void R_RestoreLevelInterpolators(void)
{
size_t i, ii;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
switch (interp->type)
{
case LVLINTERP_SectorPlane:
if (interp->sectorplane.ceiling)
{
interp->sectorplane.sector->ceilingheight = interp->sectorplane.bakheight;
}
else
{
interp->sectorplane.sector->floorheight = interp->sectorplane.bakheight;
}
interp->sectorplane.sector->moved = true;
break;
case LVLINTERP_SectorScroll:
if (interp->sectorscroll.ceiling)
{
interp->sectorscroll.sector->ceiling_xoffs = interp->sectorscroll.bakxoffs;
interp->sectorscroll.sector->ceiling_yoffs = interp->sectorscroll.bakyoffs;
}
else
{
interp->sectorscroll.sector->floor_xoffs = interp->sectorscroll.bakxoffs;
interp->sectorscroll.sector->floor_yoffs = interp->sectorscroll.bakyoffs;
}
break;
case LVLINTERP_SideScroll:
interp->sidescroll.side->textureoffset = interp->sidescroll.baktextureoffset;
interp->sidescroll.side->rowoffset = interp->sidescroll.bakrowoffset;
break;
case LVLINTERP_Polyobj:
for (ii = 0; ii < interp->polyobj.vertices_size; ii++)
{
interp->polyobj.polyobj->vertices[ii]->x = interp->polyobj.bakvertices[ii * 2 ];
interp->polyobj.polyobj->vertices[ii]->y = interp->polyobj.bakvertices[ii * 2 + 1];
}
interp->polyobj.polyobj->centerPt.x = interp->polyobj.bakcx;
interp->polyobj.polyobj->centerPt.y = interp->polyobj.bakcy;
break;
case LVLINTERP_DynSlope:
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
break;
}
}
}
void R_DestroyLevelInterpolators(thinker_t *thinker)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
if (interp->thinker == thinker)
{
// Swap the tail of the level interpolators to this spot
levelinterpolators[i] = levelinterpolators[levelinterpolators_len - 1];
levelinterpolators_len -= 1;
Z_Free(interp);
i -= 1;
}
}
}
static mobj_t **interpolated_mobjs = NULL;
static size_t interpolated_mobjs_len = 0;
static size_t interpolated_mobjs_capacity = 0;
// NOTE: This will NOT check that the mobj has already been added, for perf
// reasons.
void R_AddMobjInterpolator(mobj_t *mobj)
{
if (interpolated_mobjs_len >= interpolated_mobjs_capacity)
{
if (interpolated_mobjs_capacity == 0)
{
interpolated_mobjs_capacity = 256;
}
else
{
interpolated_mobjs_capacity *= 2;
}
interpolated_mobjs = Z_ReallocAlign(
interpolated_mobjs,
sizeof(mobj_t *) * interpolated_mobjs_capacity,
PU_LEVEL,
NULL,
64
);
}
interpolated_mobjs[interpolated_mobjs_len] = mobj;
interpolated_mobjs_len += 1;
R_ResetMobjInterpolationState(mobj);
mobj->resetinterp = true;
}
void R_RemoveMobjInterpolator(mobj_t *mobj)
{
size_t i;
if (interpolated_mobjs_len == 0) return;
for (i = 0; i < interpolated_mobjs_len - 1; i++)
{
if (interpolated_mobjs[i] == mobj)
{
interpolated_mobjs[i] = interpolated_mobjs[
interpolated_mobjs_len - 1
];
interpolated_mobjs_len -= 1;
return;
}
}
}
void R_InitMobjInterpolators(void)
{
// apparently it's not acceptable to free something already unallocated
// Z_Free(interpolated_mobjs);
interpolated_mobjs = NULL;
interpolated_mobjs_len = 0;
interpolated_mobjs_capacity = 0;
}
void R_UpdateMobjInterpolators(void)
{
size_t i;
for (i = 0; i < interpolated_mobjs_len; i++)
{
mobj_t *mobj = interpolated_mobjs[i];
if (!P_MobjWasRemoved(mobj))
R_ResetMobjInterpolationState(mobj);
}
}
//
// P_ResetMobjInterpolationState
//
// Reset the rendering interpolation state of the mobj.
//
void R_ResetMobjInterpolationState(mobj_t *mobj)
{
mobj->old_x2 = mobj->old_x;
mobj->old_y2 = mobj->old_y;
mobj->old_z2 = mobj->old_z;
mobj->old_angle2 = mobj->old_angle;
mobj->old_scale2 = mobj->old_scale;
mobj->old_x = mobj->x;
mobj->old_y = mobj->y;
mobj->old_z = mobj->z;
mobj->old_angle = mobj->angle;
mobj->old_scale = mobj->scale;
if (mobj->player)
{
mobj->player->old_frameangle2 = mobj->player->old_frameangle;
mobj->player->old_frameangle = mobj->player->frameangle;
}
mobj->resetinterp = false;
}
//
// P_ResetPrecipitationMobjInterpolationState
//
// Reset the rendering interpolation state of the precipmobj.
//
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj)
{
mobj->old_x2 = mobj->old_x;
mobj->old_y2 = mobj->old_y;
mobj->old_z2 = mobj->old_z;
mobj->old_angle2 = mobj->old_angle;
mobj->old_x = mobj->x;
mobj->old_y = mobj->y;
mobj->old_z = mobj->z;
mobj->old_angle = mobj->angle;
}

158
src/r_fps.h Normal file
View file

@ -0,0 +1,158 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
// Copyright (C) 1999-2019 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_fps.h
/// \brief Uncapped framerate stuff.
#ifndef __R_FPS_H__
#define __R_FPS_H__
#include "m_fixed.h"
#include "p_local.h"
#include "r_state.h"
extern consvar_t cv_fpscap;
UINT32 R_GetFramerateCap(void);
boolean R_UsingFrameInterpolation(void);
enum viewcontext_e
{
VIEWCONTEXT_PLAYER1 = 0,
VIEWCONTEXT_PLAYER2,
VIEWCONTEXT_PLAYER3,
VIEWCONTEXT_PLAYER4,
VIEWCONTEXT_SKY1,
VIEWCONTEXT_SKY2,
VIEWCONTEXT_SKY3,
VIEWCONTEXT_SKY4
};
typedef struct {
fixed_t x;
fixed_t y;
fixed_t z;
boolean sky;
sector_t *sector;
player_t *player;
angle_t angle;
angle_t aim;
fixed_t cos;
fixed_t sin;
mobj_t *mobj;
} viewvars_t;
extern viewvars_t *newview;
typedef struct {
fixed_t x;
fixed_t y;
fixed_t z;
subsector_t *subsector;
angle_t angle;
fixed_t scale;
} interpmobjstate_t;
// Level interpolators
// The union tag for levelinterpolator_t
typedef enum {
LVLINTERP_SectorPlane,
LVLINTERP_SectorScroll,
LVLINTERP_SideScroll,
LVLINTERP_Polyobj,
LVLINTERP_DynSlope,
} levelinterpolator_type_e;
// Tagged union of a level interpolator
typedef struct levelinterpolator_s {
levelinterpolator_type_e type;
thinker_t *thinker;
union {
struct {
sector_t *sector;
fixed_t oldheight;
fixed_t bakheight;
boolean ceiling;
} sectorplane;
struct {
sector_t *sector;
fixed_t oldxoffs, oldyoffs, bakxoffs, bakyoffs;
boolean ceiling;
} sectorscroll;
struct {
side_t *side;
fixed_t oldtextureoffset, oldrowoffset, baktextureoffset, bakrowoffset;
} sidescroll;
struct {
polyobj_t *polyobj;
fixed_t *oldvertices;
fixed_t *bakvertices;
size_t vertices_size;
fixed_t oldcx, oldcy, bakcx, bakcy;
} polyobj;
struct {
pslope_t *slope;
vector3_t oldo, bako;
vector2_t oldd, bakd;
fixed_t oldzdelta, bakzdelta;
} dynslope;
};
} levelinterpolator_t;
// Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext
void R_InterpolateView(fixed_t frac);
// Buffer the current new views into the old views. Call once after each real tic.
void R_UpdateViewInterpolation(void);
// Reset the view states (e.g. after level load) so R_InterpolateView doesn't interpolate invalid data
void R_ResetViewInterpolation(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

View file

@ -31,6 +31,7 @@
#include "z_zone.h"
#include "m_random.h" // quake camera shake
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#include "r_fps.h" // Frame interpolation/uncapped
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -68,7 +69,7 @@ fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle;
UINT8 viewssnum;
fixed_t viewcos, viewsin;
boolean viewsky, skyVisible;
boolean skyVisible;
boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player
sector_t *viewsector;
player_t *viewplayer;
@ -99,6 +100,10 @@ portal_pair *portal_base, *portal_cap;
line_t *portalclipline;
INT32 portalclipstart, portalclipend;
fixed_t rendertimefrac;
fixed_t renderdeltatics;
boolean renderisnewtic;
//
// precalculated math tables
//
@ -793,31 +798,6 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y)
static mobj_t *viewmobj;
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
static void R_SetupFreelook(void)
{
INT32 dy = 0;
// clip it in the case we are looking a hardware 90 degrees full aiming
// (lmps, network and use F12...)
if (rendermode == render_soft
#ifdef HWRENDER
|| cv_grshearing.value
#endif
)
G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
if (rendermode == render_soft)
{
dy = (AIMINGTODY(aimingangle)/fovtan) * viewwidth/BASEVIDWIDTH;
yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
}
centery = (viewheight/2) + dy;
centeryfrac = centery<<FRACBITS;
}
void R_SkyboxFrame(player_t *player)
{
camera_t *thiscam = &camera[0];
@ -830,13 +810,18 @@ void R_SkyboxFrame(player_t *player)
if (player == &players[displayplayers[i]])
{
thiscam = &camera[i];
R_SetViewContext(VIEWCONTEXT_SKY1 + i);
break;
}
}
}
else
{
R_SetViewContext(VIEWCONTEXT_SKY1);
}
// cut-away view stuff
viewsky = true;
newview->sky = true;
viewmobj = skyboxmo[0];
#ifdef PARANOIA
if (!viewmobj)
@ -847,24 +832,24 @@ void R_SkyboxFrame(player_t *player)
#endif
if (player->awayviewtics)
{
aimingangle = player->awayviewaiming;
viewangle = player->awayviewmobj->angle;
newview->aim = player->awayviewaiming;
newview->angle = player->awayviewmobj->angle;
}
else if (thiscam->chase)
{
aimingangle = thiscam->aiming;
viewangle = thiscam->angle;
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else
{
aimingangle = player->aiming;
viewangle = player->mo->angle;
newview->aim = player->aiming;
newview->angle = player->mo->angle;
if (/*!demo.playback && */player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{
viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming[0];
newview->angle = localangle[0]; // WARNING: camera uses this
newview->aim = localaiming[0];
}
else if (splitscreen)
{
@ -872,27 +857,27 @@ void R_SkyboxFrame(player_t *player)
{
if (player == &players[displayplayers[i]])
{
viewangle = localangle[i];
aimingangle = localaiming[i];
newview->angle = localangle[i];
newview->aim = localaiming[i];
break;
}
}
}
}
}
viewangle += viewmobj->angle;
newview->angle += viewmobj->angle;
viewplayer = player;
newview->player = player;
viewx = viewmobj->x;
viewy = viewmobj->y;
viewz = 0;
newview->x = viewmobj->x;
newview->y = viewmobj->y;
newview->z = 0;
if (viewmobj->spawnpoint)
viewz = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
viewx += quake.x;
viewy += quake.y;
viewz += quake.z;
newview->x += quake.x;
newview->y += quake.y;
newview->z += quake.z;
if (mapheaderinfo[gamemap-1])
{
@ -914,35 +899,35 @@ void R_SkyboxFrame(player_t *player)
if (viewmobj->angle == 0)
{
viewx += x;
viewy += y;
newview->x += x;
newview->y += y;
}
else if (viewmobj->angle == ANGLE_90)
{
viewx -= y;
viewy += x;
newview->x -= y;
newview->y += x;
}
else if (viewmobj->angle == ANGLE_180)
{
viewx -= x;
viewy -= y;
newview->x -= x;
newview->y -= y;
}
else if (viewmobj->angle == ANGLE_270)
{
viewx += y;
viewy -= x;
newview->x += y;
newview->y -= x;
}
else
{
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
}
if (mh->skybox_scalez > 0)
viewz += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
viewz += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
newview->z += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez;
}
else if (thiscam->chase)
{
@ -961,35 +946,35 @@ void R_SkyboxFrame(player_t *player)
if (viewmobj->angle == 0)
{
viewx += x;
viewy += y;
newview->x += x;
newview->y += y;
}
else if (viewmobj->angle == ANGLE_90)
{
viewx -= y;
viewy += x;
newview->x -= y;
newview->y += x;
}
else if (viewmobj->angle == ANGLE_180)
{
viewx -= x;
viewy -= y;
newview->x -= x;
newview->y -= y;
}
else if (viewmobj->angle == ANGLE_270)
{
viewx += y;
viewy -= x;
newview->x += y;
newview->y -= x;
}
else
{
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
}
if (mh->skybox_scalez > 0)
viewz += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
newview->z += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
viewz += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
newview->z += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez;
}
else
{
@ -1007,47 +992,47 @@ void R_SkyboxFrame(player_t *player)
if (viewmobj->angle == 0)
{
viewx += x;
viewy += y;
newview->x += x;
newview->y += y;
}
else if (viewmobj->angle == ANGLE_90)
{
viewx -= y;
viewy += x;
newview->x -= y;
newview->y += x;
}
else if (viewmobj->angle == ANGLE_180)
{
viewx -= x;
viewy -= y;
newview->x -= x;
newview->y -= y;
}
else if (viewmobj->angle == ANGLE_270)
{
viewx += y;
viewy -= x;
newview->x += y;
newview->y -= x;
}
else
{
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
}
}
if (mh->skybox_scalez > 0)
viewz += player->viewz / mh->skybox_scalez;
newview->z += player->viewz / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
viewz += player->viewz * -mh->skybox_scalez;
newview->z += player->viewz * -mh->skybox_scalez;
}
}
if (viewmobj->subsector)
viewsector = viewmobj->subsector->sector;
newview->sector = viewmobj->subsector->sector;
else
viewsector = R_PointInSubsector(viewx, viewy)->sector;
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_SetupFreelook();
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
}
void R_SetupFrame(player_t *player, boolean skybox)
@ -1059,21 +1044,25 @@ void R_SetupFrame(player_t *player, boolean skybox)
{
thiscam = &camera[3];
chasecam = (cv_chasecam4.value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER4);
}
else if (splitscreen > 1 && player == &players[displayplayers[2]])
{
thiscam = &camera[2];
chasecam = (cv_chasecam3.value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER3);
}
else if (splitscreen && player == &players[displayplayers[1]])
{
thiscam = &camera[1];
chasecam = (cv_chasecam2.value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER2);
}
else
{
thiscam = &camera[0];
chasecam = (cv_chasecam.value != 0);
R_SetViewContext(VIEWCONTEXT_PLAYER1);
}
if (player->spectator) // no spectator chasecam
@ -1089,41 +1078,41 @@ void R_SetupFrame(player_t *player, boolean skybox)
else if (!chasecam)
thiscam->chase = false;
viewsky = !skybox;
newview->sky = !skybox;
if (player->awayviewtics)
{
// cut-away view stuff
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(viewmobj != NULL);
viewz = viewmobj->z + 20*FRACUNIT;
aimingangle = player->awayviewaiming;
viewangle = viewmobj->angle;
newview->z = viewmobj->z + 20*FRACUNIT;
newview->aim = player->awayviewaiming;
newview->angle = viewmobj->angle;
}
else if (!player->spectator && chasecam)
// use outside cam view
{
viewmobj = NULL;
viewz = thiscam->z + (thiscam->height>>1);
aimingangle = thiscam->aiming;
viewangle = thiscam->angle;
newview->z = thiscam->z + (thiscam->height>>1);
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else
// use the player's eyes view
{
viewz = player->viewz;
newview->z = player->viewz;
viewmobj = player->mo;
I_Assert(viewmobj != NULL);
aimingangle = player->aiming;
viewangle = viewmobj->angle;
newview->aim = player->aiming;
newview->angle = viewmobj->angle;
if (!demo.playback && player->playerstate != PST_DEAD)
{
if (player == &players[consoleplayer])
{
viewangle = localangle[0]; // WARNING: camera uses this
aimingangle = localaiming[0];
newview->angle = localangle[0]; // WARNING: camera uses this
newview->aim = localaiming[0];
}
else if (splitscreen)
{
@ -1132,47 +1121,47 @@ void R_SetupFrame(player_t *player, boolean skybox)
{
if (player == &players[displayplayers[i]])
{
viewangle = localangle[i];
aimingangle = localaiming[i];
newview->angle = localangle[i];
newview->aim = localaiming[i];
break;
}
}
}
}
}
viewz += quake.z;
newview->z += quake.z;
viewplayer = player;
newview->player = player;
if (chasecam && !player->awayviewtics && !player->spectator)
{
viewx = thiscam->x;
viewy = thiscam->y;
viewx += quake.x;
viewy += quake.y;
newview->x = thiscam->x;
newview->y = thiscam->y;
newview->x += quake.x;
newview->y += quake.y;
if (thiscam->subsector && thiscam->subsector->sector)
viewsector = thiscam->subsector->sector;
newview->sector = thiscam->subsector->sector;
else
viewsector = R_PointInSubsector(viewx, viewy)->sector;
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
}
else
{
viewx = viewmobj->x;
viewy = viewmobj->y;
viewx += quake.x;
viewy += quake.y;
newview->x = viewmobj->x;
newview->y = viewmobj->y;
newview->x += quake.x;
newview->y += quake.y;
if (viewmobj->subsector && thiscam->subsector->sector)
viewsector = viewmobj->subsector->sector;
newview->sector = viewmobj->subsector->sector;
else
viewsector = R_PointInSubsector(viewx, viewy)->sector;
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
}
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
// newview->sin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
R_SetupFreelook();
R_InterpolateView(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
}
#define ANGLED_PORTALS
@ -1186,13 +1175,13 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
#endif
//R_SetupFrame(player, false);
viewx = portal->viewx;
viewy = portal->viewy;
viewz = portal->viewz;
newview->x = portal->viewx;
newview->y = portal->viewy;
newview->z = portal->viewz;
viewangle = portal->viewangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
newview->angle = portal->viewangle;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
portalcullsector = dest->frontsector;
viewsector = dest->frontsector;
@ -1211,22 +1200,22 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
dest_c.y = (dest->v1->y + dest->v2->y) / 2;
// Heights!
viewz += dest->frontsector->floorheight - start->frontsector->floorheight;
newview->z += dest->frontsector->floorheight - start->frontsector->floorheight;
// calculate the difference in position and rotation!
#ifdef ANGLED_PORTALS
if (dangle == 0)
#endif
{ // the entrance goes straight opposite the exit, so we just need to mess with the offset.
viewx += dest_c.x - start_c.x;
viewy += dest_c.y - start_c.y;
newview->x += dest_c.x - start_c.x;
newview->y += dest_c.y - start_c.y;
return;
}
#ifdef ANGLED_PORTALS
viewangle += dangle;
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
newview->angle += dangle;
// newview->sin = FINESINE(newview->angle>>ANGLETOFINESHIFT);
// newview->cos = FINECOSINE(newview->angle>>ANGLETOFINESHIFT);
//CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS);
// ????
@ -1234,12 +1223,12 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal)
fixed_t disttopoint;
angle_t angtopoint;
disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy);
disttopoint = R_PointToDist2(start_c.x, start_c.y, newview->x, newview->y);
angtopoint = R_PointToAngle2(start_c.x, start_c.y, newview->x, newview->y);
angtopoint += dangle;
viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
newview->x = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
newview->y = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
}
#endif
}
@ -1544,4 +1533,7 @@ void R_RegisterEngineStuff(void)
if (rendermode != render_soft && rendermode != render_none)
HWR_AddCommands();
#endif
// Frame interpolation/uncapped
CV_RegisterVar(&cv_fpscap);
}

View file

@ -29,6 +29,13 @@ extern fixed_t projection, projectiony;
extern size_t validcount, linecount, loopcount, framecount;
// The fraction of a tic being drawn (for interpolation between two tics)
extern fixed_t rendertimefrac;
// Evaluated delta tics for this frame (how many tics since the last frame)
extern fixed_t renderdeltatics;
// The current render is a new logical tic
extern boolean renderisnewtic;
//
// Lighting LUT.
// Used for z-depth cuing per column/row,

View file

@ -27,6 +27,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "p_tick.h"
#include "r_fps.h"
#ifdef TIMING
#include "p5prof.h"
@ -678,8 +679,6 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
void R_DrawPlanes(void)
{
visplane_t *pl;
INT32 x;
INT32 angle;
INT32 i;
spanfunc = basespanfunc;
@ -689,50 +688,7 @@ void R_DrawPlanes(void)
{
for (pl = visplanes[i]; pl; pl = pl->next)
{
// sky flat
if (pl->picnum == skyflatnum)
{
if (!viewsky)
{
skyVisible = true;
continue;
}
// use correct aspect ratio scale
dc_iscale = skyscale;
// Sky is always drawn full bright,
// i.e. colormaps[0] is used.
// Because of this hack, sky is not affected
// by INVUL inverse mapping.
dc_colormap = colormaps;
if (encoremap)
dc_colormap += (256*32);
dc_texturemid = skytexturemid;
dc_texheight = textureheight[skytexture]
>>FRACBITS;
for (x = pl->minx; x <= pl->maxx; x++)
{
dc_yl = pl->top[x];
dc_yh = pl->bottom[x];
if (dc_yl <= dc_yh)
{
angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
dc_x = x;
dc_source =
R_GetColumn(texturetranslation[skytexture],
angle);
wallcolfunc();
}
}
continue;
}
if (pl->ffloor != NULL
|| pl->polyobj != NULL
)
if (pl->ffloor != NULL || pl->polyobj != NULL)
continue;
R_DrawSinglePlane(pl);
@ -744,6 +700,48 @@ void R_DrawPlanes(void)
#endif
}
static void R_DrawSkyPlane(visplane_t *pl)
{
INT32 x;
INT32 angle;
if (!newview->sky)
{
skyVisible = true;
return;
}
wallcolfunc = walldrawerfunc;
// use correct aspect ratio scale
dc_iscale = skyscale;
// Sky is always drawn full bright,
// i.e. colormaps[0] is used.
// Because of this hack, sky is not affected
// by INVUL inverse mapping.
dc_colormap = colormaps;
if (encoremap)
dc_colormap += (256*32);
dc_texturemid = skytexturemid;
dc_texheight = textureheight[skytexture]
>>FRACBITS;
for (x = pl->minx; x <= pl->maxx; x++)
{
dc_yl = pl->top[x];
dc_yh = pl->bottom[x];
if (dc_yl <= dc_yh)
{
angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT));
dc_x = x;
dc_source =
R_GetColumn(texturetranslation[skytexture],
angle);
wallcolfunc();
}
}
}
void R_DrawSinglePlane(visplane_t *pl)
{
INT32 light = 0;
@ -755,6 +753,13 @@ void R_DrawSinglePlane(visplane_t *pl)
if (!(pl->minx <= pl->maxx))
return;
// sky flat
if (pl->picnum == skyflatnum)
{
R_DrawSkyPlane(pl);
return;
}
#ifndef NOWATER
itswater = false;
#endif

View file

@ -20,6 +20,7 @@
#include "z_zone.h"
#include "m_misc.h"
#include "i_video.h" // rendermode
#include "r_fps.h"
#include "r_things.h"
#include "r_plane.h"
#include "p_tick.h"
@ -1158,13 +1159,28 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t gz, gzt;
INT32 heightsec, phs;
INT32 light = 0;
fixed_t this_scale = thing->scale;
fixed_t this_scale;
fixed_t ang_scale = FRACUNIT;
// uncapped/interpolation
interpmobjstate_t interp = {0};
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{
R_InterpolateMobjState(thing, rendertimefrac, &interp);
}
else
{
R_InterpolateMobjState(thing, FRACUNIT, &interp);
}
this_scale = interp.scale;
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
tr_x = interp.x - viewx;
tr_y = interp.y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
@ -1229,10 +1245,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (sprframe->rotate != SRF_SINGLE || papersprite)
{
if (thing->player)
ang = R_PointToAngle (thing->x, thing->y) - thing->player->frameangle;
else
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
if (papersprite)
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
}
@ -1247,7 +1260,7 @@ static void R_ProjectSprite(mobj_t *thing)
else
{
// choose a different rotation based on player view
//ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
//ang = R_PointToAngle (interp.x, interp.y) - interpangle;
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
rot = 6; // F7 slot
@ -1300,8 +1313,8 @@ static void R_ProjectSprite(mobj_t *thing)
offset2 *= -1;
}
cosmul = FINECOSINE(thing->angle>>ANGLETOFINESHIFT);
sinmul = FINESINE(thing->angle>>ANGLETOFINESHIFT);
cosmul = FINECOSINE(interp.angle >> ANGLETOFINESHIFT);
sinmul = FINESINE(interp.angle >> ANGLETOFINESHIFT);
tr_x += FixedMul(offset, cosmul);
tr_y += FixedMul(offset, sinmul);
@ -1343,7 +1356,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (x2 < portalclipstart || x1 > portalclipend)
return;
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
return;
}
@ -1353,12 +1366,12 @@ static void R_ProjectSprite(mobj_t *thing)
// When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned.
// sprite height - sprite topoffset is the proper inverse of the vertical offset, of course.
// remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes!
gz = thing->z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
gz = interp.z + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale);
gzt = gz + FixedMul(spritecachedinfo[lump].height, this_scale);
}
else
{
gzt = thing->z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
gzt = interp.z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale);
}
@ -1374,7 +1387,7 @@ static void R_ProjectSprite(mobj_t *thing)
light = thing->subsector->sector->numlights - 1;
for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, interp.x, interp.y)
: thing->subsector->sector->lightlist[lightnum].height;
if (h <= gzt) {
light = lightnum - 1;
@ -1416,12 +1429,12 @@ static void R_ProjectSprite(mobj_t *thing)
vis->scale = yscale; //<<detailshift;
vis->sortscale = sortscale;
vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
vis->gx = thing->x;
vis->gy = thing->y;
vis->gx = interp.x;
vis->gy = interp.y;
vis->gz = gz;
vis->gzt = gzt;
vis->thingheight = thing->height;
vis->pz = thing->z;
vis->pz = interp.z;
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = scalestep;
@ -1539,9 +1552,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
//SoM: 3/17/2000
fixed_t gz ,gzt;
// uncapped/interpolation
interpmobjstate_t interp = {0};
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{
R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp);
}
else
{
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
}
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
tr_x = interp.x - viewx;
tr_y = interp.y - viewy;
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
@ -1610,7 +1636,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
if (x2 < portalclipstart || x1 > portalclipend)
return;
if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0)
if (P_PointOnLineSide(interp.x, interp.y, portalclipline) != 0)
return;
}
@ -1626,7 +1652,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
//SoM: 3/17/2000: Disregard sprites that are out of view..
gzt = thing->z + spritecachedinfo[lump].topoffset;
gzt = interp.z + spritecachedinfo[lump].topoffset;
gz = gzt - spritecachedinfo[lump].height;
if (thing->subsector->sector->cullheight)
@ -1639,12 +1665,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis = R_NewVisSprite();
vis->scale = vis->sortscale = yscale; //<<detailshift;
vis->dispoffset = 0; // Monster Iestyn: 23/11/15
vis->gx = thing->x;
vis->gy = thing->y;
vis->gx = interp.x;
vis->gy = interp.y;
vis->gz = gz;
vis->gzt = gzt;
vis->thingheight = 4*FRACUNIT;
vis->pz = thing->z;
vis->pz = interp.z;
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = 0;

View file

@ -143,7 +143,7 @@ extern struct cursongcredit
{
musicdef_t *def;
UINT16 anim;
INT32 x;
fixed_t x;
UINT8 trans;
} cursongcredit;

View file

@ -15,6 +15,7 @@
#include "screen.h"
#include "console.h"
#include "am_map.h"
#include "i_time.h"
#include "i_system.h"
#include "i_video.h"
#include "r_local.h"
@ -29,6 +30,8 @@
#include "d_clisrv.h"
#include "f_finale.h"
// SRB2Kart
#include "r_fps.h" // R_GetFramerateCap
#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
#define RUSEASM //MSC.NET can't patch itself
@ -397,46 +400,110 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
);
}
// XMOD FPS display
// moved out of os-specific code for consistency
static boolean fpsgraph[TICRATE];
static tic_t lasttic;
double averageFPS = 0.0f;
#define USE_FPS_SAMPLES
#ifdef USE_FPS_SAMPLES
#define FPS_SAMPLE_RATE (0.05) // How often to update FPS samples, in seconds
#define NUM_FPS_SAMPLES (16) // Number of samples to store
static double fps_samples[NUM_FPS_SAMPLES];
static double updateElapsed = 0.0;
#endif
static boolean fps_init = false;
static precise_t fps_enter = 0;
void SCR_CalculateFPS(void)
{
precise_t fps_finish = 0;
double frameElapsed = 0.0;
if (fps_init == false)
{
fps_enter = I_GetPreciseTime();
fps_init = true;
}
fps_finish = I_GetPreciseTime();
frameElapsed = (double)((INT64)(fps_finish - fps_enter)) / I_GetPrecisePrecision();
fps_enter = fps_finish;
#ifdef USE_FPS_SAMPLES
updateElapsed += frameElapsed;
if (updateElapsed >= FPS_SAMPLE_RATE)
{
static int sampleIndex = 0;
int i;
fps_samples[sampleIndex] = frameElapsed;
sampleIndex++;
if (sampleIndex >= NUM_FPS_SAMPLES)
sampleIndex = 0;
averageFPS = 0.0;
for (i = 0; i < NUM_FPS_SAMPLES; i++)
{
averageFPS += fps_samples[i];
}
if (averageFPS > 0.0)
{
averageFPS = 1.0 / (averageFPS / NUM_FPS_SAMPLES);
}
}
while (updateElapsed >= FPS_SAMPLE_RATE)
{
updateElapsed -= FPS_SAMPLE_RATE;
}
#else
// Direct, unsampled counter.
averageFPS = 1.0 / frameElapsed;
#endif
}
void SCR_DisplayTicRate(void)
{
tic_t i;
tic_t ontic = I_GetTime();
tic_t totaltics = 0;
const UINT8 *ticcntcolor = NULL;
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
fpsgraph[i % TICRATE] = false;
fpsgraph[ontic % TICRATE] = true;
for (i = 0;i < TICRATE;++i)
if (fpsgraph[i])
++totaltics;
if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SALMON, GTC_CACHE);
else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
/*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy),
V_YELLOWMAP|V_NOSCALESTART, "FPS");
V_DrawString(vid.width-(40*vid.dupx), vid.height-( 8*vid.dupy),
ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/
UINT32 cap = R_GetFramerateCap();
UINT32 benchmark = (cap == 0) ? I_GetRefreshRate() : cap;
INT32 x = 318;
double fps = round(averageFPS);
// draw "FPS"
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
// draw total frame:
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, TICRATE, ticcntcolor);
// draw "/"
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, frameslash, ticcntcolor);
if (fps > (benchmark - 5))
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
else if (fps < 20)
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
if (cap != 0)
{
UINT32 digits = 1;
UINT32 c2 = cap;
while (c2 > 0)
{
c2 = c2 / 10;
digits++;
}
// draw total frame:
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, cap, ticcntcolor);
x -= digits * 4;
// draw "/"
V_DrawFixedPatch(x<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT, frameslash, ticcntcolor);
}
// draw our actual framerate
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, totaltics, ticcntcolor);
lasttic = ontic;
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT, fps, ticcntcolor);
}
// SCR_DisplayLocalPing

View file

@ -154,6 +154,7 @@ extern boolean R_SSE2;
// ----------------
extern viddef_t vid;
extern INT32 setmodeneeded; // mode number to set if needed, or 0
extern double averageFPS;
extern INT32 scr_bpp;
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
@ -161,6 +162,7 @@ extern UINT8 *scr_borderpatch; // patch used to fill the view borders
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen;
// wait for page flipping to end or not
extern consvar_t cv_vidwait;
extern consvar_t cv_timescale;
// quick fix for tall/short skies, depending on bytesperpixel
extern void (*walldrawerfunc)(void);
@ -176,6 +178,8 @@ void SCR_SetDefaultMode (void);
void SCR_Startup (void);
void SCR_CalculateFPS(void);
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
// move out to main code for consistency

View file

@ -160,6 +160,7 @@ static char returnWadPath[256];
#include "../doomdef.h"
#include "../m_misc.h"
#include "../i_time.h"
#include "../i_video.h"
#include "../i_sound.h"
#include "../i_system.h"
@ -175,6 +176,9 @@ static char returnWadPath[256];
#include "../m_argv.h"
#include "../r_main.h" // Frame interpolation/uncapped
#include "../r_fps.h"
#ifdef MAC_ALERT
#include "macosx/mac_alert.h"
#endif
@ -2927,122 +2931,80 @@ ticcmd_t *I_BaseTiccmd4(void)
return &emptycmd4;
}
#if defined (_WIN32)
static HMODULE winmm = NULL;
static DWORD starttickcount = 0; // hack for win2k time bug
static p_timeGetTime pfntimeGetTime = NULL;
static Uint64 timer_frequency;
// ---------
// I_GetTime
// Use the High Resolution Timer if available,
// else use the multimedia timer which has 1 millisecond precision on Windowz 95,
// but lower precision on Windows NT
// ---------
tic_t I_GetTime(void)
precise_t I_GetPreciseTime(void)
{
tic_t newtics = 0;
return SDL_GetPerformanceCounter();
}
if (!starttickcount) // high precision timer
UINT64 I_GetPrecisePrecision(void)
{
return SDL_GetPerformanceFrequency();
}
static UINT32 frame_rate;
static double frame_frequency;
static UINT64 frame_epoch;
static double elapsed_frames;
static void I_InitFrameTime(const UINT64 now, const UINT32 cap)
{
frame_rate = cap;
frame_epoch = now;
//elapsed_frames = 0.0;
if (frame_rate == 0)
{
LARGE_INTEGER currtime; // use only LowPart if high resolution counter is not available
static LARGE_INTEGER basetime = {{0, 0}};
// Shouldn't be used, but just in case...?
frame_frequency = 1.0;
return;
}
// use this if High Resolution timer is found
static LARGE_INTEGER frequency;
frame_frequency = timer_frequency / (double)frame_rate;
}
if (!basetime.LowPart)
{
if (!QueryPerformanceFrequency(&frequency))
frequency.QuadPart = 0;
else
QueryPerformanceCounter(&basetime);
}
double I_GetFrameTime(void)
{
const UINT64 now = SDL_GetPerformanceCounter();
const UINT32 cap = R_GetFramerateCap();
if (frequency.LowPart && QueryPerformanceCounter(&currtime))
{
newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE
/ frequency.QuadPart);
}
else if (pfntimeGetTime)
{
currtime.LowPart = pfntimeGetTime();
if (!basetime.LowPart)
basetime.LowPart = currtime.LowPart;
newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE));
}
if (cap != frame_rate)
{
// Maybe do this in a OnChange function for cv_fpscap?
I_InitFrameTime(now, cap);
}
if (frame_rate == 0)
{
// Always advance a frame.
elapsed_frames += 1.0;
}
else
newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE);
return newtics;
}
static void I_ShutdownTimer(void)
{
pfntimeGetTime = NULL;
if (winmm)
{
p_timeEndPeriod pfntimeEndPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeEndPeriod");
if (pfntimeEndPeriod)
pfntimeEndPeriod(1);
FreeLibrary(winmm);
winmm = NULL;
elapsed_frames += (now - frame_epoch) / frame_frequency;
}
frame_epoch = now; // moving epoch
return elapsed_frames;
}
#else
//
// I_GetTime
// returns time in 1/TICRATE second tics
//
tic_t I_GetTime (void)
{
static Uint64 basetime = 0;
Uint64 ticks = SDL_GetTicks();
if (!basetime)
basetime = ticks;
ticks -= basetime;
ticks = (ticks*TICRATE);
ticks = (ticks/1000);
return (tic_t)ticks;
}
#endif
//
//I_StartupTimer
// I_StartupTimer
//
void I_StartupTimer(void)
{
#ifdef _WIN32
// for win2k time bug
if (M_CheckParm("-gettickcount"))
{
starttickcount = GetTickCount();
CONS_Printf("%s", M_GetText("Using GetTickCount()\n"));
}
winmm = LoadLibraryA("winmm.dll");
if (winmm)
{
p_timeEndPeriod pfntimeBeginPeriod = (p_timeEndPeriod)(LPVOID)GetProcAddress(winmm, "timeBeginPeriod");
if (pfntimeBeginPeriod)
pfntimeBeginPeriod(1);
pfntimeGetTime = (p_timeGetTime)(LPVOID)GetProcAddress(winmm, "timeGetTime");
}
I_AddExitFunc(I_ShutdownTimer);
#endif
timer_frequency = SDL_GetPerformanceFrequency();
I_InitFrameTime(0, R_GetFramerateCap());
elapsed_frames = 0.0;
}
void I_Sleep(void)
void I_Sleep(UINT32 ms)
{
if (cv_sleep.value > 0)
SDL_Delay(cv_sleep.value);
SDL_Delay(ms);
}
#ifdef NEWSIGNALHANDLER

View file

@ -1351,12 +1351,15 @@ void I_UpdateNoBlit(void)
// from PrBoom's src/SDL/i_video.c
static inline boolean I_SkipFrame(void)
{
#if 0
#if 1
// While I fixed the FPS counter bugging out with this,
// I actually really like being able to pause and
// use perfstats to measure rendering performance
// without game logic changes.
return false;
#else
static boolean skip = false;
if (rendermode != render_soft)
return false;
skip = !skip;
switch (gamestate)
@ -1371,17 +1374,20 @@ static inline boolean I_SkipFrame(void)
return false;
}
#endif
return false;
}
//
// I_FinishUpdate
//
static SDL_Rect src_rect = { 0, 0, 0, 0 };
void I_FinishUpdate(void)
{
if (rendermode == render_none)
return; //Alam: No software or OpenGl surface
SCR_CalculateFPS();
if (I_SkipFrame())
return;
@ -1398,27 +1404,22 @@ void I_FinishUpdate(void)
if (rendermode == render_soft && screens[0])
{
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = vid.width;
rect.h = vid.height;
if (!bufSurface) //Double-Check
{
Impl_VideoSetupSDLBuffer();
}
if (bufSurface)
{
SDL_BlitSurface(bufSurface, NULL, vidSurface, &rect);
SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect);
// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
SDL_LockSurface(vidSurface);
SDL_UpdateTexture(texture, &rect, vidSurface->pixels, vidSurface->pitch);
SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch);
SDL_UnlockSurface(vidSurface);
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderCopy(renderer, texture, &src_rect, NULL);
SDL_RenderPresent(renderer);
}
@ -1428,6 +1429,7 @@ void I_FinishUpdate(void)
OglSdlFinishUpdate(cv_vidwait.value);
}
#endif
exposevideo = SDL_FALSE;
}
@ -1621,6 +1623,27 @@ void VID_PrepareModeList(void)
#endif
}
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();
@ -1665,6 +1688,11 @@ INT32 VID_SetMode(INT32 modeNum)
}
}
src_rect.w = vid.width;
src_rect.h = vid.height;
refresh_rate = VID_GetRefreshRate();
return SDL_TRUE;
}
@ -2057,4 +2085,15 @@ void I_ShutdownGraphics(void)
SDL_QuitSubSystem(SDL_INIT_VIDEO);
framebuffer = SDL_FALSE;
}
UINT32 I_GetRefreshRate(void)
{
// Moved to VID_GetRefreshRate.
// Precalculating it like that won't work as
// well for windowed mode since you can drag
// the window around, but very slow PCs might have
// trouble querying mode over and over again.
return refresh_rate;
}
#endif

View file

@ -42,8 +42,12 @@
#ifdef HAVE_BLUA
#include "lua_hud.h"
#include "lua_hudlib_drawlist.h"
#include "lua_hook.h"
#endif
#include "r_fps.h"
UINT16 objectsdrawn = 0;
//
@ -175,6 +179,10 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
{ 240, 160}, // HUD_LAP
};
#ifdef HAVE_BLUA
static huddrawlist_h luahuddrawlist_game;
#endif
//
// STATUS BAR CODE
//
@ -422,6 +430,10 @@ void ST_Init(void)
return;
ST_LoadGraphics();
#ifdef HAVE_BLUA
luahuddrawlist_game = LUA_HUD_CreateDrawList();
#endif
}
// change the status bar too, when pressing F12 while viewing a demo.
@ -1952,7 +1964,14 @@ static void ST_overlayDrawer(void)
#ifdef HAVE_BLUA
if (!(netgame || multiplayer) || !hu_showscores)
LUAh_GameHUD(stplyr);
{
if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_game);
LUAh_GameHUD(stplyr, luahuddrawlist_game);
}
LUA_HUD_DrawList(luahuddrawlist_game);
}
#endif
// draw level title Tails

View file

@ -55,6 +55,7 @@
#include "g_game.h" // G_LoadGameData
#include "filesrch.h"
#include "i_time.h"
#include "i_video.h" // rendermode
#include "d_netfil.h"
#include "dehacked.h"

View file

@ -35,6 +35,7 @@
#include <mmsystem.h>
#include "../m_misc.h"
#include "../i_time.h"
#include "../i_video.h"
#include "../i_sound.h"
#include "../i_system.h"
@ -45,6 +46,7 @@
#include "../d_main.h"
#include "../m_argv.h"
#include "../m_fixed.h"
#include "../w_wad.h"
#include "../z_zone.h"
@ -259,10 +261,25 @@ tic_t I_GetTime(void)
return newtics;
}
void I_Sleep(void)
precise_t I_GetPreciseTime(void)
{
if (cv_sleep.value > 0)
Sleep(cv_sleep.value);
LARGE_INTEGER time;
BOOL res = QueryPerformanceCounter(&time);
if (!res) I_Error("QueryPerformanceCounter error"); // if this happens, you've gone back to the 90s
return (precise_t) time.QuadPart;
}
UINT64 I_GetPrecisePrecision(void)
{
LARGE_INTEGER time;
BOOL res = QueryPerformanceFrequency(&time);
if (!res) I_Error("QueryPerformanceFrequency error"); // if this happens, you've gone back to the 90s
return (precise_t) time.QuadPart;
}
void I_Sleep(UINT32 ms)
{
Sleep(ms);
}
// should move to i_video