diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index 7a021dda7..27ac64e78 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -162,7 +162,7 @@ ifdef DEBUGMODE ifdef GCC48 opts+=-Og else -opts+=O0 +opts+=-O0 endif endif diff --git a/src/Sourcefile b/src/Sourcefile index 384af8da7..9bc27d4da 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -56,6 +56,7 @@ tables.c r_bsp.c r_data.c r_draw.c +r_fps.c r_main.c r_plane.c r_segs.c diff --git a/src/android/i_system.c b/src/android/i_system.c index 908629bea..d8b81dcec 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -88,6 +88,12 @@ tic_t I_GetTime(void) return (since_start*TICRATE)/1000000; } +fixed_t I_GetTimeFrac(void) +{ + //stub + return 0; +} + void I_Sleep(void){} void I_GetEvent(void){} diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5b4141328..aa3ef2cd6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5264,12 +5264,14 @@ void TryRunTics(tic_t realtics) if (neededtic > gametic) { - hu_stopped = false; + if (realtics) + hu_stopped = false; } if (player_joining) { - hu_stopped = true; + if (realtics) + hu_stopped = true; return; } @@ -5288,6 +5290,7 @@ void TryRunTics(tic_t realtics) while (neededtic > gametic) { DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); + prev_tics = I_GetTime(); ps_tictime = I_GetPreciseTime(); @@ -5306,7 +5309,8 @@ void TryRunTics(tic_t realtics) } else { - hu_stopped = true; + if (realtics) + hu_stopped = true; } } diff --git a/src/d_main.c b/src/d_main.c index 5ded2bf14..52cd7b46c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -63,6 +63,7 @@ #include "deh_tables.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 #include "g_input.h" // tutorial mode control scheming @@ -755,7 +756,7 @@ void D_SRB2Loop(void) debugload--; #endif - if (!realtics && !singletics) + if (!realtics && !singletics && cv_frameinterpolation.value != 1) { I_Sleep(); continue; @@ -773,13 +774,37 @@ void D_SRB2Loop(void) // process tics (but maybe not if realtic == 0) TryRunTics(realtics); + if (cv_frameinterpolation.value == 1) + { + fixed_t entertimefrac = I_GetTimeFrac(); + // renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based + renderdeltatics = realtics * FRACUNIT; + if (entertimefrac > rendertimefrac) + renderdeltatics += entertimefrac - rendertimefrac; + else + renderdeltatics -= rendertimefrac - entertimefrac; + + rendertimefrac = entertimefrac; + } + else + { + rendertimefrac = FRACUNIT; + renderdeltatics = realtics * FRACUNIT; + } + + if (cv_frameinterpolation.value == 1) + { + D_Display(); + } + if (lastdraw || singletics || gametic > rendergametic) { rendergametic = gametic; rendertimeout = entertic+TICRATE/17; // Update display, next frame, with current state. - D_Display(); + // (Only display if not already done for frame interp) + cv_frameinterpolation.value == 0 ? D_Display() : 0; if (moviemode) M_SaveFrame(); @@ -788,7 +813,22 @@ void D_SRB2Loop(void) } else if (rendertimeout < entertic) // in case the server hang or netsplit { - D_Display(); +#if 0 + // Lagless camera! Yay! + if (gamestate == GS_LEVEL && netgame) + { + INT32 i; + + for (i = 0; i <= r_splitscreen; i++) + { + if (camera[i].chase) + P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false); + } + } +#endif + + // (Only display if not already done for frame interp) + cv_frameinterpolation.value == 0 ? D_Display() : 0; if (moviemode) M_SaveFrame(); @@ -1639,6 +1679,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()) diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 4a657ed19..f3d0bc5e8 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -16,7 +16,7 @@ tic_t I_GetTime(void) return 0; } -int I_GetTimeMicros(void) +fixed_t I_GetTimeFrac(void) { return 0; } diff --git a/src/g_demo.c b/src/g_demo.c index 16ca2a859..08b9cddb3 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1580,7 +1580,7 @@ void G_ReadMetalTic(mobj_t *metal) oldmetal.x = READFIXED(metal_p); oldmetal.y = READFIXED(metal_p); oldmetal.z = READFIXED(metal_p); - P_TeleportMove(metal, oldmetal.x, oldmetal.y, oldmetal.z); + P_MoveOrigin(metal, oldmetal.x, oldmetal.y, oldmetal.z); oldmetal.x = metal->x; oldmetal.y = metal->y; oldmetal.z = metal->z; diff --git a/src/g_game.c b/src/g_game.c index e964fb65d..cb2fa4e77 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -45,8 +45,8 @@ #include "y_inter.h" #include "v_video.h" #include "lua_hook.h" -#include "k_bot.h" #include "m_cond.h" // condition sets +#include "r_fps.h" // frame interpolation/uncapped #include "lua_hud.h" // SRB2kart @@ -56,6 +56,7 @@ #include "k_color.h" #include "k_respawn.h" #include "k_grandprix.h" +#include "k_bot.h" #include "doomstat.h" #ifdef HAVE_DISCORDRPC @@ -1920,6 +1921,8 @@ void G_Ticker(boolean run) F_TextPromptTicker(); AM_Ticker(); HU_Ticker(); + R_UpdateViewInterpolation(); + break; case GS_INTERMISSION: @@ -1976,7 +1979,12 @@ void G_Ticker(boolean run) break; case GS_TITLESCREEN: - if (titlemapinaction) P_Ticker(run); + if (titlemapinaction) + { + P_Ticker(run); + R_UpdateViewInterpolation(); + } + F_TitleScreenTicker(run); break; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 205fc3ff6..b74bd71ea 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -38,6 +38,7 @@ #include "../m_cheat.h" #include "../f_finale.h" #include "../r_things.h" // R_GetShadowZ +#include "../d_main.h" #include "../p_slopes.h" #include "hw_md2.h" @@ -3623,10 +3624,6 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { - fixed_t thingxpos = thing->x + thing->sprxoff; - fixed_t thingypos = thing->y + thing->spryoff; - fixed_t thingzpos = thing->z + thing->sprzoff; - patch_t *gpatch; FOutVector shadowVerts[4]; FSurfaceInfo sSurf; @@ -3643,7 +3640,19 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) fixed_t slopez; pslope_t *groundslope; - // hitlag vibrating + fixed_t interpx = thing->x; + fixed_t interpy = thing->y; + fixed_t interpz = thing->z; + + // do interpolation + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); + interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); + interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + } + + // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { fixed_t mul = thing->hitlag * (FRACUNIT / 10); @@ -3653,14 +3662,19 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) mul = -mul; } - thingxpos += FixedMul(thing->momx, mul); - thingypos += FixedMul(thing->momy, mul); - thingzpos += FixedMul(thing->momz, mul); + interpx += FixedMul(thing->momx, mul); + interpy += FixedMul(thing->momy, mul); + interpz += FixedMul(thing->momz, mul); } + // sprite offset + interpx += thing->sprxoff; + interpy += thing->spryoff; + interpz += thing->sprzoff; + groundz = R_GetShadowZ(thing, &groundslope); - floordiff = abs((flip < 0 ? thing->height : 0) + thingzpos - groundz); + floordiff = abs((flip < 0 ? thing->height : 0) + interpz - groundz); alpha = floordiff / (4*FRACUNIT) + 75; if (alpha >= 255) return; @@ -3674,8 +3688,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); fscale = FIXED_TO_FLOAT(scalemul); - fx = FIXED_TO_FLOAT(thingxpos); - fy = FIXED_TO_FLOAT(thingypos); + fx = FIXED_TO_FLOAT(interpx); + fy = FIXED_TO_FLOAT(interpy); // 3--2 // | /| @@ -5013,10 +5027,6 @@ static void HWR_AddSprites(sector_t *sec) // BP why not use xtoviexangle/viewangletox like in bsp ?.... static void HWR_ProjectSprite(mobj_t *thing) { - fixed_t thingxpos = thing->x + thing->sprxoff; - fixed_t thingypos = thing->y + thing->spryoff; - fixed_t thingzpos = thing->z + thing->sprzoff; - gl_vissprite_t *vis; float tr_x, tr_y; float tz; @@ -5056,13 +5066,34 @@ static void HWR_ProjectSprite(mobj_t *thing) angle_t spriterotangle = 0; #endif + // uncapped/interpolation + fixed_t interpx; + fixed_t interpy; + fixed_t interpz; + angle_t interpangle; + if (!thing) return; if (thing->spritexscale < 1 || thing->spriteyscale < 1) return; - // hitlag vibrating + dispoffset = thing->info->dispoffset; + + interpx = thing->x; + interpy = thing->y; + interpz = thing->z; + interpangle = mobjangle; + + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); + interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); + interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + interpangle = mobjangle; + } + + // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { fixed_t mul = thing->hitlag * (FRACUNIT / 10); @@ -5072,20 +5103,23 @@ static void HWR_ProjectSprite(mobj_t *thing) mul = -mul; } - thingxpos += FixedMul(thing->momx, mul); - thingypos += FixedMul(thing->momy, mul); - thingzpos += FixedMul(thing->momz, mul); + interpx += FixedMul(thing->momx, mul); + interpy += FixedMul(thing->momy, mul); + interpz += FixedMul(thing->momz, mul); } - dispoffset = thing->info->dispoffset; + // sprite offset + interpx += thing->sprxoff; + interpy += thing->spryoff; + interpz += thing->sprzoff; this_scale = FIXED_TO_FLOAT(thing->scale); spritexscale = FIXED_TO_FLOAT(thing->spritexscale); spriteyscale = FIXED_TO_FLOAT(thing->spriteyscale); // transform the origin point - tr_x = FIXED_TO_FLOAT(thingxpos) - gl_viewx; - tr_y = FIXED_TO_FLOAT(thingypos) - gl_viewy; + tr_x = FIXED_TO_FLOAT(interpx) - gl_viewx; + tr_y = FIXED_TO_FLOAT(interpy) - gl_viewy; // rotation around vertical axis tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); @@ -5108,8 +5142,8 @@ static void HWR_ProjectSprite(mobj_t *thing) } // The above can stay as it works for cutting sprites that are too close - tr_x = FIXED_TO_FLOAT(thingxpos); - tr_y = FIXED_TO_FLOAT(thingypos); + tr_x = FIXED_TO_FLOAT(interpx); + tr_y = FIXED_TO_FLOAT(interpy); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -5157,7 +5191,7 @@ static void HWR_ProjectSprite(mobj_t *thing) I_Error("sprframes NULL for sprite %d\n", thing->sprite); #endif - ang = R_PointToAngle (thingxpos, thingypos) - mobjangle; + ang = R_PointToAngle (interpx, interpy) - interpangle; if (mirrored) ang = InvAngle(ang); @@ -5304,12 +5338,12 @@ static void HWR_ProjectSprite(mobj_t *thing) if (vflip) { - gz = FIXED_TO_FLOAT(thingzpos + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); + gz = FIXED_TO_FLOAT(interpz + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale); } else { - gzt = FIXED_TO_FLOAT(thingzpos) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); + gzt = FIXED_TO_FLOAT(interpz) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale); gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale); } @@ -5320,7 +5354,7 @@ static void HWR_ProjectSprite(mobj_t *thing) } heightsec = thing->subsector->sector->heightsec; - if (viewplayer->mo && viewplayer->mo->subsector) + if (viewplayer && viewplayer->mo && viewplayer->mo->subsector) phs = viewplayer->mo->subsector->sector->heightsec; else phs = -1; @@ -5328,12 +5362,12 @@ static void HWR_ProjectSprite(mobj_t *thing) if (heightsec != -1 && phs != -1) // only clip things which are in special sectors { if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ? - FIXED_TO_FLOAT(thingzpos) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) : + FIXED_TO_FLOAT(interpz) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) : gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight)) return; if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ? gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) : - FIXED_TO_FLOAT(thingzpos) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight)) + FIXED_TO_FLOAT(interpz) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight)) return; } @@ -5468,9 +5502,29 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) unsigned rot = 0; UINT8 flip; + // uncapped/interpolation + fixed_t interpx; + fixed_t interpy; + fixed_t interpz; + + if (!thing) + return; + + interpx = thing->x; + interpy = thing->y; + interpz = thing->z; + + // do interpolation + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); + interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); + interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + } + // transform the origin point - tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; - tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; + tr_x = FIXED_TO_FLOAT(interpx) - gl_viewx; + tr_y = FIXED_TO_FLOAT(interpy) - gl_viewy; // rotation around vertical axis tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); @@ -5479,8 +5533,8 @@ static 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(interpx); + tr_y = FIXED_TO_FLOAT(interpy); // decide which patch to use for sprite relative to player if ((unsigned)thing->sprite >= numsprites) @@ -5547,7 +5601,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) #endif // set top/bottom coords - vis->gzt = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); + vis->gzt = FIXED_TO_FLOAT(interpz + spritecachedinfo[lumpoff].topoffset); vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height); vis->precip = true; @@ -6702,6 +6756,8 @@ void HWR_DoPostProcessor(player_t *player) // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; static double disStart = 0; + static fixed_t last_fractime = 0; + UINT8 x, y; INT32 WAVELENGTH; INT32 AMPLITUDE; @@ -6733,6 +6789,15 @@ void HWR_DoPostProcessor(player_t *player) HWD.pfnPostImgRedraw(v); if (!(paused || P_AutoPause())) disStart += 1; + if (renderdeltatics > FRACUNIT) + { + disStart = disStart - FIXED_TO_FLOAT(last_fractime) + 1 + FIXED_TO_FLOAT(rendertimefrac); + } + else + { + disStart = disStart - FIXED_TO_FLOAT(last_fractime) + FIXED_TO_FLOAT(rendertimefrac); + } + last_fractime = rendertimefrac; // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 4b8d1de6f..70c064081 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1355,10 +1355,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // Look at HWR_ProjectSprite for more { - fixed_t thingxpos = spr->mobj->x + spr->mobj->sprxoff; - fixed_t thingypos = spr->mobj->y + spr->mobj->spryoff; - fixed_t thingzpos = spr->mobj->z + spr->mobj->sprzoff; - patch_t *gpatch, *blendgpatch; GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL; INT32 durs = spr->mobj->state->tics; @@ -1371,6 +1367,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) INT32 mod; float finalscale; + fixed_t interpx = spr->mobj->x; + fixed_t interpy = spr->mobj->y; + fixed_t interpz = spr->mobj->z; + + // do interpolation + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x); + interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y); + interpz = spr->mobj->old_z + FixedMul(rendertimefrac, spr->mobj->z - spr->mobj->old_z); + } + // hitlag vibrating if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG)) { @@ -1381,11 +1389,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) mul = -mul; } - thingxpos += FixedMul(spr->mobj->momx, mul); - thingypos += FixedMul(spr->mobj->momy, mul); - thingzpos += FixedMul(spr->mobj->momz, mul); + interpx += FixedMul(spr->mobj->momx, mul); + interpy += FixedMul(spr->mobj->momy, mul); + interpy += FixedMul(spr->mobj->momz, mul); } + // sprite offset + interpx += spr->mobj->sprxoff; + interpy += spr->mobj->spryoff; + interpz += spr->mobj->sprzoff; + // Apparently people don't like jump frames like that, so back it goes //if (tics > durs) //durs = tics; @@ -1605,13 +1618,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) #endif //Hurdler: it seems there is still a small problem with mobj angle - p.x = FIXED_TO_FLOAT(thingxpos); - p.y = FIXED_TO_FLOAT(thingypos) + md2->offset; + p.x = FIXED_TO_FLOAT(interpx); + p.y = FIXED_TO_FLOAT(interpy) + md2->offset; if (flip) p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); else - p.z = FIXED_TO_FLOAT(thingzpos); + p.z = FIXED_TO_FLOAT(interpz); if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2]; @@ -1631,7 +1644,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } else { - const fixed_t anglef = AngleFixed((R_PointToAngle(thingxpos, thingypos))-ANGLE_180); + const fixed_t anglef = AngleFixed((R_PointToAngle(interpx, interpy))-ANGLE_180); p.angley = FIXED_TO_FLOAT(anglef); } diff --git a/src/i_system.h b/src/i_system.h index 0d5898a72..4bc0e73da 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -46,6 +46,10 @@ UINT32 I_GetFreeMem(UINT32 *total); */ tic_t I_GetTime(void); +/** \brief Get the current time as a fraction of a tic since the last tic. +*/ +fixed_t I_GetTimeFrac(void); + /** \brief Returns precise time value for performance measurement. */ precise_t I_GetPreciseTime(void); diff --git a/src/info.c b/src/info.c index c28c81dfd..c0268d075 100644 --- a/src/info.c +++ b/src/info.c @@ -9199,7 +9199,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NOTHINK|MF_DONTENCOREMAP, // flags + MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/k_hud.c b/src/k_hud.c index 0068bc836..589467bd6 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -761,9 +761,14 @@ void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du if (lt_exitticker < length) { - INT32 offset = screenwidth - ((lt_exitticker * screenwidth) / length); boolean slidefromright = false; + const INT32 offsetAmount = (screenwidth * FRACUNIT) / length; + fixed_t offset = (screenwidth * FRACUNIT) - (lt_exitticker * offsetAmount); + + offset += FixedMul(offsetAmount, renderdeltatics); + offset /= FRACUNIT; + if (r_splitscreen > 1) { if (stplyr == &players[displayplayers[1]] || stplyr == &players[displayplayers[3]]) @@ -3041,6 +3046,7 @@ static void K_drawKartMinimap(void) SINT8 numlocalplayers = 0; INT32 hyu = hyudorotime; mobj_t *mobj, *next; // for SPB drawing (or any other item(s) we may wanna draw, I dunno!) + fixed_t interpx, interpy; // Draw the HUD only when playing in a level. // hu_stuff needs this, unlike st_stuff. @@ -3135,7 +3141,17 @@ static void K_drawKartMinimap(void) } else colormap = NULL; - K_drawKartMinimapIcon(g->mo->x, g->mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); + + interpx = g->mo->x; + interpy = g->mo->y; + + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x); + interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y); + } + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); g = g->next; } @@ -3191,11 +3207,22 @@ static void K_drawKartMinimap(void) else colormap = NULL; - K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); + interpx = players[i].mo->x; + interpy = players[i].mo->y; + + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x); + interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y); + } + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); // Target reticule if ((gametype == GT_RACE && players[i].position == spbplace) - || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i]))) - K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i]))) + { + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + } } } @@ -3215,7 +3242,16 @@ static void K_drawKartMinimap(void) colormap = R_GetTranslationColormap(TC_RAINBOW, mobj->color, GTC_CACHE); } - K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_spbminimap, colormap, AutomapPic); + interpx = mobj->x; + interpy = mobj->y; + + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x); + interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y); + } + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_spbminimap, colormap, AutomapPic); } } @@ -3243,12 +3279,23 @@ static void K_drawKartMinimap(void) else colormap = NULL; - K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); + interpx = players[localplayers[i]].mo->x; + interpy = players[localplayers[i]].mo->y; + + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x); + interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y); + } + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); // Target reticule if ((gametype == GT_RACE && players[localplayers[i]].position == spbplace) - || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]]))) - K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]]))) + { + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + } } } @@ -3508,7 +3555,7 @@ static void K_drawKartFinish(void) //else -- 1/2p, scrolling FINISH { - INT32 x, xval; + INT32 x, xval, ox, interpx; if (r_splitscreen) // wide splitscreen pnum += 4; @@ -3516,11 +3563,14 @@ static void K_drawKartFinish(void) x = ((vid.width<width)<karthud[khud_cardanimation])*(xval > x ? xval : x))/TICRATE; + ox = ((TICRATE - (stplyr->karthud[khud_cardanimation] - 1))*(xval > x ? xval : x))/TICRATE; + + interpx = ox + FixedMul(rendertimefrac, x - ox); if (r_splitscreen && stplyr == &players[displayplayers[1]]) - x = -x; + interpx = -interpx; - V_DrawFixedPatch(x + (STCD_X<>1), + V_DrawFixedPatch(interpx + (STCD_X<>1), (STCD_Y<height)<<(FRACBITS-1)), FRACUNIT, splitflags, kp_racefinish[pnum], NULL); @@ -3909,33 +3959,63 @@ static void K_drawChallengerScreen(void) static void K_drawLapStartAnim(void) { // This is an EVEN MORE insanely complicated animation. - const UINT8 progress = 80-stplyr->karthud[khud_lapanimation]; + const UINT8 t = stplyr->karthud[khud_lapanimation]; + const UINT8 progress = 80 - t; + + const UINT8 tOld = t - 1; + const UINT8 progressOld = 80 - tOld; + + const tic_t leveltimeOld = leveltime - 1; + UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE); - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, - (48 - (32*max(0, progress-76)))*FRACUNIT, + fixed_t interpx, interpy, newval, oldval; + + newval = (BASEVIDWIDTH/2 + (32 * max(0, t - 76))) * FRACUNIT; + oldval = (BASEVIDWIDTH/2 + (32 * max(0, tOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + newval = (48 - (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (48 - (32 * max(0, progressOld - 76))) * FRACUNIT; + interpy = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, interpy, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, (modeattacking ? kp_lapanim_emblem[1] : kp_lapanim_emblem[0]), colormap); if (stplyr->karthud[khud_laphand] >= 1 && stplyr->karthud[khud_laphand] <= 3) { - V_DrawFixedPatch((BASEVIDWIDTH/2 + (32*max(0, stplyr->karthud[khud_lapanimation]-76)))*FRACUNIT, - (48 - (32*max(0, progress-76)) - + 4 - abs((signed)((leveltime % 8) - 4)))*FRACUNIT, + newval = (4 - abs((signed)((leveltime % 8) - 4))) * FRACUNIT; + oldval = (4 - abs((signed)((leveltimeOld % 8) - 4))) * FRACUNIT; + interpy += oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, interpy, FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL); } if (stplyr->laps == (UINT8)(cv_numlaps.value)) { - V_DrawFixedPatch((62 - (32*max(0, progress-76)))*FRACUNIT, // 27 + newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, // 27 30*FRACUNIT, // 24 FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_final[min(progress/2, 10)], NULL); if (progress/2-12 >= 0) { - V_DrawFixedPatch((188 + (32*max(0, progress-76)))*FRACUNIT, // 194 + newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, // 194 30*FRACUNIT, // 24 FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_lap[min(progress/2-12, 6)], NULL); @@ -3943,21 +4023,36 @@ static void K_drawLapStartAnim(void) } else { - V_DrawFixedPatch((82 - (32*max(0, progress-76)))*FRACUNIT, // 61 + newval = (82 - (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (82 - (32 * max(0, progressOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, // 61 30*FRACUNIT, // 24 FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_lap[min(progress/2, 6)], NULL); if (progress/2-8 >= 0) { - V_DrawFixedPatch((188 + (32*max(0, progress-76)))*FRACUNIT, // 194 + newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, // 194 30*FRACUNIT, // 24 FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_number[(((UINT32)stplyr->laps) / 10)][min(progress/2-8, 2)], NULL); if (progress/2-10 >= 0) { - V_DrawFixedPatch((208 + (32*max(0, progress-76)))*FRACUNIT, // 221 + newval = (208 + (32 * max(0, progress - 76))) * FRACUNIT; + oldval = (208 + (32 * max(0, progressOld - 76))) * FRACUNIT; + interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + + V_DrawFixedPatch( + interpx, // 221 30*FRACUNIT, // 24 FRACUNIT, V_SNAPTOTOP|V_HUDTRANS, kp_lapanim_number[(((UINT32)stplyr->laps) % 10)][min(progress/2-10, 2)], NULL); diff --git a/src/k_kart.c b/src/k_kart.c index e8b424179..1e742ca60 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3754,7 +3754,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) { @@ -4717,7 +4717,7 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, { // 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; @@ -5347,7 +5347,7 @@ void K_DropHnextList(player_t *player, boolean keepshields) { // 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) { @@ -5873,7 +5873,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; @@ -5986,7 +5986,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); if (P_IsObjectOnGround(cur)) { @@ -6076,12 +6076,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. cur->roll = player->mo->roll; @@ -8480,7 +8480,12 @@ static void K_trickPanelTimingVisual(player_t *player, fixed_t momz) flame->frame = i|FF_FULLBRIGHT; if (player->trickpanel <= 1 && !player->tumbleBounces) + { flame->tics = 2; + flame->momx = player->mo->momx; + flame->momy = player->mo->momy; + flame->momz = player->mo->momz; + } else { flame->tics = TICRATE; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 0ce78b6f9..e07c41bd4 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1415,7 +1415,42 @@ static int lib_pTeleportMove(lua_State *L) INLEVEL 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_SetOrigin(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 + INLEVEL + 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 + INLEVEL + 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; @@ -3835,6 +3870,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}, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 0821cac6d..8a4a1e7a5 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -477,7 +477,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)); diff --git a/src/m_cheat.c b/src/m_cheat.c index b45a7cbb6..384edbba2 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -420,7 +420,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); @@ -641,7 +641,7 @@ void Command_Teleport_f(void) } P_MapStart(); - if (!P_TeleportMove(p->mo, intx, inty, intz)) + if (!P_SetOrigin(p->mo, intx, inty, intz)) CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n")); else S_StartSound(p->mo, sfx_mixup); @@ -1039,7 +1039,7 @@ void OP_ObjectplaceMovement(player_t *player) if (cmd->forwardmove != 0) { P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*player->mo->scale/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; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 9f5fc86d8..0befaa293 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1145,7 +1145,7 @@ void A_FaceStabHurl(mobj_t *actor) hwork->destscale = FixedSqrt(step*basesize); P_SetScale(hwork, hwork->destscale); hwork->fuse = 2; - P_TeleportMove(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<x + P_ReturnThrustX(actor, actor->angle, locvar1*crab->scale), crab->y + P_ReturnThrustY(actor, actor->angle, locvar1*crab->scale), crab->z + locvar2*crab->scale); @@ -2043,7 +2043,7 @@ void A_CrushclawLaunch(mobj_t *actor) fixed_t idx = dx, idy = dy, idz = dz; while (chain) { - P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); + P_MoveOrigin(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); chain->movefactor = chain->z; idx += dx; idy += dy; @@ -4023,7 +4023,7 @@ void A_AttractChase(mobj_t *actor) //P_SetScale(actor, (actor->destscale = actor->target->scale)); actor->z = actor->target->z; K_MatchGenericExtraFlags(actor, actor->target); - P_TeleportMove(actor, actor->target->x, actor->target->y, + P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->z + ( actor->target->height + offz )* P_MobjFlip(actor)); actor->extravalue1++; @@ -4052,7 +4052,7 @@ void A_AttractChase(mobj_t *actor) P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1))); actor->z = actor->target->z; K_MatchGenericExtraFlags(actor, actor->target); - P_TeleportMove(actor, + P_MoveOrigin(actor, actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)), actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)), actor->z + actor->target->scale * 24 * P_MobjFlip(actor)); @@ -9911,7 +9911,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); @@ -9956,7 +9956,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); @@ -10629,13 +10629,13 @@ void A_FlickyCenter(mobj_t *actor) if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1) { actor->extravalue2 = 1; - P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + P_SetOrigin(actor, actor->target->x, actor->target->y, actor->target->z); tmthing = NULL; } else if(actor->extravalue2) { actor->extravalue2 = 0; - P_TeleportMove(actor, originx, originy, originz); + P_SetOrigin(actor, originx, originy, originz); tmthing = NULL; } } @@ -11172,7 +11172,7 @@ void A_LightBeamReset(mobj_t *actor) actor->momy = (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; actor->momz = (P_SignedRandom()*FRACUNIT)/128; - P_TeleportMove(actor, + P_SetOrigin(actor, actor->spawnpoint->x*FRACUNIT - (P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, actor->spawnpoint->y*FRACUNIT + (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, actor->spawnpoint->z*FRACUNIT + (P_SignedRandom()*FRACUNIT)/2); @@ -11757,7 +11757,7 @@ void A_DoNPCSkid(mobj_t *actor) actor->momy = (2*actor->momy)/3; } - P_TeleportMove(actor, x, y, z); + P_MoveOrigin(actor, x, y, z); // Spawn a particle every 3 tics. if (!(leveltime % 3)) @@ -12098,7 +12098,7 @@ void A_Boss5MakeJunk(mobj_t *actor) if (locvar1 > 0) P_SetMobjState(broked, locvar1); if (!P_MobjWasRemoved(broked)) - P_TeleportMove(broked, broked->x + broked->momx, broked->y + broked->momy, broked->z); + P_MoveOrigin(broked, broked->x + broked->momx, broked->y + broked->momy, broked->z); ang += ANGLE_45; } @@ -13161,7 +13161,7 @@ void A_DragonWing(mobj_t *actor) actor->angle = target->angle + actor->movedir; x = target->x + P_ReturnThrustX(actor, actor->angle, -target->radius); y = target->y + P_ReturnThrustY(actor, actor->angle, -target->radius); - P_TeleportMove(actor, x, y, target->z); + P_MoveOrigin(actor, x, y, target->z); } // Function: A_DragonSegment @@ -13202,7 +13202,7 @@ void A_DragonSegment(mobj_t *actor) zdist = P_ReturnThrustY(target, zangle, radius); actor->angle = hangle; - P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist); + P_MoveOrigin(actor, target->x + xdist, target->y + ydist, target->z + zdist); } // Function: A_ChangeHeight @@ -14164,10 +14164,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; @@ -14644,7 +14644,7 @@ void A_InvincSparkleRotate(mobj_t *actor) sx = actor->target->x + FixedMul((actor->movefactor), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT)); sy = actor->target->y + FixedMul((actor->movefactor), FINESINE((actor->angle)>>ANGLETOFINESHIFT)); sz = actor->target->z + (actor->extravalue1) + FixedMul((actor->cvmem), FINECOSINE((leveltime*ANG1*10 + actor->angle)>>ANGLETOFINESHIFT)); - P_TeleportMove(actor, sx, sy, sz); + P_MoveOrigin(actor, sx, sy, sz); actor->momx = actor->target->momx; actor->momy = actor->target->momy; diff --git a/src/p_inter.c b/src/p_inter.c index e5df84913..0a2bb4e13 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -237,7 +237,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<mo, special->target->x, special->target->y, special->target->z + (48<mo->angle = special->target->angle; P_SetObjectMomZ(player->mo, 12<mo, player->mo->angle, 20<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 // ========================================================================= @@ -1598,7 +1623,7 @@ static boolean PIT_CheckLine(line_t *ld) cosradius = FixedMul(dist, FINECOSINE(langle>>ANGLETOFINESHIFT)); sinradius = FixedMul(dist, FINESINE(langle>>ANGLETOFINESHIFT)); tmthing->flags |= MF_NOCLIP; - P_TeleportMove(tmthing, result.x + cosradius - tmthing->momx, result.y + sinradius - tmthing->momy, tmthing->z); + P_MoveOrigin(tmthing, result.x + cosradius - tmthing->momx, result.y + sinradius - tmthing->momy, tmthing->z); tmthing->flags &= ~MF_NOCLIP; } #endif diff --git a/src/p_mobj.c b/src/p_mobj.c index 2b2cfc251..27c23ea92 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3636,6 +3636,11 @@ void P_NullPrecipThinker(precipmobj_t *mobj) void P_PrecipThinker(precipmobj_t *mobj) { + // reset old state (for interpolation) + mobj->old_x = mobj->x; + mobj->old_y = mobj->y; + mobj->old_z = mobj->z; + P_CycleStateAnimation((mobj_t *)mobj); if (mobj->state == &states[S_RAINRETURN]) @@ -3790,9 +3795,9 @@ static void P_ItemCapsulePartThinker(mobj_t *mobj) // rotate & move to capsule mobj->angle += mobj->movedir; if (mobj->flags2 & MF2_CLASSICPUSH) // centered - P_TeleportMove(mobj, target->x, target->y, z); + P_MoveOrigin(mobj, target->x, target->y, z); else - P_TeleportMove(mobj, + P_MoveOrigin(mobj, target->x + P_ReturnThrustX(mobj, mobj->angle + ANGLE_90, mobj->radius), target->y + P_ReturnThrustY(mobj, mobj->angle + ANGLE_90, mobj->radius), z); @@ -4211,7 +4216,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y if (dist < source->movefactor) { source->momx = source->momy = source->momz = 0; - P_TeleportMove(source, tx, ty, tz); + P_MoveOrigin(source, tx, ty, tz); } else { @@ -6542,7 +6547,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->angle += ANGLE_90; } - P_TeleportMove(mobj, + P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, angle + ANGLE_180, nudge), mobj->target->y + P_ReturnThrustY(mobj, angle + ANGLE_180, nudge), mobj->target->z); @@ -6621,7 +6626,7 @@ static boolean P_MobjRegularThink(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); @@ -6673,7 +6678,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_RemoveMobj(mobj); return false; } - 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_BRAKEDRIFT: if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) @@ -6694,7 +6699,7 @@ static boolean P_MobjRegularThink(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->drift); P_SetScale(mobj, (mobj->destscale = mobj->target->scale)); @@ -6723,7 +6728,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { mobj->fuse = 9; } - P_TeleportMove(mobj, mobj->target->x, + P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z); mobj->angle = mobj->target->angle + mobj->cusval; break; @@ -6733,7 +6738,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_RemoveMobj(mobj); return false; } - 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->renderflags ^= RF_DONTDRAW; @@ -6745,7 +6750,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_RemoveMobj(mobj); return false; } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z); K_MatchGenericExtraFlags(mobj, mobj->target); break; case MT_BATTLEPOINT: @@ -6768,7 +6773,7 @@ static boolean P_MobjRegularThink(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_RINGSPARKS: if (!mobj->target || P_MobjWasRemoved(mobj->target)) @@ -6781,7 +6786,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) K_MatchGenericExtraFlags(mobj, mobj->target); - P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), + P_MoveOrigin(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), mobj->z + (mobj->target->height * P_MobjFlip(mobj))); break; @@ -6802,7 +6807,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) K_MatchGenericExtraFlags(mobj, mobj->target); mobj->renderflags = (mobj->renderflags & ~RF_DONTDRAW)|K_GetPlayerDontDrawFlag(mobj->target->player); - P_TeleportMove(mobj, mobj->target->x + FixedMul(34 * mapobjectscale, FINECOSINE((mobj->angle + mobj->movedir) >> ANGLETOFINESHIFT)), + P_MoveOrigin(mobj, mobj->target->x + FixedMul(34 * mapobjectscale, FINECOSINE((mobj->angle + mobj->movedir) >> ANGLETOFINESHIFT)), mobj->target->y + FixedMul(34 * mapobjectscale, FINESINE((mobj->angle + mobj->movedir) >> ANGLETOFINESHIFT)), mobj->z + (32 * mapobjectscale * P_MobjFlip(mobj))); @@ -6845,7 +6850,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) fixed_t newx = mobj->target->x + P_ReturnThrustX(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); fixed_t newy = mobj->target->y + P_ReturnThrustY(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); - P_TeleportMove(mobj, newx, newy, mobj->target->z); + P_MoveOrigin(mobj, newx, newy, mobj->target->z); if (mobj->extravalue1 & 1) mobj->angle = mobj->target->angle - ANGLE_45; @@ -6883,7 +6888,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else ang = (signed)(ang + off); - P_TeleportMove(mobj, + P_MoveOrigin(mobj, mobj->target->x - FixedMul(mobj->target->radius, FINECOSINE(ang >> ANGLETOFINESHIFT)), mobj->target->y - FixedMul(mobj->target->radius, FINESINE(ang >> ANGLETOFINESHIFT)), z); @@ -6938,7 +6943,7 @@ static boolean P_MobjRegularThink(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_BUBBLESHIELD: @@ -7066,7 +7071,7 @@ static boolean P_MobjRegularThink(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_FLAMESHIELD: @@ -7174,7 +7179,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) desty = mobj->target->y; } - P_TeleportMove(mobj, destx, desty, mobj->target->z); + P_MoveOrigin(mobj, destx, desty, mobj->target->z); mobj->angle = K_MomentumAngle(mobj->target); if (underlayst != S_NULL) @@ -7218,7 +7223,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } - 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; @@ -7268,7 +7273,7 @@ static boolean P_MobjRegularThink(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); @@ -7407,7 +7412,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) amt += 1; } - P_TeleportMove( + P_MoveOrigin( cur, mobj->x + FixedMul(amt, FINECOSINE(dir >> ANGLETOFINESHIFT)), mobj->y + FixedMul(amt, FINESINE(dir >> ANGLETOFINESHIFT)), @@ -7497,7 +7502,7 @@ static boolean P_MobjRegularThink(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; @@ -7630,7 +7635,7 @@ static boolean P_MobjRegularThink(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); @@ -7741,7 +7746,7 @@ static boolean P_MobjRegularThink(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 { @@ -7815,7 +7820,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->extravalue1 = 1; player->offroad += 2<mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius) + P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius) @@ -7976,7 +7981,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->tracer->momx = mobj->tracer->momy = 0; } - P_TeleportMove(mobj, + P_MoveOrigin(mobj, mobj->tracer->x + P_ReturnThrustX(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->y + P_ReturnThrustY(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->z - (4*mobj->tracer->scale) + (P_RandomRange(-abs(mobj->cvmem), abs(mobj->cvmem))<angle = angle + ANGLE_90; } - P_TeleportMove(cur, newx, newy, newz); + P_MoveOrigin(cur, newx, newy, newz); cur = cur->hnext; } @@ -8345,7 +8350,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->extravalue1++; dist = mobj->extravalue1 * mapobjectscale; - P_TeleportMove(mobj, battleovertime.x + P_ReturnThrustX(NULL, ang, dist), + P_MoveOrigin(mobj, battleovertime.x + P_ReturnThrustX(NULL, ang, dist), battleovertime.y + P_ReturnThrustY(NULL, ang, dist), z); ghost = P_SpawnGhostMobj(mobj); @@ -8593,6 +8598,11 @@ void P_MobjThinker(mobj_t *mobj) I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); + // Set old position (for interpolation) + mobj->old_x = mobj->x; + mobj->old_y = mobj->y; + mobj->old_z = mobj->z; + // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) P_SetTarget(&mobj->target, NULL); @@ -9670,7 +9680,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)<>ANGLETOFINESHIFT) & FINEMASK)), + P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<>ANGLETOFINESHIFT) & FINEMASK)), cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<>ANGLETOFINESHIFT) & FINEMASK)), cur->z); cur->angle = ANGLE_90*(cur->threshold+1); @@ -9743,6 +9753,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (CheckForReverseGravity && !(mobj->flags & MF_NOBLOCKMAP)) P_CheckGravity(mobj, false); + // set initial old positions (for interpolation) + mobj->old_x = mobj->x; + mobj->old_y = mobj->y; + mobj->old_z = mobj->z; + return mobj; } @@ -9794,6 +9809,11 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype || mobj->subsector->sector->floorpic == skyflatnum) mobj->precipflags |= PCF_PIT; + // set initial old positions (for interpolation) + mobj->old_x = mobj->x; + mobj->old_y = mobj->y; + mobj->old_z = mobj->z; + return mobj; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 16055907b..3247c14d7 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -275,6 +275,7 @@ typedef struct mobj_s // Info for drawing: position. fixed_t x, y, z; + fixed_t old_x, old_y, old_z; // position interpolation // More list: links in sector (if needed) struct mobj_s *snext; @@ -412,6 +413,7 @@ typedef struct precipmobj_s // Info for drawing: position. fixed_t x, y, z; + fixed_t old_x, old_y, old_z; // position interpolation // More list: links in sector (if needed) struct precipmobj_s *snext; diff --git a/src/p_telept.c b/src/p_telept.c index 0c324c8c9..3e2917092 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -120,7 +120,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; if (!dontstopmove) diff --git a/src/p_tick.c b/src/p_tick.c index be82b9d40..9a4baa092 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -24,6 +24,7 @@ #include "lua_hook.h" #include "m_perfstats.h" #include "i_system.h" // I_GetPreciseTime +#include "r_fps.h" // Object place #include "m_cheat.h" diff --git a/src/p_user.c b/src/p_user.c index c58e61b4d..2d849c312 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1138,6 +1138,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW); } + // Copy interpolation data :) + ghost->old_x = mobj->old_x; + ghost->old_y = mobj->old_y; + ghost->old_z = mobj->old_z; + return ghost; } @@ -2115,6 +2120,9 @@ void P_MovePlayer(player_t *player) ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); water->angle = forwardangle - ANGLE_180 - ANGLE_22h; water->destscale = trailScale; + water->momx = player->mo->momx; + water->momy = player->mo->momy; + water->momz = player->mo->momz; P_SetScale(water, trailScale); P_SetMobjState(water, curUnderlayFrame); @@ -2123,6 +2131,9 @@ void P_MovePlayer(player_t *player) ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); water->angle = forwardangle - ANGLE_180 - ANGLE_22h; water->destscale = trailScale; + water->momx = player->mo->momx; + water->momy = player->mo->momy; + water->momz = player->mo->momz; P_SetScale(water, trailScale); P_SetMobjState(water, curOverlayFrame); @@ -2132,6 +2143,9 @@ void P_MovePlayer(player_t *player) ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); water->angle = forwardangle - ANGLE_180 + ANGLE_22h; water->destscale = trailScale; + water->momx = player->mo->momx; + water->momy = player->mo->momy; + water->momz = player->mo->momz; P_SetScale(water, trailScale); P_SetMobjState(water, curUnderlayFrame); @@ -2140,6 +2154,9 @@ void P_MovePlayer(player_t *player) ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); water->angle = forwardangle - ANGLE_180 + ANGLE_22h; water->destscale = trailScale; + water->momx = player->mo->momx; + water->momy = player->mo->momy; + water->momz = player->mo->momz; P_SetScale(water, trailScale); P_SetMobjState(water, curOverlayFrame); diff --git a/src/r_fps.c b/src/r_fps.c new file mode 100644 index 000000000..2d2b4f61e --- /dev/null +++ b/src/r_fps.c @@ -0,0 +1,163 @@ +// 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" +#ifdef HWRENDER +#include "hardware/hw_main.h" // for cv_glshearing +#endif + +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]; +viewvars_t *newview = &pview_new[0]; + + +enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1; + +static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac) +{ + return FixedMul(frac, to - from); +} + +static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac) +{ + return FixedMul(frac, to - from); +} + +// 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) +{ +#ifndef HWRENDER + (void)player; + (void)skybox; +#endif + + // 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 + || (rendermode == render_opengl + && (cv_glshearing.value == 1 + || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox)))) +#endif + ) + { + G_SoftwareClipAimingPitch((INT32 *)&aimingangle); + } + + centeryfrac = (viewheight/2)< FRACUNIT) + frac = FRACUNIT; + + viewx = oldview->x + R_LerpFixed(oldview->x, newview->x, frac); + viewy = oldview->y + R_LerpFixed(oldview->y, newview->y, frac); + viewz = oldview->z + R_LerpFixed(oldview->z, newview->z, frac); + + viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac); + aimingangle = oldview->aim + R_LerpAngle(oldview->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; + + // well, this ain't pretty + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (newview == &skyview_new[i]) + { + skybox = true; + break; + } + } + + R_SetupFreelook(newview->player, skybox); +} + +void R_UpdateViewInterpolation(void) +{ + INT32 i; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + pview_old[i] = pview_new[i]; + skyview_old[i] = skyview_new[i]; + } +} + +void R_SetViewContext(enum viewcontext_e _viewcontext) +{ + INT32 i; + + 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; + } +} diff --git a/src/r_fps.h b/src/r_fps.h new file mode 100644 index 000000000..2d4dbe874 --- /dev/null +++ b/src/r_fps.h @@ -0,0 +1,58 @@ +// 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" + +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; + +// 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); +// Set the current view context (the viewvars pointed to by newview) +void R_SetViewContext(enum viewcontext_e _viewcontext); + +#endif diff --git a/src/r_main.c b/src/r_main.c index dfc11ab4a..231bde280 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -36,6 +36,7 @@ #include "r_main.h" #include "i_system.h" // I_GetPreciseTime #include "doomstat.h" // MAXSPLITSCREENPLAYERS +#include "r_fps.h" // Frame interpolation/uncapped #ifdef HWRENDER #include "hardware/hw_main.h" @@ -79,6 +80,9 @@ mobj_t *r_viewmobj; int r_splitscreen; +fixed_t rendertimefrac; +fixed_t renderdeltatics; + // // precalculated math tables // @@ -100,6 +104,9 @@ lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *scalelightfixed[MAXLIGHTSCALE]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; +// Frame interpolation/uncapped +tic_t prev_tics; + // Hack to support extra boom colormaps. extracolormap_t *extra_colormaps = NULL; @@ -172,6 +179,9 @@ consvar_t cv_fov[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("fov4", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange) }; +// Frame interpolation/uncapped +consvar_t cv_frameinterpolation = CVAR_INIT ("frameinterpolation", "On", CV_SAVE, CV_OnOff, NULL); + // Okay, whoever said homremoval causes a performance hit should be shot. consvar_t cv_homremoval = CVAR_INIT ("homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL); @@ -1193,40 +1203,6 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) // R_SetupFrame // -// 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) -{ -#ifndef HWRENDER - (void)player; - (void)skybox; -#endif - - // 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 - || (rendermode == render_opengl - && (cv_glshearing.value == 1 - || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox)))) -#endif - ) - { - G_SoftwareClipAimingPitch((INT32 *)&aimingangle); - } - - centeryfrac = (viewheight/2)<chase = false; + newview->sky = false; + if (player->awayviewtics) { // cut-away view stuff r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN I_Assert(r_viewmobj != NULL); - viewz = r_viewmobj->z + 20*FRACUNIT; - aimingangle = player->awayviewaiming; - viewangle = r_viewmobj->angle; + newview->z = r_viewmobj->z + 20*FRACUNIT; + newview->aim = player->awayviewaiming; + newview->angle = r_viewmobj->angle; } else if (!player->spectator && chasecam) // use outside cam view { r_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; r_viewmobj = player->mo; I_Assert(r_viewmobj != NULL); - aimingangle = player->aiming; - viewangle = r_viewmobj->angle; + newview->aim = player->aiming; + newview->angle = r_viewmobj->angle; if (!demo.playback && player->playerstate != PST_DEAD) { - viewangle = localangle[i]; // WARNING: camera uses this - aimingangle = localaiming[i]; + newview->angle = localangle[i]; // WARNING: camera uses this + newview->aim = localaiming[i]; } } - 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) - 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 = r_viewmobj->x; - viewy = r_viewmobj->y; - viewx += quake.x; - viewy += quake.y; + newview->x = r_viewmobj->x; + newview->y = r_viewmobj->y; + newview->x += quake.x; + newview->y += quake.y; if (r_viewmobj->subsector) - viewsector = r_viewmobj->subsector->sector; + newview->sector = r_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(player, false); + R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); } void R_SkyboxFrame(player_t *player) @@ -1338,6 +1317,7 @@ void R_SkyboxFrame(player_t *player) if (player == &players[displayplayers[i]]) { thiscam = &camera[i]; + R_SetViewContext(VIEWCONTEXT_SKY1 + i); break; } } @@ -1349,6 +1329,7 @@ void R_SkyboxFrame(player_t *player) } // cut-away view stuff + newview->sky = true; r_viewmobj = skyboxmo[0]; #ifdef PARANOIA if (!r_viewmobj) @@ -1359,31 +1340,31 @@ 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) { - viewangle = localangle[i]; - aimingangle = localaiming[i]; + newview->angle = localangle[i]; + newview->aim = localaiming[i]; } } - viewangle += r_viewmobj->angle; + newview->angle += r_viewmobj->angle; - viewplayer = player; + newview->player = player; - viewx = r_viewmobj->x; - viewy = r_viewmobj->y; - viewz = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! + newview->x = r_viewmobj->x; + newview->y = r_viewmobj->y; + newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! if (mapheaderinfo[gamemap-1]) { @@ -1425,46 +1406,46 @@ void R_SkyboxFrame(player_t *player) if (r_viewmobj->angle == 0) { - viewx += x; - viewy += y; + newview->x += x; + newview->y += y; } else if (r_viewmobj->angle == ANGLE_90) { - viewx -= y; - viewy += x; + newview->x -= y; + newview->y += x; } else if (r_viewmobj->angle == ANGLE_180) { - viewx -= x; - viewy -= y; + newview->x -= x; + newview->y -= y; } else if (r_viewmobj->angle == ANGLE_270) { - viewx += y; - viewy -= x; + newview->x += y; + newview->y -= x; } else { angle_t ang = r_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 += campos.z / mh->skybox_scalez; + newview->z += campos.z / mh->skybox_scalez; else if (mh->skybox_scalez < 0) - viewz += campos.z * -mh->skybox_scalez; + newview->z += campos.z * -mh->skybox_scalez; } if (r_viewmobj->subsector) - viewsector = r_viewmobj->subsector->sector; + newview->sector = r_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(player, true); + R_InterpolateView(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT); } boolean R_ViewpointHasChasecam(player_t *player) @@ -1737,4 +1718,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_maxportals); CV_RegisterVar(&cv_movebob); + + // Frame interpolation/uncapped + CV_RegisterVar(&cv_frameinterpolation); } diff --git a/src/r_main.h b/src/r_main.h index 5208b52a3..a2acf60d9 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -33,6 +33,11 @@ extern fixed_t fovtan[MAXSPLITSCREENPLAYERS]; 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;; + // // Lighting LUT. // Used for z-depth cuing per column/row, @@ -111,6 +116,10 @@ extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; +// Frame interpolation (uncapped framerate) +extern tic_t prev_tics; +extern consvar_t cv_frameinterpolation; + // Called by startup code. void R_Init(void); diff --git a/src/r_things.c b/src/r_things.c index defd02a5f..6d9cca7a4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1361,16 +1361,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, // static void R_ProjectSprite(mobj_t *thing) { - fixed_t thingxpos = thing->x + thing->sprxoff; - fixed_t thingypos = thing->y + thing->spryoff; - fixed_t thingzpos = thing->z + thing->sprzoff; - mobj_t *oldthing = thing; - //const fixed_t oldthingxpos = oldthing->x + oldthing->sprxoff; - //const fixed_t oldthingypos = oldthing->y + oldthing->spryoff; - const fixed_t oldthingzpos = oldthing->z + oldthing->sprzoff; - fixed_t tr_x, tr_y; fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! @@ -1435,7 +1427,32 @@ static void R_ProjectSprite(mobj_t *thing) angle_t spriterotangle = 0; #endif - // hitlag vibrating + // uncapped/interpolation + fixed_t interpx = thing->x; + fixed_t interpy = thing->y; + fixed_t interpz = thing->z; + angle_t interpangle = thing->angle; + + // use player drawangle if player + if (thing->player) interpangle = thing->player->drawangle; + + // do interpolation + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); + interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); + interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + if (thing->player) + { + interpangle = thing->player->drawangle; + } + else + { + interpangle = thing->angle; + } + } + + // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) { fixed_t mul = thing->hitlag * (FRACUNIT / 10); @@ -1445,14 +1462,19 @@ static void R_ProjectSprite(mobj_t *thing) mul = -mul; } - thingxpos += FixedMul(thing->momx, mul); - thingypos += FixedMul(thing->momy, mul); - thingzpos += FixedMul(thing->momz, mul); + interpx += FixedMul(thing->momx, mul); + interpy += FixedMul(thing->momy, mul); + interpz += FixedMul(thing->momz, mul); } + // sprite offset + interpx += thing->sprxoff; + interpy += thing->spryoff; + interpz += thing->sprzoff; + // transform the origin point - tr_x = thingxpos - viewx; - tr_y = thingypos - viewy; + tr_x = interpx - viewx; + tr_y = interpy - viewy; basetz = tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance @@ -1529,7 +1551,7 @@ static void R_ProjectSprite(mobj_t *thing) if (sprframe->rotate != SRF_SINGLE || papersprite) { - ang = R_PointToAngle (thingxpos, thingypos) - (thing->player ? thing->player->drawangle : thing->angle); + ang = R_PointToAngle (interpx, interpy) - interpangle; if (mirrored) ang = InvAngle(ang); } @@ -1544,7 +1566,7 @@ static void R_ProjectSprite(mobj_t *thing) else { // choose a different rotation based on player view - //ang = R_PointToAngle (thingxpos, thingypos) - thing->angle; + //ang = R_PointToAngle (interpx, interpy) - interpangle; if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right rot = 6; // F7 slot @@ -1755,12 +1777,37 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t linkscale; thing = thing->tracer; + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac); + interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac); + } + + // hitlag vibrating (todo: interp somehow?) + if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) + { + fixed_t mul = thing->hitlag * (FRACUNIT / 10); + + if (leveltime & 1) + { + mul = -mul; + } + + interpx += FixedMul(thing->momx, mul); + interpy += FixedMul(thing->momy, mul); + interpz += FixedMul(thing->momz, mul); + } + + // sprite offset + interpx += thing->sprxoff; + interpy += thing->spryoff; + interpz += thing->sprzoff; if (! R_ThingVisible(thing)) return; - tr_x = (thingxpos + sort_x) - viewx; - tr_y = (thingypos + sort_y) - viewy; + tr_x = (interpx + sort_x) - viewx; + tr_y = (interpy + sort_y) - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); linkscale = FixedDiv(projectiony[viewssnum], tz); @@ -1775,8 +1822,8 @@ static void R_ProjectSprite(mobj_t *thing) } else if (splat) { - tr_x = (thingxpos + sort_x) - viewx; - tr_y = (thingypos + sort_y) - viewy; + tr_x = (interpx + sort_x) - viewx; + tr_y = (interpy + sort_y) - viewy; sort_z = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); sortscale = FixedDiv(projectiony[viewssnum], sort_z); } @@ -1796,7 +1843,7 @@ static void R_ProjectSprite(mobj_t *thing) if (x2 < portalclipstart || x1 >= portalclipend) return; - if (P_PointOnLineSide(thingxpos, thingypos, portalclipline) != 0) + if (P_PointOnLineSide(interpx, interpy, portalclipline) != 0) return; } @@ -1865,12 +1912,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 = oldthingzpos + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gz = interpz + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); } else { - gzt = oldthingzpos + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gzt = interpz + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); gz = gzt - FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); } } @@ -1889,7 +1936,7 @@ static void R_ProjectSprite(mobj_t *thing) // R_GetPlaneLight won't work on sloped lights! for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { - fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thingxpos, thingypos); + fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], interpx, interpy); if (h <= top) { light = lightnum - 1; break; @@ -1907,7 +1954,7 @@ static void R_ProjectSprite(mobj_t *thing) } heightsec = thing->subsector->sector->heightsec; - if (viewplayer->mo && viewplayer->mo->subsector) + if (viewplayer && viewplayer->mo && viewplayer->mo->subsector) phs = viewplayer->mo->subsector->sector->heightsec; else phs = -1; @@ -1915,12 +1962,12 @@ static void R_ProjectSprite(mobj_t *thing) if (heightsec != -1 && phs != -1) // only clip things which are in special sectors { if (viewz < sectors[phs].floorheight ? - thingzpos >= sectors[heightsec].floorheight : + interpz >= sectors[heightsec].floorheight : gzt < sectors[heightsec].floorheight) return; if (viewz > sectors[phs].ceilingheight ? gzt < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight : - thingzpos >= sectors[heightsec].ceilingheight) + interpz >= sectors[heightsec].ceilingheight) return; } @@ -1933,12 +1980,12 @@ static void R_ProjectSprite(mobj_t *thing) vis->sortscale = sortscale; vis->sortsplat = sortsplat; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15 - vis->gx = thingxpos; - vis->gy = thingypos; + vis->gx = interpx; + vis->gy = interpy; vis->gz = gz; vis->gzt = gzt; vis->thingheight = thing->height; - vis->pz = thingzpos; + vis->pz = interpz; vis->pzt = vis->pz + vis->thingheight; vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); vis->scalestep = scalestep; @@ -2073,9 +2120,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) //SoM: 3/17/2000 fixed_t gz, gzt; + // uncapped/interpolation + fixed_t interpx = thing->x; + fixed_t interpy = thing->y; + fixed_t interpz = thing->z; + + // do interpolation + if (cv_frameinterpolation.value == 1 && !paused) + { + interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); + interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); + interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); + } + // transform the origin point - tr_x = thing->x - viewx; - tr_y = thing->y - viewy; + tr_x = interpx - viewx; + tr_y = interpy - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance @@ -2139,12 +2199,12 @@ 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(interpx, interpy, portalclipline) != 0) return; } //SoM: 3/17/2000: Disregard sprites that are out of view.. - gzt = thing->z + spritecachedinfo[lump].topoffset; + gzt = interpz + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height; if (thing->subsector->sector->cullheight) @@ -2157,10 +2217,13 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis = R_NewVisSprite(); vis->scale = vis->sortscale = yscale; //<dispoffset = 0; // Monster Iestyn: 23/11/15 - vis->gx = thing->x; - vis->gy = thing->y; + vis->gx = interpx; + vis->gy = interpy; vis->gz = gz; vis->gzt = gzt; + vis->thingheight = 4*FRACUNIT; + vis->pz = interpz; + vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 2778e6b6f..71b5af958 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -181,7 +181,7 @@ static char returnWadPath[256]; #include "../m_argv.h" -#include "../m_menu.h" +#include "../r_main.h" // Frame interpolation/uncapped #ifdef MAC_ALERT #include "macosx/mac_alert.h" @@ -1640,17 +1640,29 @@ static Uint64 timer_frequency; static double tic_frequency; static Uint64 tic_epoch; +static double elapsed_tics; + +static void UpdateElapsedTics(void) +{ + const Uint64 now = SDL_GetPerformanceCounter(); + + elapsed_tics += (now - tic_epoch) / tic_frequency; + tic_epoch = now; // moving epoch +} tic_t I_GetTime(void) { - static double elapsed; + double f = 0.0; + UpdateElapsedTics(); + f = floor(elapsed_tics); + return (tic_t)f; +} - const Uint64 now = SDL_GetPerformanceCounter(); - - elapsed += (now - tic_epoch) / tic_frequency; - tic_epoch = now; // moving epoch - - return (tic_t)elapsed; +fixed_t I_GetTimeFrac(void) +{ + UpdateElapsedTics(); + + return FLOAT_TO_FIXED((float) (elapsed_tics - floor(elapsed_tics))); } precise_t I_GetPreciseTime(void) @@ -1672,6 +1684,7 @@ void I_StartupTimer(void) tic_epoch = SDL_GetPerformanceCounter(); tic_frequency = timer_frequency / (double)NEWTICRATE; + elapsed_tics = 0.0; } void I_Sleep(void) diff --git a/src/st_stuff.c b/src/st_stuff.c index ee03a07a4..3e0788f4d 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1260,6 +1260,7 @@ void ST_Drawer(void) if (rendermode != render_none) ST_doPaletteStuff(); { +#if 0 const tic_t length = TICRATE/2; if (lt_exitticker) @@ -1270,6 +1271,9 @@ void ST_Drawer(void) } else st_translucency = 0; +#else + st_translucency = cv_translucenthud.value; +#endif } // Check for a valid level title diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 2609c3e31..9b2c5bd07 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -45,6 +45,7 @@ #include "../d_main.h" #include "../m_argv.h" +#include "../m_fixed.h" #include "../w_wad.h" #include "../z_zone.h" @@ -261,6 +262,11 @@ tic_t I_GetTime(void) return newtics; } +fixed_t I_GetTimeFrac(void) +{ + return 0; +} + void I_Sleep(void) { if (cv_sleep.value > 0)