From 24fbaa527c4a9a06b08dd25388877f7241e781ec Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Thu, 5 Aug 2021 12:38:26 +1000 Subject: [PATCH] - Blood: Re-time weapon and scene QAV code based on reworked timer and QAV struct code. --- source/games/blood/src/blood.cpp | 2 ++ source/games/blood/src/hudsprites.cpp | 8 ++++---- source/games/blood/src/misc.h | 2 +- source/games/blood/src/nnexts.cpp | 9 +++++++-- source/games/blood/src/nnexts.h | 2 +- source/games/blood/src/player.cpp | 6 ++++++ source/games/blood/src/player.h | 2 ++ source/games/blood/src/qav.cpp | 25 +++++++++++++++++++++++++ source/games/blood/src/qav.h | 1 + source/games/blood/src/weapon.cpp | 19 ++++++++++--------- 10 files changed, 59 insertions(+), 17 deletions(-) diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index c53284831..3693ad73f 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -201,6 +201,8 @@ void StartLevel(MapRecord* level, bool newgame) pPlayer->qavLoop = gPlayerTemp[i].qavLoop; pPlayer->weaponTimer = gPlayerTemp[i].weaponTimer; pPlayer->nextWeapon = gPlayerTemp[i].nextWeapon; + pPlayer->qavLastTick = gPlayerTemp[i].qavLastTick; + pPlayer->qavTimer = gPlayerTemp[i].qavTimer; } } PreloadCache(); diff --git a/source/games/blood/src/hudsprites.cpp b/source/games/blood/src/hudsprites.cpp index bb0f4a311..6af4b9dbf 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, smoothratio); - else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette, smoothratio); + if (gView->sceneQav < 0) WeaponDraw(gView, nShade, cX, cY, nPalette); + else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette); else { gView->sceneQav = gView->weaponQav = -1; - gView->weaponTimer = gView->curWeapon = 0; + gView->qavTimer = gView->weaponTimer = gView->curWeapon = 0; } #else - WeaponDraw(gView, nShade, cX, cY, nPalette, smoothratio); + WeaponDraw(gView, nShade, cX, cY, nPalette); #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 3d2fbd214..fcd7b8da1 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, double smoothratio); +void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5); 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 151f46a91..ba6910953 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -1844,6 +1844,8 @@ void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force) { pPlayer->weaponTimer = pCtrl->qavScene.qavResrc->duration; pPlayer->qavCallback = (pXSource->data3 > 0) ? ClipRange(pXSource->data3 - 1, 0, 32) : -1; pPlayer->qavLoop = false; + pPlayer->qavLastTick = I_GetTime(pCtrl->qavScene.qavResrc->ticrate); + pPlayer->qavTimer = pCtrl->qavScene.qavResrc->duration; } @@ -6180,7 +6182,7 @@ void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene) { } } -void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, double smoothratio) { +void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5) { if (pPlayer == NULL || pPlayer->sceneQav == -1) return; QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene; @@ -6189,7 +6191,10 @@ void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5, d if (pQavScene->qavResrc != NULL) { QAV* pQAV = pQavScene->qavResrc; - int v4 = (pPlayer->weaponTimer == 0) ? ((PlayClock + MulScale(4, int(smoothratio), 16)) % pQAV->duration) : pQAV->duration - pPlayer->weaponTimer; + int v4; + double smoothratio; + + qavProcessTimer(pPlayer, pQAV, &v4, &smoothratio); int flags = 2; int nInv = powerupCheck(pPlayer, kPwUpShadowCloak); if (nInv >= 120 * 8 || (nInv != 0 && (PlayClock & 32))) { diff --git a/source/games/blood/src/nnexts.h b/source/games/blood/src/nnexts.h index 3c46d063b..044758c2a 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, double smoothratio); +void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5); void playerQavSceneReset(PLAYER* pPlayer); // ------------------------------------------------------------------------- // void callbackUniMissileBurst(int nSprite); diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index df86d59eb..9cf0895eb 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -740,6 +740,8 @@ void playerStart(int nPlayer, int bNewLevel) pPlayer->weaponTimer = 0; pPlayer->weaponState = 0; pPlayer->weaponQav = -1; + pPlayer->qavLastTick = 0; + pPlayer->qavTimer = 0; #ifdef NOONE_EXTENSIONS playerQavSceneReset(pPlayer); // reset qav scene @@ -813,6 +815,8 @@ void playerReset(PLAYER *pPlayer) pPlayer->weaponState = 0; pPlayer->weaponQav = -1; pPlayer->qavLoop = 0; + pPlayer->qavLastTick = 0; + pPlayer->qavTimer = 0; pPlayer->packItemId = -1; for (int i = 0; i < 5; i++) { @@ -2249,6 +2253,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, PLAYER& w, PLAYER* .Array("weaponorder", &w.weaponOrder[0][0], 14*2) .Array("ammocount", w.ammoCount, countof(w.ammoCount)) ("qavloop", w.qavLoop) + ("qavlastTick", w.qavLastTick) + ("qavtimer", w.qavTimer) ("fusetime", w.fuseTime) ("throwtime", w.throwTime) ("throwpower", w.throwPower) diff --git a/source/games/blood/src/player.h b/source/games/blood/src/player.h index 245042027..1c0cfca62 100644 --- a/source/games/blood/src/player.h +++ b/source/games/blood/src/player.h @@ -127,6 +127,8 @@ struct PLAYER //int at149[14]; int ammoCount[12]; bool qavLoop; + int qavLastTick; + int qavTimer; int fuseTime; int throwTime; int throwPower; diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index 084848be4..5d7adf60f 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -236,6 +236,31 @@ void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick) *duration = ClipLow(*duration, 0); } +void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration) +{ + // Process clock based on QAV's ticrate and last tick value. + qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick); + + if (pPlayer->weaponTimer == 0) + { + // Check if we're playing an idle QAV as per the ticker's weapon timer. + *duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration; + *smoothratio = MaxSmoothRatio; + } + else if (pPlayer->qavTimer == 0) + { + // If qavTimer is 0, play the last frame uninterpolated. Sometimes the timer can be just ahead of weaponTimer. + *duration = pQAV->duration - 1; + *smoothratio = MaxSmoothRatio; + } + else + { + // Apply normal values. + *duration = pQAV->duration - pPlayer->qavTimer; + *smoothratio = I_GetTimeFrac(pQAV->ticrate) * MaxSmoothRatio; + } +} + // This is to eliminate a huge design issue in NBlood that was apparently copied verbatim from the DOS-Version. // Sequences were cached in the resource and directly returned from there in writable form, with byte swapping directly performed in the cache on Big Endian systems. diff --git a/source/games/blood/src/qav.h b/source/games/blood/src/qav.h index e12bce495..0571056d6 100644 --- a/source/games/blood/src/qav.h +++ b/source/games/blood/src/qav.h @@ -87,5 +87,6 @@ struct QAV QAV* getQAV(int res_id); void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick); +void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration = false); END_BLD_NS diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 731c2849c..ea97056c9 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -255,22 +255,16 @@ bool isOriginalQAV() return cached; } -void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum, double smoothratio) +void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum) { assert(pPlayer != NULL); if (pPlayer->weaponQav == -1) return; QAV * pQAV = weaponQAV[pPlayer->weaponQav]; int duration; + double smoothratio; - if (pPlayer->weaponTimer == 0) // playing idle QAV? - { - // 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, int(smoothratio), 16)) % pQAV->duration; - } - else duration = pQAV->duration - pPlayer->weaponTimer; + qavProcessTimer(pPlayer, pQAV, &duration, &smoothratio, pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7)); pQAV->x = int(xpos); pQAV->y = int(ypos); @@ -302,6 +296,8 @@ static void StartQAV(PLAYER *pPlayer, int nWeaponQAV, int callback, bool looped pPlayer->weaponTimer = weaponQAV[nWeaponQAV]->duration; pPlayer->qavCallback = callback; pPlayer->qavLoop = looped; + pPlayer->qavLastTick = I_GetTime(weaponQAV[nWeaponQAV]->ticrate); + pPlayer->qavTimer = weaponQAV[nWeaponQAV]->duration; //weaponQAV[nWeaponQAV]->Preload(); WeaponPlay(pPlayer); pPlayer->weaponTimer -= 4; @@ -1913,6 +1909,7 @@ static bool processProxy(PLAYER *pPlayer) case 9: pPlayer->throwPower = ClipHigh(DivScale(PlayClock-pPlayer->throwTime,240, 16), 65536); pPlayer->weaponTimer = 0; + pPlayer->qavTimer = 0; if (!(pPlayer->input.actions & SB_FIRE)) { pPlayer->weaponState = 8; @@ -2043,11 +2040,15 @@ void WeaponProcess(PLAYER *pPlayer) { if (bShoot && CheckAmmo(pPlayer, pPlayer->weaponAmmo, 1)) { while (pPlayer->weaponTimer <= 0) + { pPlayer->weaponTimer += weaponQAV[pPlayer->weaponQav]->duration; + pPlayer->qavTimer += weaponQAV[pPlayer->weaponQav]->duration; + } } else { pPlayer->weaponTimer = 0; + pPlayer->qavTimer = 0; pPlayer->qavLoop = 0; } return;