- Blood: Re-time weapon and scene QAV code based on reworked timer and QAV struct code.

This commit is contained in:
Mitchell Richters 2021-08-05 12:38:26 +10:00
parent ab502ebc66
commit 24fbaa527c
10 changed files with 59 additions and 17 deletions

View file

@ -201,6 +201,8 @@ void StartLevel(MapRecord* level, bool newgame)
pPlayer->qavLoop = gPlayerTemp[i].qavLoop; pPlayer->qavLoop = gPlayerTemp[i].qavLoop;
pPlayer->weaponTimer = gPlayerTemp[i].weaponTimer; pPlayer->weaponTimer = gPlayerTemp[i].weaponTimer;
pPlayer->nextWeapon = gPlayerTemp[i].nextWeapon; pPlayer->nextWeapon = gPlayerTemp[i].nextWeapon;
pPlayer->qavLastTick = gPlayerTemp[i].qavLastTick;
pPlayer->qavTimer = gPlayerTemp[i].qavTimer;
} }
} }
PreloadCache(); PreloadCache();

View file

@ -127,14 +127,14 @@ void hudDraw(PLAYER *gView, int nSectnum, double bobx, double boby, double zDelt
} }
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (gView->sceneQav < 0) WeaponDraw(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, smoothratio); else if (gView->pXSprite->health > 0) playerQavSceneDraw(gView, nShade, cX, cY, nPalette);
else { else {
gView->sceneQav = gView->weaponQav = -1; gView->sceneQav = gView->weaponQav = -1;
gView->weaponTimer = gView->curWeapon = 0; gView->qavTimer = gView->weaponTimer = gView->curWeapon = 0;
} }
#else #else
WeaponDraw(gView, nShade, cX, cY, nPalette, smoothratio); WeaponDraw(gView, nShade, cX, cY, nPalette);
#endif #endif
} }
if (gViewPos == 0 && gView->pXSprite->burnTime > 60) if (gViewPos == 0 && gView->pXSprite->burnTime > 60)

View file

@ -46,7 +46,7 @@ struct PLAYER;
extern QAV* weaponQAV[]; extern QAV* weaponQAV[];
void WeaponInit(void); 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 WeaponRaise(PLAYER *pPlayer);
void WeaponLower(PLAYER *pPlayer); void WeaponLower(PLAYER *pPlayer);
int WeaponUpgrade(PLAYER *pPlayer, int newWeapon); int WeaponUpgrade(PLAYER *pPlayer, int newWeapon);

View file

@ -1844,6 +1844,8 @@ void trPlayerCtrlStartScene(XSPRITE* pXSource, PLAYER* pPlayer, bool force) {
pPlayer->weaponTimer = pCtrl->qavScene.qavResrc->duration; pPlayer->weaponTimer = pCtrl->qavScene.qavResrc->duration;
pPlayer->qavCallback = (pXSource->data3 > 0) ? ClipRange(pXSource->data3 - 1, 0, 32) : -1; pPlayer->qavCallback = (pXSource->data3 > 0) ? ClipRange(pXSource->data3 - 1, 0, 32) : -1;
pPlayer->qavLoop = false; 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; if (pPlayer == NULL || pPlayer->sceneQav == -1) return;
QAVSCENE* pQavScene = &gPlayerCtrl[pPlayer->nPlayer].qavScene; 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) { if (pQavScene->qavResrc != NULL) {
QAV* pQAV = pQavScene->qavResrc; 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); int flags = 2; int nInv = powerupCheck(pPlayer, kPwUpShadowCloak);
if (nInv >= 120 * 8 || (nInv != 0 && (PlayClock & 32))) { if (nInv >= 120 * 8 || (nInv != 0 && (PlayClock & 32))) {

View file

@ -384,7 +384,7 @@ void playerDeactivateShrooms(PLAYER* pPlayer);
QAV* playerQavSceneLoad(int qavId); QAV* playerQavSceneLoad(int qavId);
void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene); void playerQavSceneProcess(PLAYER* pPlayer, QAVSCENE* pQavScene);
void playerQavScenePlay(PLAYER* pPlayer); 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 playerQavSceneReset(PLAYER* pPlayer);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
void callbackUniMissileBurst(int nSprite); void callbackUniMissileBurst(int nSprite);

View file

@ -740,6 +740,8 @@ void playerStart(int nPlayer, int bNewLevel)
pPlayer->weaponTimer = 0; pPlayer->weaponTimer = 0;
pPlayer->weaponState = 0; pPlayer->weaponState = 0;
pPlayer->weaponQav = -1; pPlayer->weaponQav = -1;
pPlayer->qavLastTick = 0;
pPlayer->qavTimer = 0;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
playerQavSceneReset(pPlayer); // reset qav scene playerQavSceneReset(pPlayer); // reset qav scene
@ -813,6 +815,8 @@ void playerReset(PLAYER *pPlayer)
pPlayer->weaponState = 0; pPlayer->weaponState = 0;
pPlayer->weaponQav = -1; pPlayer->weaponQav = -1;
pPlayer->qavLoop = 0; pPlayer->qavLoop = 0;
pPlayer->qavLastTick = 0;
pPlayer->qavTimer = 0;
pPlayer->packItemId = -1; pPlayer->packItemId = -1;
for (int i = 0; i < 5; i++) { 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("weaponorder", &w.weaponOrder[0][0], 14*2)
.Array("ammocount", w.ammoCount, countof(w.ammoCount)) .Array("ammocount", w.ammoCount, countof(w.ammoCount))
("qavloop", w.qavLoop) ("qavloop", w.qavLoop)
("qavlastTick", w.qavLastTick)
("qavtimer", w.qavTimer)
("fusetime", w.fuseTime) ("fusetime", w.fuseTime)
("throwtime", w.throwTime) ("throwtime", w.throwTime)
("throwpower", w.throwPower) ("throwpower", w.throwPower)

View file

@ -127,6 +127,8 @@ struct PLAYER
//int at149[14]; //int at149[14];
int ammoCount[12]; int ammoCount[12];
bool qavLoop; bool qavLoop;
int qavLastTick;
int qavTimer;
int fuseTime; int fuseTime;
int throwTime; int throwTime;
int throwPower; int throwPower;

View file

@ -236,6 +236,31 @@ void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick)
*duration = ClipLow(*duration, 0); *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. // 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. // 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.

View file

@ -87,5 +87,6 @@ struct QAV
QAV* getQAV(int res_id); QAV* getQAV(int res_id);
void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick); 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 END_BLD_NS

View file

@ -255,22 +255,16 @@ bool isOriginalQAV()
return cached; 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); assert(pPlayer != NULL);
if (pPlayer->weaponQav == -1) if (pPlayer->weaponQav == -1)
return; return;
QAV * pQAV = weaponQAV[pPlayer->weaponQav]; QAV * pQAV = weaponQAV[pPlayer->weaponQav];
int duration; int duration;
double smoothratio;
if (pPlayer->weaponTimer == 0) // playing idle QAV? qavProcessTimer(pPlayer, pQAV, &duration, &smoothratio, pPlayer->weaponState == -1 || (pPlayer->curWeapon == 3 && pPlayer->weaponState == 7));
{
// 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;
pQAV->x = int(xpos); pQAV->x = int(xpos);
pQAV->y = int(ypos); 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->weaponTimer = weaponQAV[nWeaponQAV]->duration;
pPlayer->qavCallback = callback; pPlayer->qavCallback = callback;
pPlayer->qavLoop = looped; pPlayer->qavLoop = looped;
pPlayer->qavLastTick = I_GetTime(weaponQAV[nWeaponQAV]->ticrate);
pPlayer->qavTimer = weaponQAV[nWeaponQAV]->duration;
//weaponQAV[nWeaponQAV]->Preload(); //weaponQAV[nWeaponQAV]->Preload();
WeaponPlay(pPlayer); WeaponPlay(pPlayer);
pPlayer->weaponTimer -= 4; pPlayer->weaponTimer -= 4;
@ -1913,6 +1909,7 @@ static bool processProxy(PLAYER *pPlayer)
case 9: case 9:
pPlayer->throwPower = ClipHigh(DivScale(PlayClock-pPlayer->throwTime,240, 16), 65536); pPlayer->throwPower = ClipHigh(DivScale(PlayClock-pPlayer->throwTime,240, 16), 65536);
pPlayer->weaponTimer = 0; pPlayer->weaponTimer = 0;
pPlayer->qavTimer = 0;
if (!(pPlayer->input.actions & SB_FIRE)) if (!(pPlayer->input.actions & SB_FIRE))
{ {
pPlayer->weaponState = 8; pPlayer->weaponState = 8;
@ -2043,11 +2040,15 @@ void WeaponProcess(PLAYER *pPlayer) {
if (bShoot && CheckAmmo(pPlayer, pPlayer->weaponAmmo, 1)) if (bShoot && CheckAmmo(pPlayer, pPlayer->weaponAmmo, 1))
{ {
while (pPlayer->weaponTimer <= 0) while (pPlayer->weaponTimer <= 0)
{
pPlayer->weaponTimer += weaponQAV[pPlayer->weaponQav]->duration; pPlayer->weaponTimer += weaponQAV[pPlayer->weaponQav]->duration;
pPlayer->qavTimer += weaponQAV[pPlayer->weaponQav]->duration;
}
} }
else else
{ {
pPlayer->weaponTimer = 0; pPlayer->weaponTimer = 0;
pPlayer->qavTimer = 0;
pPlayer->qavLoop = 0; pPlayer->qavLoop = 0;
} }
return; return;