diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index 4b033c31a..830bf6912 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -387,6 +387,11 @@ inline constexpr int32_t interpolatedangle(int32_t oang, int32_t ang, int const return oang + MulScale(((ang + 1024 - oang) & 2047) - 1024, smoothratio, scale); } +inline constexpr double interpolatedanglef(double oang, double ang, double const smoothratio, int const scale = 16) +{ + return oang + MulScaleF(fmod((ang + 1024. - oang), 2048.) - 1024., smoothratio, scale); +} + inline constexpr binangle interpolatedangle(binangle oang, binangle ang, double const smoothratio, int const scale = 16) { return bamang(oang.asbam() + MulScale(((ang.asbam() + 0x80000000 - oang.asbam()) & 0xFFFFFFFF) - 0x80000000, int(smoothratio), scale)); diff --git a/source/core/gamehud.cpp b/source/core/gamehud.cpp index c009652e6..baee0c248 100644 --- a/source/core/gamehud.cpp +++ b/source/core/gamehud.cpp @@ -50,9 +50,9 @@ F2DDrawer twodpsp; -void hud_drawsprite(double sx, double sy, int z, double a, int picnum, int dashade, int dapalnum, int dastat, double alpha) +void hud_drawsprite(double sx, double sy, double sz, double a, int picnum, int dashade, int dapalnum, int dastat, double alpha) { - double dz = z / 65536.; + sz *= 1. / 65536.; alpha *= (dastat & RS_TRANS1)? glblend[0].def[!!(dastat & RS_TRANS2)].alpha : 1.; int palid = TRANSLATION(Translation_Remap + curbasepal, dapalnum); @@ -62,7 +62,7 @@ void hud_drawsprite(double sx, double sy, int z, double a, int picnum, int dasha auto tex = tileGetTexture(picnum); DrawTexture(&twodpsp, tex, sx, sy, - DTA_ScaleX, dz, DTA_ScaleY, dz, + DTA_ScaleX, sz, DTA_ScaleY, sz, DTA_Color, shadeToLight(dashade), DTA_TranslationIndex, palid, DTA_ViewportX, windowxy1.x, DTA_ViewportY, windowxy1.y, diff --git a/source/core/gamehud.h b/source/core/gamehud.h index 56033bdd3..0fdfb12d0 100644 --- a/source/core/gamehud.h +++ b/source/core/gamehud.h @@ -5,4 +5,4 @@ extern F2DDrawer twodpsp; void DrawRateStuff(); -void hud_drawsprite(double sx, double sy, int z, double a, int picnum, int dashade, int dapalnum, int dastat, double alpha = 1); +void hud_drawsprite(double sx, double sy, double sz, double a, int picnum, int dashade, int dapalnum, int dastat, double alpha = 1); diff --git a/source/games/blood/src/hudsprites.cpp b/source/games/blood/src/hudsprites.cpp index b35fb8969..bb0f4a311 100644 --- a/source/games/blood/src/hudsprites.cpp +++ b/source/games/blood/src/hudsprites.cpp @@ -127,14 +127,14 @@ void hudDraw(PLAYER *gView, int nSectnum, double bobx, double boby, double zDelt } #ifdef NOONE_EXTENSIONS - if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette, int(smoothratio)); - else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette, int(smoothratio)); + if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette, smoothratio); + else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette, smoothratio); else { gView->sceneQav = gView->weaponQav = -1; gView->weaponTimer = gView->curWeapon = 0; } #else - WeaponDraw(gView, nShade, cX, cY, nPalette, int(smoothratio)); + WeaponDraw(gView, nShade, cX, cY, nPalette, smoothratio); #endif } if (gViewPos == 0 && gView->pXSprite->burnTime > 60) diff --git a/source/games/blood/src/misc.h b/source/games/blood/src/misc.h index 390db1d07..3d2fbd214 100644 --- a/source/games/blood/src/misc.h +++ b/source/games/blood/src/misc.h @@ -46,7 +46,7 @@ struct PLAYER; extern QAV* weaponQAV[]; void WeaponInit(void); -void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5, int smoothratio); +void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5, double smoothratio); void WeaponRaise(PLAYER *pPlayer); void WeaponLower(PLAYER *pPlayer); int WeaponUpgrade(PLAYER *pPlayer, int newWeapon); diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 9c3d48fa9..87efb285e 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -6180,7 +6180,7 @@ void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene) { } } -void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, int smoothratio) { +void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, double smoothratio) { if (pPlayer == NULL || pPlayer->sceneQav == -1) return; QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene; @@ -6189,7 +6189,7 @@ void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, i if (pQavScene->qavResrc != NULL) { QAV* pQAV = pQavScene->qavResrc; - int v4 = (pPlayer->weaponTimer == 0) ? ((PlayClock + MulScale(4, smoothratio, 16)) % pQAV->duration) : pQAV->duration - pPlayer->weaponTimer; + int v4 = (pPlayer->weaponTimer == 0) ? ((PlayClock + MulScale(4, int(smoothratio), 16)) % pQAV->duration) : pQAV->duration - pPlayer->weaponTimer; int flags = 2; int nInv = powerupCheck(pPlayer, kPwUpShadowCloak); if (nInv >= 120 * 8 || (nInv != 0 && (PlayClock & 32))) { @@ -6200,13 +6200,13 @@ void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, i if (!(pSprite->flags & kModernTypeFlag1)) { pQAV->x = int(a3); pQAV->y = int(a4); - pQAV->Draw(a3, a4, v4, flags, a2, a5, true); + pQAV->Draw(a3, a4, v4, flags, a2, a5, true, smoothratio); // draw fullscreen (currently 4:3 only) } else { // What an awful hack. This throws proper ordering out of the window, but there is no way to reproduce this better with strict layering of elements. // From the above commit it seems to be incomplete anyway... - pQAV->Draw(v4, flags, a2, a5, false); + pQAV->Draw(v4, flags, a2, a5, false, smoothratio); } } diff --git a/source/games/blood/src/nnexts.h b/source/games/blood/src/nnexts.h index fae23300b..3c46d063b 100644 --- a/source/games/blood/src/nnexts.h +++ b/source/games/blood/src/nnexts.h @@ -384,7 +384,7 @@ void playerDeactivateShrooms(PLAYER* pPlayer); QAV* playerQavSceneLoad(int qavId); void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene); void playerQavScenePlay(PLAYER* pPlayer); -void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, int smoothratio); +void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, double smoothratio); void playerQavSceneReset(PLAYER* pPlayer); // ------------------------------------------------------------------------- // void callbackUniMissileBurst(int nSprite); diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index 3194b30cd..8d2bf7e63 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -34,18 +34,16 @@ BEGIN_BLD_NS extern void (*qavClientCallback[])(int, void *); -void DrawFrame(double x, double y, TILE_FRAME *pTile, int stat, int shade, int palnum, bool to3dview) +void DrawFrame(double x, double y, double z, double a, TILE_FRAME *pTile, int stat, int shade, int palnum, bool to3dview) { stat |= pTile->stat; - x += pTile->x; - y += pTile->y; if (palnum <= 0) palnum = pTile->palnum; if (!to3dview) { auto tex = tileGetTexture(pTile->picnum); - double scale = pTile->z/65536.; - double angle = pTile->angle * BAngToDegree; + double scale = z * (1. / 65536.); + double angle = a * BAngToDegree; int renderstyle = (stat & RS_NOMASK)? STYLE_Normal : STYLE_Translucent; double alpha = (stat & RS_TRANS1)? glblend[0].def[!!(stat & RS_TRANS2)].alpha : 1.; int pin = (stat & kQavOrientationLeft)? -1 : (stat & RS_ALIGN_R)? 1:0; @@ -70,26 +68,61 @@ void DrawFrame(double x, double y, TILE_FRAME *pTile, int stat, int shade, int p if ((stat & kQavOrientationLeft)) stat |= RS_ALIGN_L; stat &= ~kQavOrientationLeft; - hud_drawsprite(x, y, pTile->z, pTile->angle, pTile->picnum, pTile->shade + shade, palnum, stat); + hud_drawsprite(x, y, z, a, pTile->picnum, pTile->shade + shade, palnum, stat); } } -void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview) +void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio) { assert(ticksPerFrame > 0); + int nFrame = ticks / ticksPerFrame; assert(nFrame >= 0 && nFrame < nFrames); - FRAMEINFO *pFrame = &frames[nFrame]; + FRAMEINFO *thisFrame = &frames[nFrame]; + + if ((nFrame == (nFrames - 1)) && !lastframetic) + { + lastframetic = ticks; + } + else if (lastframetic > ticks) + { + lastframetic = 0; + } + + int oFrame = nFrame == 0 || (lastframetic && ticks > lastframetic) ? nFrame : nFrame - 1; + assert(oFrame >= 0 && oFrame < nFrames); + FRAMEINFO *prevFrame = &frames[oFrame]; + for (int i = 0; i < 8; i++) { - if (pFrame->tiles[i].picnum > 0) - DrawFrame(x, y, &pFrame->tiles[i], stat, shade, palnum, to3dview); - } -} + auto* thisTile = &thisFrame->tiles[i]; + auto* prevTile = &prevFrame->tiles[i]; -void QAV::Draw(int ticks, int stat, int shade, int palnum, bool to3dview) -{ - Draw(x, y, ticks, stat, shade, palnum, to3dview); + if (thisTile->picnum > 0) + { + double tileX = x; + double tileY = y; + double tileZ; + double tileA; + + if ((nFrames > 1) && (nFrame != oFrame) && (thisTile->picnum == prevTile->picnum) && (smoothratio != MaxSmoothRatio)) + { + tileX += interpolatedvaluef(prevTile->x, thisTile->x, smoothratio); + tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio); + tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio); + tileA = interpolatedanglef(prevTile->angle, thisTile->angle, smoothratio); + } + else + { + tileX += thisTile->x; + tileY += thisTile->y; + tileZ = thisTile->z; + tileA = thisTile->angle; + } + + DrawFrame(tileX, tileY, tileZ, tileA, thisTile, stat, shade, palnum, to3dview); + } + } } diff --git a/source/games/blood/src/qav.h b/source/games/blood/src/qav.h index 9c1cdde93..9bea3d3d4 100644 --- a/source/games/blood/src/qav.h +++ b/source/games/blood/src/qav.h @@ -77,10 +77,11 @@ struct QAV int y; // 18 int nSprite; // 1c //SPRITE *pSprite; // 1c - char pad3[4]; // 20 + char pad3[3]; // 20 + char lastframetic; FRAMEINFO frames[1]; // 24 - void Draw(int ticks, int stat, int shade, int palnum, bool in3dscene); - void Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool in3dscene); + void Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536); + void Draw(int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536) { Draw(x, y, ticks, stat, shade, palnum, to3dview, smoothratio); } void Play(int, int, int, void *); void Precache(int palette = 0); }; diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index f6f361db0..51f690220 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -255,7 +255,7 @@ bool isOriginalQAV() return cached; } -void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum, int smoothratio) +void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum, double smoothratio) { assert(pPlayer != NULL); if (pPlayer->weaponQav == -1) @@ -268,7 +268,7 @@ void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum // Double shotgun fix from BloodGDX. if (/*!IsOriginalDemo() &&*/ (pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7))/* && isOriginalQAV()*/) duration = pQAV->duration - 1; - else duration = (PlayClock + MulScale(4, smoothratio, 16)) % pQAV->duration; + else duration = (PlayClock + MulScale(4, int(smoothratio), 16)) % pQAV->duration; } else duration = pQAV->duration - pPlayer->weaponTimer; @@ -281,7 +281,7 @@ void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum shade = -128; flags |= 1; } - pQAV->Draw(xpos, ypos, duration, flags, shade, palnum, true); + pQAV->Draw(xpos, ypos, duration, flags, shade, palnum, true, smoothratio); } void WeaponPlay(PLAYER *pPlayer)