From ea9c88d9529f45451c3a905c8a9c1bf4eaf1a567 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 30 Aug 2022 19:08:16 +0200 Subject: [PATCH] =?UTF-8?q?-=20floatified=20Blood=E2=80=99s=20MoveMissile?= =?UTF-8?q?=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/games/blood/src/actor.cpp | 43 +++++++++++++---------------- source/games/blood/src/bloodactor.h | 5 ++++ source/games/blood/src/gameutil.h | 15 ++++++++++ 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 945491fd3..942076cf0 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5241,17 +5241,15 @@ int MoveMissile(DBloodActor* actor) actor->vel.Z += deltaz; } } - int vx = actor->vel.X >> 12; - int vy = actor->vel.Y >> 12; - int vz = actor->vel.Z >> 8; - int top, bottom; + auto vel = actor->fVel(); + double top, bottom; GetActorExtents(actor, &top, &bottom); int i = 1; const int bakCompat = enginecompatibility_mode; const bool isFlameSprite = (actor->spr.type == kMissileFlameSpray || actor->spr.type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) while (1) { - vec3_t pos = actor->int_pos(); + auto ppos = actor->spr.pos; auto pSector2 = actor->sector(); const auto bakSpriteCstat = actor->spr.cstat; if (Owner && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) @@ -5260,7 +5258,7 @@ int MoveMissile(DBloodActor* actor) actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; // remove self collisions for accurate clipmove } Collision clipmoveresult; - ClipMove(pos, &pSector2, vx, vy, actor->spr.clipdist << 2, (pos.Z - top) / 4, (bottom - pos.Z) / 4, CLIPMASK0, clipmoveresult, 1); + ClipMove(ppos, &pSector2, vel.XY(), actor->spr.clipdist << 2, (ppos.Z - top) / 4, (bottom - ppos.Z) / 4, CLIPMASK0, clipmoveresult, 1); enginecompatibility_mode = bakCompat; // restore actor->spr.cstat = bakSpriteCstat; auto pSector = pSector2; @@ -5280,9 +5278,9 @@ int MoveMissile(DBloodActor* actor) if (!gHitInfo.hitWall->twoSided()) cliptype = 0; else { - int32_t fz, cz; - getzsofslopeptr(clipmoveresult.hitWall->nextSector(), pos.X, pos.Y, &cz, &fz); - if (pos.Z <= cz || pos.Z >= fz) cliptype = 0; + double fz, cz; + getzsofslopeptr(clipmoveresult.hitWall->nextSector(), ppos, &cz, &fz); + if (ppos.Z <= cz || ppos.Z >= fz) cliptype = 0; else cliptype = 4; } } @@ -5308,35 +5306,32 @@ int MoveMissile(DBloodActor* actor) } if (cliptype >= 0 && cliptype != 3) { - int nAngle = getangle(actor->vel.X, actor->vel.Y); - pos.X -= MulScale(Cos(nAngle), 16, 30); - pos.Y -= MulScale(Sin(nAngle), 16, 30); - int nVel = approxDist(actor->vel.X, actor->vel.Y); - vz -= Scale(0x100, actor->vel.Z, nVel); - updatesector(pos.X, pos.Y, &pSector); + double nVel = actor->fVel().XY().Length(); + ppos.XY() -= actor->fVel().XY() / nVel; + vel.Z -= actor->fVel().Z / nVel; + updatesector(ppos, &pSector); pSector2 = pSector; } - int ceilZ, floorZ; + double ceilZ, floorZ; Collision ceilColl, floorColl; - GetZRangeAtXYZ(pos.X, pos.Y, pos.Z, pSector2, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist << 2, CLIPMASK0); + GetZRangeAtXYZ(ppos, pSector2, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist << 2, CLIPMASK0); GetActorExtents(actor, &top, &bottom); - top += vz; - bottom += vz; + top += vel.Z; + bottom += vel.Z; if (bottom >= floorZ) { actor->hit.florhit = floorColl; - vz += floorZ - bottom; + vel.Z += floorZ - bottom; cliptype = 2; } if (top <= ceilZ) { actor->hit.ceilhit = ceilColl; - vz += ClipLow(ceilZ - top, 0); + vel.Z += std::max(ceilZ - top, 0.); cliptype = 1; } - actor->set_int_pos( pos); - actor->add_int_z(vz); - updatesector(pos.X, pos.Y, &pSector); + actor->spr.pos = ppos.plusZ(vel.Z); + updatesector(ppos, &pSector); if (pSector != nullptr && pSector != actor->sector()) { assert(pSector); diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 7b58ef680..90f454221 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -42,6 +42,11 @@ public: bool hasX() { return hasx; } void addX() { hasx = true; } + + DVector3 fVel() const + { + return { FixedToFloat(vel.X), FixedToFloat(vel.Y), FixedToFloat(vel.Z) }; + } void SetOwner(DBloodActor* own) { diff --git a/source/games/blood/src/gameutil.h b/source/games/blood/src/gameutil.h index 891e5d51c..77f76b3e9 100644 --- a/source/games/blood/src/gameutil.h +++ b/source/games/blood/src/gameutil.h @@ -45,6 +45,14 @@ inline int HitScan(DBloodActor* pSprite, double z, int dx, int dy, int dz, unsig int VectorScan(DBloodActor* pSprite, int nOffset, int nZOffset, int dx, int dy, int dz, int nRange, int ac); void GetZRange(DBloodActor* pSprite, int* ceilZ, Collision* ceilHit, int* floorZ, Collision* floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0); void GetZRangeAtXYZ(int x, int y, int z, sectortype* pSector, int* ceilZ, Collision* ceilHit, int* floorZ, Collision* floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0); +void GetZRangeAtXYZ(const DVector3& pos, sectortype* pSector, double* ceilZ, Collision* ceilHit, double* floorZ, Collision* floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0) +{ + vec3_t ipos = { int(pos.X * worldtoint), int(pos.Y * worldtoint), int(pos.Z * zworldtoint)}; + int cz, fz; + GetZRangeAtXYZ(ipos.X, ipos.Y, ipos.Z, pSector, &cz, ceilHit, &fz, floorHit, nDist, nMask); + *ceilZ = cz * zinttoworld; + *floorZ = fz * zinttoworld; +} int GetDistToLine(int x1, int y1, int x2, int y2, int x3, int y3); void ClipMove(vec3_t& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, CollisionBase& hit, int tracecount = 3); inline void ClipMove(DVector3& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, CollisionBase& hit, int tracecount = 3) @@ -54,6 +62,13 @@ inline void ClipMove(DVector3& pos, sectortype** pSector, int xv, int yv, int wd ClipMove(ipos, pSector, xv, yv, wd, cd, fd, nMask, hit, tracecount); pos = { ipos.X * inttoworld, ipos.Y * inttoworld, ipos.Z * zinttoworld }; } +inline void ClipMove(DVector3& pos, sectortype** pSector, const DVector2& vect, int wd, double cd, double fd, unsigned int nMask, CollisionBase& hit, int tracecount = 3) +{ + // this uses floats only partially. + vec3_t ipos = { int(pos.X * worldtoint), int(pos.Y * worldtoint), int(pos.Z * zworldtoint)}; + ClipMove(ipos, pSector, int(vect.X * worldtoint), int(vect.Y * worldtoint), wd, int(cd * zworldtoint), int(fd * zworldtoint), nMask, hit, tracecount); + pos = { ipos.X * inttoworld, ipos.Y * inttoworld, ipos.Z * zinttoworld }; +} BitArray GetClosestSpriteSectors(sectortype* pSector, const DVector2& pos, int nDist, TArray* pWalls, bool newSectCheckMethod = false); int picWidth(int nPic, int repeat); int picHeight(int nPic, int repeat);