From e2498a53a9b8fd298257aad53a9ee958f7af6367 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Aug 2020 19:43:45 +0200 Subject: [PATCH] - split Blood prediction code into its own file. --- source/blood/CMakeLists.txt | 1 + source/blood/src/endgame.cpp | 3 - source/blood/src/prediction.cpp | 730 +++++++++++++++++++++++++++++++ source/blood/src/view.cpp | 744 +------------------------------- source/blood/src/view.h | 51 ++- 5 files changed, 778 insertions(+), 751 deletions(-) create mode 100644 source/blood/src/prediction.cpp diff --git a/source/blood/CMakeLists.txt b/source/blood/CMakeLists.txt index 4bfe3179d..12d20bc3b 100644 --- a/source/blood/CMakeLists.txt +++ b/source/blood/CMakeLists.txt @@ -52,6 +52,7 @@ set( PCH_SOURCES src/nnexts.cpp src/osdcmd.cpp src/player.cpp + src/prediction.cpp src/qav.cpp src/replace.cpp src/sbar.cpp diff --git a/source/blood/src/endgame.cpp b/source/blood/src/endgame.cpp index d7679d99f..da088c9c9 100644 --- a/source/blood/src/endgame.cpp +++ b/source/blood/src/endgame.cpp @@ -97,9 +97,6 @@ CEndGameMgr::CEndGameMgr() void CEndGameMgr::Draw(void) { drawTextScreenBackground(); - int nHeight; - viewGetFontInfo(1, NULL, NULL, &nHeight); - int nY = 20 - nHeight / 2; if (gGameOptions.nGameType == 0) { DrawMenuCaption(GStrings("TXTB_LEVELSTATS")); diff --git a/source/blood/src/prediction.cpp b/source/blood/src/prediction.cpp new file mode 100644 index 000000000..e55f10faf --- /dev/null +++ b/source/blood/src/prediction.cpp @@ -0,0 +1,730 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2010-2019 EDuke32 developers and contributors +Copyright (C) 2019 Nuke.YKT + +This file is part of NBlood. + +NBlood is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- +#include "ns.h" // Must come before everything else! + +#include +#include + +#include "compat.h" +#include "build.h" +#include "pragmas.h" +#include "mmulti.h" +#include "v_font.h" + +#include "endgame.h" +#include "aistate.h" +#include "map2d.h" +#include "loadsave.h" +#include "sectorfx.h" +#include "choke.h" +#include "view.h" +#include "nnexts.h" +#include "zstring.h" +#include "menu.h" +#include "gstrings.h" +#include "v_2ddrawer.h" +#include "v_video.h" +#include "v_font.h" +#include "glbackend/glbackend.h" + +BEGIN_BLD_NS + +void fakePlayerProcess(PLAYER* pPlayer, GINPUT* pInput); +void fakeActProcessSprites(void); + +bool gPrediction = true; +VIEW predict, predictOld; +static VIEW predictFifo[256]; + +void viewInitializePrediction(void) +{ + predict.at30 = gMe->q16ang; + predict.at20 = gMe->q16look; + predict.at24 = gMe->q16horiz; + predict.at28 = gMe->q16slopehoriz; + predict.at2c = gMe->slope; + predict.at6f = gMe->cantJump; + predict.at70 = gMe->isRunning; + predict.at72 = gMe->isUnderwater; + predict.at71 = gMe->input.buttonFlags.jump; + predict.at50 = gMe->pSprite->x; + predict.at54 = gMe->pSprite->y; + predict.at58 = gMe->pSprite->z; + predict.at68 = gMe->pSprite->sectnum; + predict.at73 = gMe->pSprite->flags; + predict.at5c = xvel[gMe->pSprite->index]; + predict.at60 = yvel[gMe->pSprite->index]; + predict.at64 = zvel[gMe->pSprite->index]; + predict.at6a = gMe->pXSprite->height; + predict.at48 = gMe->posture; + predict.at4c = gMe->spin; + predict.at6e = gMe->input.keyFlags.lookCenter; + memcpy(&predict.at75,&gSpriteHit[gMe->pSprite->extra],sizeof(SPRITEHIT)); + predict.at0 = gMe->bobPhase; + predict.at4 = gMe->bobAmp; + predict.at8 = gMe->bobHeight; + predict.atc = gMe->bobWidth; + predict.at10 = gMe->swayPhase; + predict.at14 = gMe->swayAmp; + predict.at18 = gMe->swayHeight; + predict.at1c = gMe->swayWidth; + predict.at34 = gMe->zWeapon-gMe->zView-(12<<8); + predict.at38 = gMe->zView; + predict.at3c = gMe->zViewVel; + predict.at40 = gMe->zWeapon; + predict.at44 = gMe->zWeaponVel; + predictOld = predict; + if (numplayers != 1) + { + gViewAngle = predict.at30; + gViewLook = predict.at20; + } +} + +void viewUpdatePrediction(GINPUT *pInput) +{ + predictOld = predict; + short bakCstat = gMe->pSprite->cstat; + gMe->pSprite->cstat = 0; + fakePlayerProcess(gMe, pInput); + fakeActProcessSprites(); + gMe->pSprite->cstat = bakCstat; + predictFifo[gPredictTail&255] = predict; + gPredictTail++; + if (numplayers != 1) + { + gViewAngle = predict.at30; + gViewLook = predict.at20; + } +} + +static void sub_158B4(PLAYER *pPlayer) +{ + predict.at38 = predict.at58 - pPlayer->pPosture[pPlayer->lifeMode][predict.at48].eyeAboveZ; + predict.at40 = predict.at58 - pPlayer->pPosture[pPlayer->lifeMode][predict.at48].weaponAboveZ; +} + +static void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput) +{ + POSTURE *pPosture = &pPlayer->pPosture[pPlayer->lifeMode][predict.at48]; + + if (numplayers > 1 && gPrediction) + { + gViewAngleAdjust = 0.f; + gViewLookRecenter = false; + gViewLookAdjust = 0.f; + } + + predict.at70 = pInput->syncFlags.run; + predict.at70 = 0; + predict.at71 = pInput->buttonFlags.jump; + if (predict.at48 == 1) + { + int x = Cos(fix16_to_int(predict.at30)); + int y = Sin(fix16_to_int(predict.at30)); + if (pInput->forward) + { + int forward = pInput->forward; + if (forward > 0) + forward = mulscale8(pPosture->frontAccel, forward); + else + forward = mulscale8(pPosture->backAccel, forward); + predict.at5c += mulscale30(forward, x); + predict.at60 += mulscale30(forward, y); + } + if (pInput->strafe) + { + int strafe = pInput->strafe; + strafe = mulscale8(pPosture->sideAccel, strafe); + predict.at5c += mulscale30(strafe, y); + predict.at60 -= mulscale30(strafe, x); + } + } + else if (predict.at6a < 0x100) + { + int speed = 0x10000; + if (predict.at6a > 0) + speed -= divscale16(predict.at6a, 0x100); + int x = Cos(fix16_to_int(predict.at30)); + int y = Sin(fix16_to_int(predict.at30)); + if (pInput->forward) + { + int forward = pInput->forward; + if (forward > 0) + forward = mulscale8(pPosture->frontAccel, forward); + else + forward = mulscale8(pPosture->backAccel, forward); + if (predict.at6a) + forward = mulscale16(forward, speed); + predict.at5c += mulscale30(forward, x); + predict.at60 += mulscale30(forward, y); + } + if (pInput->strafe) + { + int strafe = pInput->strafe; + strafe = mulscale8(pPosture->sideAccel, strafe); + if (predict.at6a) + strafe = mulscale16(strafe, speed); + predict.at5c += mulscale30(strafe, y); + predict.at60 -= mulscale30(strafe, x); + } + } + if (pInput->q16turn) + predict.at30 = (predict.at30+pInput->q16turn)&0x7ffffff; + if (pInput->keyFlags.spin180) + if (!predict.at4c) + predict.at4c = -1024; + if (predict.at4c < 0) + { + int speed; + if (predict.at48 == 1) + speed = 64; + else + speed = 128; + + predict.at4c = min(predict.at4c+speed, 0); + predict.at30 += fix16_from_int(speed); + if (numplayers > 1 && gPrediction) + gViewAngleAdjust += float(speed); + } + + if (!predict.at71) + predict.at6f = 0; + + switch (predict.at48) + { + case 1: + if (predict.at71) + predict.at64 -= pPosture->normalJumpZ;//0x5b05; + if (pInput->buttonFlags.crouch) + predict.at64 += pPosture->normalJumpZ;//0x5b05; + break; + case 2: + if (!pInput->buttonFlags.crouch) + predict.at48 = 0; + break; + default: + if (!predict.at6f && predict.at71 && predict.at6a == 0) { + if (packItemActive(pPlayer, 4)) predict.at64 = pPosture->pwupJumpZ;//-0x175555; + else predict.at64 = pPosture->normalJumpZ;//-0xbaaaa; + predict.at6f = 1; + } + if (pInput->buttonFlags.crouch) + predict.at48 = 2; + break; + } +#if 0 + if (predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown) + { + if (predict.at20 < 0) + predict.at20 = fix16_min(predict.at20+fix16_from_int(4), fix16_from_int(0)); + if (predict.at20 > 0) + predict.at20 = fix16_max(predict.at20-fix16_from_int(4), fix16_from_int(0)); + if (predict.at20 == 0) + predict.at6e = 0; + } + else + { + if (pInput->buttonFlags.lookUp) + predict.at20 = fix16_min(predict.at20+fix16_from_int(4), fix16_from_int(60)); + if (pInput->buttonFlags.lookDown) + predict.at20 = fix16_max(predict.at20-fix16_from_int(4), fix16_from_int(-60)); + } + predict.at20 = fix16_clamp(predict.at20+pInput->q16mlook, fix16_from_int(-60), fix16_from_int(60)); + + if (predict.at20 > 0) + predict.at24 = mulscale30(fix16_from_int(120), Sin(fix16_to_int(predict.at20<<3))); + else if (predict.at20 < 0) + predict.at24 = mulscale30(fix16_from_int(180), Sin(fix16_to_int(predict.at20<<3))); + else + predict.at24 = 0; +#endif + int upAngle = 289; + int downAngle = -347; + double lookStepUp = 4.0*upAngle/60.0; + double lookStepDown = -4.0*downAngle/60.0; + if (predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown) + { + if (predict.at20 < 0) + predict.at20 = fix16_min(predict.at20+fix16_from_dbl(lookStepDown), fix16_from_int(0)); + if (predict.at20 > 0) + predict.at20 = fix16_max(predict.at20-fix16_from_dbl(lookStepUp), fix16_from_int(0)); + if (predict.at20 == 0) + predict.at6e = 0; + } + else + { + if (pInput->buttonFlags.lookUp) + predict.at20 = fix16_min(predict.at20+fix16_from_dbl(lookStepUp), fix16_from_int(upAngle)); + if (pInput->buttonFlags.lookDown) + predict.at20 = fix16_max(predict.at20-fix16_from_dbl(lookStepDown), fix16_from_int(downAngle)); + } + if (numplayers > 1 && gPrediction) + { + if (pInput->buttonFlags.lookUp) + { + gViewLookAdjust += float(lookStepUp); + } + if (pInput->buttonFlags.lookDown) + { + gViewLookAdjust -= float(lookStepDown); + } + gViewLookRecenter = predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown; + } + predict.at20 = fix16_clamp(predict.at20+(pInput->q16mlook<<3), fix16_from_int(downAngle), fix16_from_int(upAngle)); + predict.at24 = fix16_from_float(100.f*tanf(fix16_to_float(predict.at20)*fPI/1024.f)); + + int nSector = predict.at68; + int florhit = predict.at75.florhit & 0xc000; + char va; + if (predict.at6a < 16 && (florhit == 0x4000 || florhit == 0)) + va = 1; + else + va = 0; + if (va && (sector[nSector].floorstat&2) != 0) + { + int z1 = getflorzofslope(nSector, predict.at50, predict.at54); + int x2 = predict.at50+mulscale30(64, Cos(fix16_to_int(predict.at30))); + int y2 = predict.at54+mulscale30(64, Sin(fix16_to_int(predict.at30))); + short nSector2 = nSector; + updatesector(x2, y2, &nSector2); + if (nSector2 == nSector) + { + int z2 = getflorzofslope(nSector2, x2, y2); + predict.at28 = interpolate(predict.at28, fix16_from_int(z1-z2)>>3, 0x4000); + } + } + else + { + predict.at28 = interpolate(predict.at28, 0, 0x4000); + if (klabs(predict.at28) < 4) + predict.at28 = 0; + } + predict.at2c = (-fix16_to_int(predict.at24))<<7; +} + +void fakePlayerProcess(PLAYER *pPlayer, GINPUT *pInput) +{ + spritetype *pSprite = pPlayer->pSprite; + XSPRITE *pXSprite = pPlayer->pXSprite; + POSTURE* pPosture = &pPlayer->pPosture[pPlayer->lifeMode][predict.at48]; + + int top, bottom; + GetSpriteExtents(pSprite, &top, &bottom); + + top += predict.at58-pSprite->z; + bottom += predict.at58-pSprite->z; + + int dzb = (bottom-predict.at58)/4; + int dzt = (predict.at58-top)/4; + + int dw = pSprite->clipdist<<2; + short nSector = predict.at68; + if (!gNoClip) + { + pushmove_old((int32_t*)&predict.at50, (int32_t*)&predict.at54, (int32_t*)&predict.at58, &predict.at68, dw, dzt, dzb, CLIPMASK0); + if (predict.at68 == -1) + predict.at68 = nSector; + } + fakeProcessInput(pPlayer, pInput); + + int nSpeed = approxDist(predict.at5c, predict.at60); + + predict.at3c = interpolate(predict.at3c, predict.at64, 0x7000); + int dz = predict.at58-pPosture->eyeAboveZ-predict.at38; + if (dz > 0) + predict.at3c += mulscale16(dz<<8, 0xa000); + else + predict.at3c += mulscale16(dz<<8, 0x1800); + predict.at38 += predict.at3c>>8; + + predict.at44 = interpolate(predict.at44, predict.at64, 0x5000); + dz = predict.at58-pPosture->weaponAboveZ-predict.at40; + if (dz > 0) + predict.at44 += mulscale16(dz<<8, 0x8000); + else + predict.at44 += mulscale16(dz<<8, 0xc00); + predict.at40 += predict.at44>>8; + + predict.at34 = predict.at40 - predict.at38 - (12<<8); + + predict.at0 = ClipLow(predict.at0-4, 0); + + nSpeed >>= 16; + if (predict.at48 == 1) + { + predict.at4 = (predict.at4+17)&2047; + predict.at14 = (predict.at14+17)&2047; + predict.at8 = mulscale30(10*pPosture->bobV,Sin(predict.at4*2)); + predict.atc = mulscale30(predict.at0*pPosture->bobH,Sin(predict.at4-256)); + predict.at18 = mulscale30(predict.at0*pPosture->swayV,Sin(predict.at14*2)); + predict.at1c = mulscale30(predict.at0*pPosture->swayH,Sin(predict.at14-0x155)); + } + else + { + if (pXSprite->height < 256) + { + predict.at4 = (predict.at4+(pPosture->pace[predict.at70]*4))&2047; + predict.at14 = (predict.at14+(pPosture->pace[predict.at70]*4)/2)&2047; + if (predict.at70) + { + if (predict.at0 < 60) + predict.at0 = ClipHigh(predict.at0 + nSpeed, 60); + } + else + { + if (predict.at0 < 30) + predict.at0 = ClipHigh(predict.at0 + nSpeed, 30); + } + } + predict.at8 = mulscale30(predict.at0*pPosture->bobV,Sin(predict.at4*2)); + predict.atc = mulscale30(predict.at0*pPosture->bobH,Sin(predict.at4-256)); + predict.at18 = mulscale30(predict.at0*pPosture->swayV,Sin(predict.at14*2)); + predict.at1c = mulscale30(predict.at0*pPosture->swayH,Sin(predict.at14-0x155)); + } + if (!pXSprite->health) + return; + predict.at72 = 0; + if (predict.at48 == 1) + { + predict.at72 = 1; + int nSector = predict.at68; + int nLink = gLowerLink[nSector]; + if (nLink > 0 && (sprite[nLink].type == kMarkerLowGoo || sprite[nLink].type == kMarkerLowWater)) + { + if (getceilzofslope(nSector, predict.at50, predict.at54) > predict.at38) + predict.at72 = 0; + } + } +} + +static void fakeMoveDude(spritetype *pSprite) +{ + PLAYER *pPlayer = NULL; + int bottom, top; + if (IsPlayerSprite(pSprite)) + pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; + dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); + GetSpriteExtents(pSprite, &top, &bottom); + top += predict.at58 - pSprite->z; + bottom += predict.at58 - pSprite->z; + int bz = (bottom-predict.at58)/4; + int tz = (predict.at58-top)/4; + int wd = pSprite->clipdist*4; + int nSector = predict.at68; + dassert(nSector >= 0 && nSector < kMaxSectors); + if (predict.at5c || predict.at60) + { + if (pPlayer && gNoClip) + { + predict.at50 += predict.at5c>>12; + predict.at54 += predict.at60>>12; + if (!FindSector(predict.at50, predict.at54, &nSector)) + nSector = predict.at68; + } + else + { + short bakCstat = pSprite->cstat; + pSprite->cstat &= ~257; + predict.at75.hit = ClipMove(&predict.at50, &predict.at54, &predict.at58, &nSector, predict.at5c >> 12, predict.at60 >> 12, wd, tz, bz, CLIPMASK0); + if (nSector == -1) + nSector = predict.at68; + + if (sector[nSector].type >= kSectorPath && sector[nSector].type <= kSectorRotate) + { + short nSector2 = nSector; + pushmove_old((int32_t*)&predict.at50, (int32_t*)&predict.at54, (int32_t*)&predict.at58, &nSector2, wd, tz, bz, CLIPMASK0); + if (nSector2 != -1) + nSector = nSector2; + } + + dassert(nSector >= 0); + + pSprite->cstat = bakCstat; + } + switch (predict.at75.hit&0xc000) + { + case 0x8000: + { + int nHitWall = predict.at75.hit&0x3fff; + walltype *pHitWall = &wall[nHitWall]; + if (pHitWall->nextsector != -1) + { + sectortype *pHitSector = §or[pHitWall->nextsector]; + if (top < pHitSector->ceilingz || bottom > pHitSector->floorz) + { + // ??? + } + } + actWallBounceVector(&predict.at5c, &predict.at60, nHitWall, 0); + break; + } + } + } + if (predict.at68 != nSector) + { + dassert(nSector >= 0 && nSector < kMaxSectors); + predict.at68 = nSector; + } + char bUnderwater = 0; + char bDepth = 0; + int nXSector = sector[nSector].extra; + if (nXSector > 0) + { + XSECTOR *pXSector = &xsector[nXSector]; + if (pXSector->Underwater) + bUnderwater = 1; + if (pXSector->Depth) + bDepth = 1; + } + int nUpperLink = gUpperLink[nSector]; + int nLowerLink = gLowerLink[nSector]; + if (nUpperLink >= 0 && (sprite[nUpperLink].type == kMarkerUpWater || sprite[nUpperLink].type == kMarkerUpGoo)) + bDepth = 1; + if (nLowerLink >= 0 && (sprite[nLowerLink].type == kMarkerLowWater || sprite[nLowerLink].type == kMarkerLowGoo)) + bDepth = 1; + if (pPlayer) + wd += 16; + + if (predict.at64) + predict.at58 += predict.at64 >> 8; + + spritetype pSpriteBak = *pSprite; + spritetype *pTempSprite = pSprite; + pTempSprite->x = predict.at50; + pTempSprite->y = predict.at54; + pTempSprite->z = predict.at58; + pTempSprite->sectnum = predict.at68; + int ceilZ, ceilHit, floorZ, floorHit; + GetZRange(pTempSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0); + GetSpriteExtents(pTempSprite, &top, &bottom); + if (predict.at73 & 2) + { + int vc = 58254; + if (bDepth) + { + if (bUnderwater) + { + int cz = getceilzofslope(nSector, predict.at50, predict.at54); + if (cz > top) + vc += ((bottom-cz)*-80099) / (bottom-top); + else + vc = 0; + } + else + { + int fz = getflorzofslope(nSector, predict.at50, predict.at54); + if (fz < bottom) + vc += ((bottom-fz)*-80099) / (bottom-top); + } + } + else + { + if (bUnderwater) + vc = 0; + else if (bottom >= floorZ) + vc = 0; + } + if (vc) + { + predict.at58 += ((vc*4)/2)>>8; + predict.at64 += vc; + } + } + GetSpriteExtents(pTempSprite, &top, &bottom); + if (bottom >= floorZ) + { + int floorZ2 = floorZ; + int floorHit2 = floorHit; + GetZRange(pTempSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); + if (bottom <= floorZ && predict.at58-floorZ2 < bz) + { + floorZ = floorZ2; + floorHit = floorHit2; + } + } + if (floorZ <= bottom) + { + predict.at75.florhit = floorHit; + predict.at58 += floorZ-bottom; + int var44 = predict.at64-velFloor[predict.at68]; + if (var44 > 0) + { + actFloorBounceVector(&predict.at5c, &predict.at60, &var44, predict.at68, 0); + predict.at64 = var44; + if (klabs(predict.at64) < 0x10000) + { + predict.at64 = velFloor[predict.at68]; + predict.at73 &= ~4; + } + else + predict.at73 |= 4; + } + else if (predict.at64 == 0) + predict.at73 &= ~4; + } + else + { + predict.at75.florhit = 0; + if (predict.at73 & 2) + predict.at73 |= 4; + } + if (top <= ceilZ) + { + predict.at75.ceilhit = ceilHit; + predict.at58 += ClipLow(ceilZ-top, 0); + if (predict.at64 <= 0 && (predict.at73&4)) + predict.at64 = mulscale16(-predict.at64, 0x2000); + } + else + predict.at75.ceilhit = 0; + + GetSpriteExtents(pTempSprite, &top, &bottom); + *pSprite = pSpriteBak; + predict.at6a = ClipLow(floorZ-bottom, 0)>>8; + if (predict.at5c || predict.at60) + { + if ((floorHit & 0xc000) == 0xc000) + { + int nHitSprite = floorHit & 0x3fff; + if ((sprite[nHitSprite].cstat & 0x30) == 0) + { + predict.at5c += mulscale(4, predict.at50 - sprite[nHitSprite].x, 2); + predict.at60 += mulscale(4, predict.at54 - sprite[nHitSprite].y, 2); + return; + } + } + int nXSector = sector[pSprite->sectnum].extra; + if (nXSector > 0 && xsector[nXSector].Underwater) + return; + if (predict.at6a >= 0x100) + return; + int nDrag = gDudeDrag; + if (predict.at6a > 0) + nDrag -= scale(gDudeDrag, predict.at6a, 0x100); + predict.at5c -= mulscale16r(predict.at5c, nDrag); + predict.at60 -= mulscale16r(predict.at60, nDrag); + if (approxDist(predict.at5c, predict.at60) < 0x1000) + predict.at5c = predict.at60 = 0; + } +} + +static void fakeActAirDrag(spritetype *, int num) +{ + int xvec = 0; + int yvec = 0; + int nSector = predict.at68; + dassert(nSector >= 0 && nSector < kMaxSectors); + sectortype *pSector = §or[nSector]; + int nXSector = pSector->extra; + if (nXSector > 0) + { + dassert(nXSector < kMaxXSectors); + XSECTOR *pXSector = &xsector[nXSector]; + if (pXSector->windVel && (pXSector->windAlways || pXSector->busy)) + { + int vel = pXSector->windVel<<12; + if (!pXSector->windAlways && pXSector->busy) + vel = mulscale16(vel, pXSector->busy); + xvec = mulscale30(vel, Cos(pXSector->windAng)); + yvec = mulscale30(vel, Sin(pXSector->windAng)); + } + } + predict.at5c += mulscale16(xvec-predict.at5c, num); + predict.at60 += mulscale16(yvec-predict.at60, num); + predict.at64 -= mulscale16(predict.at64, num); +} + +void fakeActProcessSprites(void) +{ + spritetype *pSprite = gMe->pSprite; + if (pSprite->statnum == kStatDude) + { + int nXSprite = pSprite->extra; + dassert(nXSprite > 0 && nXSprite < kMaxXSprites); + int nSector = predict.at68; + int nXSector = sector[nSector].extra; + XSECTOR *pXSector = NULL; + if (nXSector > 0) + { + dassert(nXSector > 0 && nXSector < kMaxXSectors); + dassert(xsector[nXSector].reference == nSector); + pXSector = &xsector[nXSector]; + } + if (pXSector) + { + int top, bottom; + GetSpriteExtents(pSprite, &top, &bottom); + top += predict.at58 - pSprite->z; + bottom += predict.at58 - pSprite->z; + if (getflorzofslope(nSector, predict.at50, predict.at54) < bottom) + { + int angle = pXSector->panAngle; + int speed = 0; + if (pXSector->panAlways || pXSector->state || pXSector->busy) + { + speed = pXSector->panVel << 9; + if (!pXSector->panAlways && pXSector->busy) + speed = mulscale16(speed, pXSector->busy); + } + if (sector[nSector].floorstat&64) + angle = (GetWallAngle(sector[nSector].wallptr)+512)&2047; + predict.at5c += mulscale30(speed,Cos(angle)); + predict.at60 += mulscale30(speed,Sin(angle)); + } + } + if (pXSector && pXSector->Underwater) + fakeActAirDrag(pSprite, 5376); + else + fakeActAirDrag(pSprite, 128); + + if ((predict.at73 & 4) != 0 || predict.at5c != 0 || predict.at60 != 0 || predict.at64 != 0 || velFloor[predict.at68] != 0 || velCeil[predict.at68] != 0) + { + fakeMoveDude(pSprite); + } + } +} + +void viewCorrectPrediction(void) +{ + if (numplayers == 1) + { + gViewLook = gMe->q16look; + gViewAngle = gMe->q16ang; + return; + } + spritetype *pSprite = gMe->pSprite; + VIEW *pView = &predictFifo[(gNetFifoTail-1)&255]; + if (gMe->q16ang != pView->at30 || pView->at24 != gMe->q16horiz || pView->at50 != pSprite->x || pView->at54 != pSprite->y || pView->at58 != pSprite->z) + { + viewInitializePrediction(); + predictOld = gPrevView[myconnectindex]; + gPredictTail = gNetFifoTail; + while (gPredictTail < gNetFifoHead[myconnectindex]) + { + viewUpdatePrediction(&gFifoInput[gPredictTail&255][myconnectindex]); + } + } +} + +END_BLD_NS diff --git a/source/blood/src/view.cpp b/source/blood/src/view.cpp index c1d423356..8d76617e4 100644 --- a/source/blood/src/view.cpp +++ b/source/blood/src/view.cpp @@ -49,43 +49,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -struct VIEW { - int at0; - int at4; - int at8; // bob height - int atc; // bob width - int at10; - int at14; - int at18; // bob sway y - int at1c; // bob sway x - fix16_t at20; - fix16_t at24; // horiz - int at28; // horizoff - int at2c; - fix16_t at30; // angle - int at34; // weapon z - int at38; // view z - int at3c; - int at40; - int at44; - int at48; // posture - int at4c; // spin - int at50; // x - int at54; // y - int at58; // z - int at5c; //xvel - int at60; //yvel - int at64; //zvel - short at68; // sectnum - unsigned int at6a; // floordist - char at6e; // look center - char at6f; - char at70; // run - char at71; // jump - char at72; // underwater - short at73; // sprite flags - SPRITEHIT at75; -}; VIEW gPrevView[kMaxPlayers]; VIEWPOS gViewPos; @@ -101,12 +64,6 @@ struct INTERPOLATE { int gViewMode = 3; int gViewSize = 2; -bool gPrediction = true; - -VIEW predict, predictOld; - -VIEW predictFifo[256]; - int gInterpolate; int nInterpolations; char gInterpolateSprite[(kMaxSprites+7)>>3]; @@ -188,27 +145,6 @@ void FontSet(int id, int tile, int space) if (ptrs[id]) *ptrs[id] = gFont[id]; } -void viewGetFontInfo(int id, const char *unk1, int *pXSize, int *pYSize) -{ - if (id < 0 || id >= kFontNum) - return; - FFont *pFont = gFont[id]; - if (!unk1) - { - if (pXSize) - *pXSize = pFont->GetCharWidth('N'); - if (pYSize) - *pYSize = pFont->GetHeight(); - } - else - { - if (pXSize) - *pXSize = pFont->StringWidth(unk1); - if (pYSize) - *pYSize = pFont->GetHeight(); - } -} - void viewToggle(int viewMode) { if (viewMode == 3) @@ -220,678 +156,6 @@ void viewToggle(int viewMode) } } -void viewInitializePrediction(void) -{ - predict.at30 = gMe->q16ang; - predict.at20 = gMe->q16look; - predict.at24 = gMe->q16horiz; - predict.at28 = gMe->q16slopehoriz; - predict.at2c = gMe->slope; - predict.at6f = gMe->cantJump; - predict.at70 = gMe->isRunning; - predict.at72 = gMe->isUnderwater; - predict.at71 = gMe->input.buttonFlags.jump; - predict.at50 = gMe->pSprite->x; - predict.at54 = gMe->pSprite->y; - predict.at58 = gMe->pSprite->z; - predict.at68 = gMe->pSprite->sectnum; - predict.at73 = gMe->pSprite->flags; - predict.at5c = xvel[gMe->pSprite->index]; - predict.at60 = yvel[gMe->pSprite->index]; - predict.at64 = zvel[gMe->pSprite->index]; - predict.at6a = gMe->pXSprite->height; - predict.at48 = gMe->posture; - predict.at4c = gMe->spin; - predict.at6e = gMe->input.keyFlags.lookCenter; - memcpy(&predict.at75,&gSpriteHit[gMe->pSprite->extra],sizeof(SPRITEHIT)); - predict.at0 = gMe->bobPhase; - predict.at4 = gMe->bobAmp; - predict.at8 = gMe->bobHeight; - predict.atc = gMe->bobWidth; - predict.at10 = gMe->swayPhase; - predict.at14 = gMe->swayAmp; - predict.at18 = gMe->swayHeight; - predict.at1c = gMe->swayWidth; - predict.at34 = gMe->zWeapon-gMe->zView-(12<<8); - predict.at38 = gMe->zView; - predict.at3c = gMe->zViewVel; - predict.at40 = gMe->zWeapon; - predict.at44 = gMe->zWeaponVel; - predictOld = predict; - if (numplayers != 1) - { - gViewAngle = predict.at30; - gViewLook = predict.at20; - } -} - -void viewUpdatePrediction(GINPUT *pInput) -{ - predictOld = predict; - short bakCstat = gMe->pSprite->cstat; - gMe->pSprite->cstat = 0; - fakePlayerProcess(gMe, pInput); - fakeActProcessSprites(); - gMe->pSprite->cstat = bakCstat; - predictFifo[gPredictTail&255] = predict; - gPredictTail++; - if (numplayers != 1) - { - gViewAngle = predict.at30; - gViewLook = predict.at20; - } -} - -void sub_158B4(PLAYER *pPlayer) -{ - predict.at38 = predict.at58 - pPlayer->pPosture[pPlayer->lifeMode][predict.at48].eyeAboveZ; - predict.at40 = predict.at58 - pPlayer->pPosture[pPlayer->lifeMode][predict.at48].weaponAboveZ; -} - -void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput) -{ - POSTURE *pPosture = &pPlayer->pPosture[pPlayer->lifeMode][predict.at48]; - - if (numplayers > 1 && gPrediction) - { - gViewAngleAdjust = 0.f; - gViewLookRecenter = false; - gViewLookAdjust = 0.f; - } - - predict.at70 = pInput->syncFlags.run; - predict.at70 = 0; - predict.at71 = pInput->buttonFlags.jump; - if (predict.at48 == 1) - { - int x = Cos(fix16_to_int(predict.at30)); - int y = Sin(fix16_to_int(predict.at30)); - if (pInput->forward) - { - int forward = pInput->forward; - if (forward > 0) - forward = mulscale8(pPosture->frontAccel, forward); - else - forward = mulscale8(pPosture->backAccel, forward); - predict.at5c += mulscale30(forward, x); - predict.at60 += mulscale30(forward, y); - } - if (pInput->strafe) - { - int strafe = pInput->strafe; - strafe = mulscale8(pPosture->sideAccel, strafe); - predict.at5c += mulscale30(strafe, y); - predict.at60 -= mulscale30(strafe, x); - } - } - else if (predict.at6a < 0x100) - { - int speed = 0x10000; - if (predict.at6a > 0) - speed -= divscale16(predict.at6a, 0x100); - int x = Cos(fix16_to_int(predict.at30)); - int y = Sin(fix16_to_int(predict.at30)); - if (pInput->forward) - { - int forward = pInput->forward; - if (forward > 0) - forward = mulscale8(pPosture->frontAccel, forward); - else - forward = mulscale8(pPosture->backAccel, forward); - if (predict.at6a) - forward = mulscale16(forward, speed); - predict.at5c += mulscale30(forward, x); - predict.at60 += mulscale30(forward, y); - } - if (pInput->strafe) - { - int strafe = pInput->strafe; - strafe = mulscale8(pPosture->sideAccel, strafe); - if (predict.at6a) - strafe = mulscale16(strafe, speed); - predict.at5c += mulscale30(strafe, y); - predict.at60 -= mulscale30(strafe, x); - } - } - if (pInput->q16turn) - predict.at30 = (predict.at30+pInput->q16turn)&0x7ffffff; - if (pInput->keyFlags.spin180) - if (!predict.at4c) - predict.at4c = -1024; - if (predict.at4c < 0) - { - int speed; - if (predict.at48 == 1) - speed = 64; - else - speed = 128; - - predict.at4c = min(predict.at4c+speed, 0); - predict.at30 += fix16_from_int(speed); - if (numplayers > 1 && gPrediction) - gViewAngleAdjust += float(speed); - } - - if (!predict.at71) - predict.at6f = 0; - - switch (predict.at48) - { - case 1: - if (predict.at71) - predict.at64 -= pPosture->normalJumpZ;//0x5b05; - if (pInput->buttonFlags.crouch) - predict.at64 += pPosture->normalJumpZ;//0x5b05; - break; - case 2: - if (!pInput->buttonFlags.crouch) - predict.at48 = 0; - break; - default: - if (!predict.at6f && predict.at71 && predict.at6a == 0) { - if (packItemActive(pPlayer, 4)) predict.at64 = pPosture->pwupJumpZ;//-0x175555; - else predict.at64 = pPosture->normalJumpZ;//-0xbaaaa; - predict.at6f = 1; - } - if (pInput->buttonFlags.crouch) - predict.at48 = 2; - break; - } -#if 0 - if (predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown) - { - if (predict.at20 < 0) - predict.at20 = fix16_min(predict.at20+fix16_from_int(4), fix16_from_int(0)); - if (predict.at20 > 0) - predict.at20 = fix16_max(predict.at20-fix16_from_int(4), fix16_from_int(0)); - if (predict.at20 == 0) - predict.at6e = 0; - } - else - { - if (pInput->buttonFlags.lookUp) - predict.at20 = fix16_min(predict.at20+fix16_from_int(4), fix16_from_int(60)); - if (pInput->buttonFlags.lookDown) - predict.at20 = fix16_max(predict.at20-fix16_from_int(4), fix16_from_int(-60)); - } - predict.at20 = fix16_clamp(predict.at20+pInput->q16mlook, fix16_from_int(-60), fix16_from_int(60)); - - if (predict.at20 > 0) - predict.at24 = mulscale30(fix16_from_int(120), Sin(fix16_to_int(predict.at20<<3))); - else if (predict.at20 < 0) - predict.at24 = mulscale30(fix16_from_int(180), Sin(fix16_to_int(predict.at20<<3))); - else - predict.at24 = 0; -#endif - int upAngle = 289; - int downAngle = -347; - double lookStepUp = 4.0*upAngle/60.0; - double lookStepDown = -4.0*downAngle/60.0; - if (predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown) - { - if (predict.at20 < 0) - predict.at20 = fix16_min(predict.at20+fix16_from_dbl(lookStepDown), fix16_from_int(0)); - if (predict.at20 > 0) - predict.at20 = fix16_max(predict.at20-fix16_from_dbl(lookStepUp), fix16_from_int(0)); - if (predict.at20 == 0) - predict.at6e = 0; - } - else - { - if (pInput->buttonFlags.lookUp) - predict.at20 = fix16_min(predict.at20+fix16_from_dbl(lookStepUp), fix16_from_int(upAngle)); - if (pInput->buttonFlags.lookDown) - predict.at20 = fix16_max(predict.at20-fix16_from_dbl(lookStepDown), fix16_from_int(downAngle)); - } - if (numplayers > 1 && gPrediction) - { - if (pInput->buttonFlags.lookUp) - { - gViewLookAdjust += float(lookStepUp); - } - if (pInput->buttonFlags.lookDown) - { - gViewLookAdjust -= float(lookStepDown); - } - gViewLookRecenter = predict.at6e && !pInput->buttonFlags.lookUp && !pInput->buttonFlags.lookDown; - } - predict.at20 = fix16_clamp(predict.at20+(pInput->q16mlook<<3), fix16_from_int(downAngle), fix16_from_int(upAngle)); - predict.at24 = fix16_from_float(100.f*tanf(fix16_to_float(predict.at20)*fPI/1024.f)); - - int nSector = predict.at68; - int florhit = predict.at75.florhit & 0xc000; - char va; - if (predict.at6a < 16 && (florhit == 0x4000 || florhit == 0)) - va = 1; - else - va = 0; - if (va && (sector[nSector].floorstat&2) != 0) - { - int z1 = getflorzofslope(nSector, predict.at50, predict.at54); - int x2 = predict.at50+mulscale30(64, Cos(fix16_to_int(predict.at30))); - int y2 = predict.at54+mulscale30(64, Sin(fix16_to_int(predict.at30))); - short nSector2 = nSector; - updatesector(x2, y2, &nSector2); - if (nSector2 == nSector) - { - int z2 = getflorzofslope(nSector2, x2, y2); - predict.at28 = interpolate(predict.at28, fix16_from_int(z1-z2)>>3, 0x4000); - } - } - else - { - predict.at28 = interpolate(predict.at28, 0, 0x4000); - if (klabs(predict.at28) < 4) - predict.at28 = 0; - } - predict.at2c = (-fix16_to_int(predict.at24))<<7; -} - -void fakePlayerProcess(PLAYER *pPlayer, GINPUT *pInput) -{ - spritetype *pSprite = pPlayer->pSprite; - XSPRITE *pXSprite = pPlayer->pXSprite; - POSTURE* pPosture = &pPlayer->pPosture[pPlayer->lifeMode][predict.at48]; - - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - - top += predict.at58-pSprite->z; - bottom += predict.at58-pSprite->z; - - int dzb = (bottom-predict.at58)/4; - int dzt = (predict.at58-top)/4; - - int dw = pSprite->clipdist<<2; - short nSector = predict.at68; - if (!gNoClip) - { - pushmove_old((int32_t*)&predict.at50, (int32_t*)&predict.at54, (int32_t*)&predict.at58, &predict.at68, dw, dzt, dzb, CLIPMASK0); - if (predict.at68 == -1) - predict.at68 = nSector; - } - fakeProcessInput(pPlayer, pInput); - - int nSpeed = approxDist(predict.at5c, predict.at60); - - predict.at3c = interpolate(predict.at3c, predict.at64, 0x7000); - int dz = predict.at58-pPosture->eyeAboveZ-predict.at38; - if (dz > 0) - predict.at3c += mulscale16(dz<<8, 0xa000); - else - predict.at3c += mulscale16(dz<<8, 0x1800); - predict.at38 += predict.at3c>>8; - - predict.at44 = interpolate(predict.at44, predict.at64, 0x5000); - dz = predict.at58-pPosture->weaponAboveZ-predict.at40; - if (dz > 0) - predict.at44 += mulscale16(dz<<8, 0x8000); - else - predict.at44 += mulscale16(dz<<8, 0xc00); - predict.at40 += predict.at44>>8; - - predict.at34 = predict.at40 - predict.at38 - (12<<8); - - predict.at0 = ClipLow(predict.at0-4, 0); - - nSpeed >>= 16; - if (predict.at48 == 1) - { - predict.at4 = (predict.at4+17)&2047; - predict.at14 = (predict.at14+17)&2047; - predict.at8 = mulscale30(10*pPosture->bobV,Sin(predict.at4*2)); - predict.atc = mulscale30(predict.at0*pPosture->bobH,Sin(predict.at4-256)); - predict.at18 = mulscale30(predict.at0*pPosture->swayV,Sin(predict.at14*2)); - predict.at1c = mulscale30(predict.at0*pPosture->swayH,Sin(predict.at14-0x155)); - } - else - { - if (pXSprite->height < 256) - { - predict.at4 = (predict.at4+(pPosture->pace[predict.at70]*4))&2047; - predict.at14 = (predict.at14+(pPosture->pace[predict.at70]*4)/2)&2047; - if (predict.at70) - { - if (predict.at0 < 60) - predict.at0 = ClipHigh(predict.at0 + nSpeed, 60); - } - else - { - if (predict.at0 < 30) - predict.at0 = ClipHigh(predict.at0 + nSpeed, 30); - } - } - predict.at8 = mulscale30(predict.at0*pPosture->bobV,Sin(predict.at4*2)); - predict.atc = mulscale30(predict.at0*pPosture->bobH,Sin(predict.at4-256)); - predict.at18 = mulscale30(predict.at0*pPosture->swayV,Sin(predict.at14*2)); - predict.at1c = mulscale30(predict.at0*pPosture->swayH,Sin(predict.at14-0x155)); - } - if (!pXSprite->health) - return; - predict.at72 = 0; - if (predict.at48 == 1) - { - predict.at72 = 1; - int nSector = predict.at68; - int nLink = gLowerLink[nSector]; - if (nLink > 0 && (sprite[nLink].type == kMarkerLowGoo || sprite[nLink].type == kMarkerLowWater)) - { - if (getceilzofslope(nSector, predict.at50, predict.at54) > predict.at38) - predict.at72 = 0; - } - } -} - -void fakeMoveDude(spritetype *pSprite) -{ - PLAYER *pPlayer = NULL; - int bottom, top; - if (IsPlayerSprite(pSprite)) - pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; - dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - GetSpriteExtents(pSprite, &top, &bottom); - top += predict.at58 - pSprite->z; - bottom += predict.at58 - pSprite->z; - int bz = (bottom-predict.at58)/4; - int tz = (predict.at58-top)/4; - int wd = pSprite->clipdist*4; - int nSector = predict.at68; - dassert(nSector >= 0 && nSector < kMaxSectors); - if (predict.at5c || predict.at60) - { - if (pPlayer && gNoClip) - { - predict.at50 += predict.at5c>>12; - predict.at54 += predict.at60>>12; - if (!FindSector(predict.at50, predict.at54, &nSector)) - nSector = predict.at68; - } - else - { - short bakCstat = pSprite->cstat; - pSprite->cstat &= ~257; - predict.at75.hit = ClipMove(&predict.at50, &predict.at54, &predict.at58, &nSector, predict.at5c >> 12, predict.at60 >> 12, wd, tz, bz, CLIPMASK0); - if (nSector == -1) - nSector = predict.at68; - - if (sector[nSector].type >= kSectorPath && sector[nSector].type <= kSectorRotate) - { - short nSector2 = nSector; - pushmove_old((int32_t*)&predict.at50, (int32_t*)&predict.at54, (int32_t*)&predict.at58, &nSector2, wd, tz, bz, CLIPMASK0); - if (nSector2 != -1) - nSector = nSector2; - } - - dassert(nSector >= 0); - - pSprite->cstat = bakCstat; - } - switch (predict.at75.hit&0xc000) - { - case 0x8000: - { - int nHitWall = predict.at75.hit&0x3fff; - walltype *pHitWall = &wall[nHitWall]; - if (pHitWall->nextsector != -1) - { - sectortype *pHitSector = §or[pHitWall->nextsector]; - if (top < pHitSector->ceilingz || bottom > pHitSector->floorz) - { - // ??? - } - } - actWallBounceVector(&predict.at5c, &predict.at60, nHitWall, 0); - break; - } - } - } - if (predict.at68 != nSector) - { - dassert(nSector >= 0 && nSector < kMaxSectors); - predict.at68 = nSector; - } - char bUnderwater = 0; - char bDepth = 0; - int nXSector = sector[nSector].extra; - if (nXSector > 0) - { - XSECTOR *pXSector = &xsector[nXSector]; - if (pXSector->Underwater) - bUnderwater = 1; - if (pXSector->Depth) - bDepth = 1; - } - int nUpperLink = gUpperLink[nSector]; - int nLowerLink = gLowerLink[nSector]; - if (nUpperLink >= 0 && (sprite[nUpperLink].type == kMarkerUpWater || sprite[nUpperLink].type == kMarkerUpGoo)) - bDepth = 1; - if (nLowerLink >= 0 && (sprite[nLowerLink].type == kMarkerLowWater || sprite[nLowerLink].type == kMarkerLowGoo)) - bDepth = 1; - if (pPlayer) - wd += 16; - - if (predict.at64) - predict.at58 += predict.at64 >> 8; - - spritetype pSpriteBak = *pSprite; - spritetype *pTempSprite = pSprite; - pTempSprite->x = predict.at50; - pTempSprite->y = predict.at54; - pTempSprite->z = predict.at58; - pTempSprite->sectnum = predict.at68; - int ceilZ, ceilHit, floorZ, floorHit; - GetZRange(pTempSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0); - GetSpriteExtents(pTempSprite, &top, &bottom); - if (predict.at73 & 2) - { - int vc = 58254; - if (bDepth) - { - if (bUnderwater) - { - int cz = getceilzofslope(nSector, predict.at50, predict.at54); - if (cz > top) - vc += ((bottom-cz)*-80099) / (bottom-top); - else - vc = 0; - } - else - { - int fz = getflorzofslope(nSector, predict.at50, predict.at54); - if (fz < bottom) - vc += ((bottom-fz)*-80099) / (bottom-top); - } - } - else - { - if (bUnderwater) - vc = 0; - else if (bottom >= floorZ) - vc = 0; - } - if (vc) - { - predict.at58 += ((vc*4)/2)>>8; - predict.at64 += vc; - } - } - GetSpriteExtents(pTempSprite, &top, &bottom); - if (bottom >= floorZ) - { - int floorZ2 = floorZ; - int floorHit2 = floorHit; - GetZRange(pTempSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); - if (bottom <= floorZ && predict.at58-floorZ2 < bz) - { - floorZ = floorZ2; - floorHit = floorHit2; - } - } - if (floorZ <= bottom) - { - predict.at75.florhit = floorHit; - predict.at58 += floorZ-bottom; - int var44 = predict.at64-velFloor[predict.at68]; - if (var44 > 0) - { - actFloorBounceVector(&predict.at5c, &predict.at60, &var44, predict.at68, 0); - predict.at64 = var44; - if (klabs(predict.at64) < 0x10000) - { - predict.at64 = velFloor[predict.at68]; - predict.at73 &= ~4; - } - else - predict.at73 |= 4; - } - else if (predict.at64 == 0) - predict.at73 &= ~4; - } - else - { - predict.at75.florhit = 0; - if (predict.at73 & 2) - predict.at73 |= 4; - } - if (top <= ceilZ) - { - predict.at75.ceilhit = ceilHit; - predict.at58 += ClipLow(ceilZ-top, 0); - if (predict.at64 <= 0 && (predict.at73&4)) - predict.at64 = mulscale16(-predict.at64, 0x2000); - } - else - predict.at75.ceilhit = 0; - - GetSpriteExtents(pTempSprite, &top, &bottom); - *pSprite = pSpriteBak; - predict.at6a = ClipLow(floorZ-bottom, 0)>>8; - if (predict.at5c || predict.at60) - { - if ((floorHit & 0xc000) == 0xc000) - { - int nHitSprite = floorHit & 0x3fff; - if ((sprite[nHitSprite].cstat & 0x30) == 0) - { - predict.at5c += mulscale(4, predict.at50 - sprite[nHitSprite].x, 2); - predict.at60 += mulscale(4, predict.at54 - sprite[nHitSprite].y, 2); - return; - } - } - int nXSector = sector[pSprite->sectnum].extra; - if (nXSector > 0 && xsector[nXSector].Underwater) - return; - if (predict.at6a >= 0x100) - return; - int nDrag = gDudeDrag; - if (predict.at6a > 0) - nDrag -= scale(gDudeDrag, predict.at6a, 0x100); - predict.at5c -= mulscale16r(predict.at5c, nDrag); - predict.at60 -= mulscale16r(predict.at60, nDrag); - if (approxDist(predict.at5c, predict.at60) < 0x1000) - predict.at5c = predict.at60 = 0; - } -} - -void fakeActAirDrag(spritetype *pSprite, int num) -{ - UNREFERENCED_PARAMETER(pSprite); - int xvec = 0; - int yvec = 0; - int nSector = predict.at68; - dassert(nSector >= 0 && nSector < kMaxSectors); - sectortype *pSector = §or[nSector]; - int nXSector = pSector->extra; - if (nXSector > 0) - { - dassert(nXSector < kMaxXSectors); - XSECTOR *pXSector = &xsector[nXSector]; - if (pXSector->windVel && (pXSector->windAlways || pXSector->busy)) - { - int vel = pXSector->windVel<<12; - if (!pXSector->windAlways && pXSector->busy) - vel = mulscale16(vel, pXSector->busy); - xvec = mulscale30(vel, Cos(pXSector->windAng)); - yvec = mulscale30(vel, Sin(pXSector->windAng)); - } - } - predict.at5c += mulscale16(xvec-predict.at5c, num); - predict.at60 += mulscale16(yvec-predict.at60, num); - predict.at64 -= mulscale16(predict.at64, num); -} - -void fakeActProcessSprites(void) -{ - spritetype *pSprite = gMe->pSprite; - if (pSprite->statnum == kStatDude) - { - int nXSprite = pSprite->extra; - dassert(nXSprite > 0 && nXSprite < kMaxXSprites); - int nSector = predict.at68; - int nXSector = sector[nSector].extra; - XSECTOR *pXSector = NULL; - if (nXSector > 0) - { - dassert(nXSector > 0 && nXSector < kMaxXSectors); - dassert(xsector[nXSector].reference == nSector); - pXSector = &xsector[nXSector]; - } - if (pXSector) - { - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - top += predict.at58 - pSprite->z; - bottom += predict.at58 - pSprite->z; - if (getflorzofslope(nSector, predict.at50, predict.at54) < bottom) - { - int angle = pXSector->panAngle; - int speed = 0; - if (pXSector->panAlways || pXSector->state || pXSector->busy) - { - speed = pXSector->panVel << 9; - if (!pXSector->panAlways && pXSector->busy) - speed = mulscale16(speed, pXSector->busy); - } - if (sector[nSector].floorstat&64) - angle = (GetWallAngle(sector[nSector].wallptr)+512)&2047; - predict.at5c += mulscale30(speed,Cos(angle)); - predict.at60 += mulscale30(speed,Sin(angle)); - } - } - if (pXSector && pXSector->Underwater) - fakeActAirDrag(pSprite, 5376); - else - fakeActAirDrag(pSprite, 128); - - if ((predict.at73 & 4) != 0 || predict.at5c != 0 || predict.at60 != 0 || predict.at64 != 0 || velFloor[predict.at68] != 0 || velCeil[predict.at68] != 0) - { - fakeMoveDude(pSprite); - } - } -} - -void viewCorrectPrediction(void) -{ - if (numplayers == 1) - { - gViewLook = gMe->q16look; - gViewAngle = gMe->q16ang; - return; - } - spritetype *pSprite = gMe->pSprite; - VIEW *pView = &predictFifo[(gNetFifoTail-1)&255]; - if (gMe->q16ang != pView->at30 || pView->at24 != gMe->q16horiz || pView->at50 != pSprite->x || pView->at54 != pSprite->y || pView->at58 != pSprite->z) - { - viewInitializePrediction(); - predictOld = gPrevView[myconnectindex]; - gPredictTail = gNetFifoTail; - while (gPredictTail < gNetFifoHead[myconnectindex]) - { - viewUpdatePrediction(&gFifoInput[gPredictTail&255][myconnectindex]); - } - } -} - void viewBackupView(int nPlayer) { PLAYER *pPlayer = &gPlayer[nPlayer]; @@ -1003,7 +267,7 @@ void viewDrawText(int nFont, const char *pString, int x, int y, int nShade, int DrawText(twod, pFont, CR_UNDEFINED, x+1, y+1, pString, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_Color, 0xff000000, DTA_Alpha, 0.5, TAG_DONE); } DrawText(twod, pFont, CR_UNDEFINED, x, y, pString, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_TranslationIndex, TRANSLATION(Translation_Remap, nPalette), - DTA_Color, shadeToLight(nShade), TAG_DONE); + DTA_Color, shadeToLight(nShade), DTA_Alpha, alpha / 255., TAG_DONE); } @@ -1021,13 +285,13 @@ void viewDrawMapTitle(void) if (!hud_showmapname || M_Active()) return; - int const fadeStartTic = int((videoGetRenderMode() == REND_CLASSIC ? 1.25f : 1.f)*kTicsPerSec); + int const fadeStartTic = kTicsPerSec; int const fadeEndTic = int(1.5f*kTicsPerSec); if (gLevelTime > fadeEndTic) return; - uint8_t const alpha = clamp((gLevelTime-fadeStartTic)*255/(fadeEndTic-fadeStartTic), 0, 255); + int const alpha = 255 - clamp((gLevelTime-fadeStartTic)*255/(fadeEndTic-fadeStartTic), 0, 255); - if (alpha != 255) + if (alpha != 0) { viewDrawText(1, levelGetTitle(), 160, 50, -128, 0, 1, 1, 0, alpha); } diff --git a/source/blood/src/view.h b/source/blood/src/view.h index 7c6972f7a..4a2721f98 100644 --- a/source/blood/src/view.h +++ b/source/blood/src/view.h @@ -31,6 +31,49 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +struct VIEW { + int at0; + int at4; + int at8; // bob height + int atc; // bob width + int at10; + int at14; + int at18; // bob sway y + int at1c; // bob sway x + fix16_t at20; + fix16_t at24; // horiz + int at28; // horizoff + int at2c; + fix16_t at30; // angle + int at34; // weapon z + int at38; // view z + int at3c; + int at40; + int at44; + int at48; // posture + int at4c; // spin + int at50; // x + int at54; // y + int at58; // z + int at5c; //xvel + int at60; //yvel + int at64; //zvel + short at68; // sectnum + unsigned int at6a; // floordist + char at6e; // look center + char at6f; + char at70; // run + char at71; // jump + char at72; // underwater + short at73; // sprite flags + SPRITEHIT at75; +}; + +extern VIEW gPrevView[kMaxPlayers]; + +extern VIEW predict, predictOld; +extern bool gPrediction; + enum VIEW_EFFECT { VIEW_EFFECT_0 = 0, VIEW_EFFECT_1, @@ -104,16 +147,9 @@ extern int gViewX0S, gViewY0S, gViewX1S, gViewY1S; extern int gLastPal; void hudDraw(PLAYER* gView, int nSectnum, int defaultHoriz, int bobx, int boby, int zDelta, int basepal); -void viewGetFontInfo(int id, const char *unk1, int *pXSize, int *pYSize); void viewToggle(int viewMode); void viewInitializePrediction(void); void viewUpdatePrediction(GINPUT *pInput); -void sub_158B4(PLAYER *pPlayer); -void fakeProcessInput(PLAYER *pPlayer, GINPUT *pInput); -void fakePlayerProcess(PLAYER *pPlayer, GINPUT *pInput); -void fakeMoveDude(spritetype *pSprite); -void fakeActAirDrag(spritetype *pSprite, int num); -void fakeActProcessSprites(void); void viewCorrectPrediction(void); void viewBackupView(int nPlayer); void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos); @@ -122,7 +158,6 @@ void viewAddInterpolation(void *data, INTERPOLATE_TYPE type); void CalcInterpolations(void); void RestoreInterpolations(void); void viewDrawText(int nFont, const char *pString, int x, int y, int nShade, int nPalette, int position, char shadow, unsigned int nStat = 0, uint8_t alpha = 0); -void viewTileSprite(int nTile, int nShade, int nPalette, int x1, int y1, int x2, int y2); void InitStatusBar(void); void UpdateStatusBar(ClockTicks arg); void viewInit(void);