From 276c000f9fc44e4b740b7098cd81cb0c9b45197c Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Mon, 23 Aug 2021 20:54:30 +1000 Subject: [PATCH 01/49] - Blood: Add mechanism to be able to force QAV interpolation based on picnum for testing purposes and not for end-user usage. --- source/core/gamecvars.cpp | 1 + source/core/gamecvars.h | 1 + source/games/blood/src/qav.cpp | 22 +++++++++++++++++++++- source/games/blood/src/qav.h | 16 ---------------- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/source/core/gamecvars.cpp b/source/core/gamecvars.cpp index 60e1a626b..35982b9dd 100644 --- a/source/core/gamecvars.cpp +++ b/source/core/gamecvars.cpp @@ -87,6 +87,7 @@ CVARD(Bool, cl_bloodvanillabobbing, true, CVAR_ARCHIVE, "enable/disable Blood's CVARD(Bool, cl_bloodvanillaexplosions, false, CVAR_ARCHIVE, "enable/disable Blood's vanilla explosion behavior") CVARD(Bool, cl_bloodvanillaenemies, false, CVAR_ARCHIVE, "enable/disable Blood's vanilla enemy behavior") CVARD(Bool, cl_bloodqavinterp, true, CVAR_ARCHIVE, "enable/disable Blood's QAV interpolation") +CVARD(Bool, cl_bloodqavforcedinterp, false, CVAR_ARCHIVE, "enable/disable Blood's QAV interpolation forcefully for QAVs that aren't defined as interpolatable") CVARD(Bool, cl_bloodweapinterp, false, CVAR_ARCHIVE, "enable/disable Blood's weapon interpolation. Depends on 'cl_bloodqavinterp'") CVARD(Bool, cl_bloodoldweapbalance, false, CVAR_ARCHIVE, "enable/disable legacy 1.0 weapon handling for Blood") diff --git a/source/core/gamecvars.h b/source/core/gamecvars.h index 883af97d6..99dfc7798 100644 --- a/source/core/gamecvars.h +++ b/source/core/gamecvars.h @@ -32,6 +32,7 @@ EXTERN_CVAR(Bool, cl_bloodvanillabobbing) EXTERN_CVAR(Bool, cl_bloodvanillaexplosions) EXTERN_CVAR(Bool, cl_bloodvanillaenemies) EXTERN_CVAR(Bool, cl_bloodqavinterp) +EXTERN_CVAR(Bool, cl_bloodqavforcedinterp) EXTERN_CVAR(Bool, cl_bloodweapinterp) EXTERN_CVAR(Bool, cl_bloodoldweapbalance) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index 33c8d1750..ae472db18 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -45,6 +45,22 @@ enum kQAVIsLoopable = 1 << 0, }; +using QAVPrevTileFinder = TILE_FRAME* (*)(FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int& i); + +struct QAVInterpProps +{ + int flags; + QAVPrevTileFinder PrevTileFinder; + TMap> IgnoreData; + + bool CanInterpFrameTile(const int& nFrame, const int& i) + { + // Check whether the current frame's tile is skippable. + auto thisFrame = IgnoreData.CheckKey(nFrame); + return thisFrame ? !thisFrame->Contains(i) : true; + } +}; + static TMap qavPrevTileFinders; static TMap qavInterpProps; @@ -139,11 +155,15 @@ void DrawFrame(double x, double y, double z, double a, TILE_FRAME *pTile, int st } } + +static QAVInterpProps forcedinterpdata{ 0, qavGetInterpType("picnum") }; + void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio) { assert(ticksPerFrame > 0); - auto const interpdata = qavInterpProps.CheckKey(res_id); + QAVInterpProps* interpdata = qavInterpProps.CheckKey(res_id); + if (!interpdata && cl_bloodqavforcedinterp) interpdata = &forcedinterpdata; auto const nFrame = clamp(ticks / ticksPerFrame, 0, nFrames - 1); FRAMEINFO* const thisFrame = &frames[nFrame]; diff --git a/source/games/blood/src/qav.h b/source/games/blood/src/qav.h index 50c6a74f1..aca60789a 100644 --- a/source/games/blood/src/qav.h +++ b/source/games/blood/src/qav.h @@ -238,22 +238,6 @@ struct QAV void Precache(int palette = 0); }; -using QAVPrevTileFinder = TILE_FRAME* (*)(FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int& i); - -struct QAVInterpProps -{ - int flags; - QAVPrevTileFinder PrevTileFinder; - TMap> IgnoreData; - - bool CanInterpFrameTile(const int& nFrame, const int& i) - { - // Check whether the current frame's tile is skippable. - auto thisFrame = IgnoreData.CheckKey(nFrame); - return thisFrame ? !thisFrame->Contains(i) : true; - } -}; - 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); From 4ffd02b1e14ef8e605cebb7071a4841c7e4b8428 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Mon, 23 Aug 2021 21:00:45 +1000 Subject: [PATCH 02/49] - Blood: Declare `qavGetInterpType()` as static within qav.cpp. --- source/games/blood/src/qav.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index ae472db18..fb67dbec5 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -95,7 +95,7 @@ static void qavInitTileFinderMap() }); } -QAVPrevTileFinder qavGetInterpType(const FString& type) +static QAVPrevTileFinder qavGetInterpType(const FString& type) { if (!qavPrevTileFinders.CountUsed()) qavInitTileFinderMap(); return *qavPrevTileFinders.CheckKey(type); From e74e58163789a7ddcaf4d857da2b6de9c0c30872 Mon Sep 17 00:00:00 2001 From: carnivoroussociety <38839485+carnivoroussociety@users.noreply.github.com> Date: Tue, 24 Aug 2021 01:22:31 +1000 Subject: [PATCH 03/49] Fix issues with self collision on MoveMissile() Only with new accurate clipmove() use --- source/games/blood/src/actor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 7035739d8..b698d7fe4 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5440,10 +5440,15 @@ int MoveMissile(spritetype *pSprite) int z = pSprite->z; int nSector2 = pSprite->sectnum; clipmoveboxtracenum = 1; - if ((pSprite->owner >= 0) && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) + const short bakSpriteCstat = pSprite->cstat; + if (pOwner && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) + { enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy + pSprite->cstat &= ~257; // remove self collisions for accurate clipmove + } int vdx = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist<<2, (z-top)/4, (bottom-z)/4, CLIPMASK0); enginecompatibility_mode = bakCompat; // restore + pSprite->cstat = bakSpriteCstat; clipmoveboxtracenum = 3; short nSector = nSector2; if (nSector2 < 0) From 6d958135e04992c05c22c9e8b8abb38a173cb571 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 21 Aug 2021 10:32:20 +0200 Subject: [PATCH 04/49] - give TMap a proper move constructor and assignment operator. --- source/common/utility/tarray.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/common/utility/tarray.h b/source/common/utility/tarray.h index 2aaf5c0cf..4a9e7388b 100644 --- a/source/common/utility/tarray.h +++ b/source/common/utility/tarray.h @@ -837,6 +837,18 @@ public: CopyNodes(o.Nodes, o.Size); } + TMap(TMap &&o) + { + Nodes = o.Nodes; + LastFree = o.LastFree; /* any free position is before this position */ + Size = o.Size; /* must be a power of 2 */ + NumUsed = o.NumUsed; + + o.Size = 0; + o.NumUsed = 0; + o.SetNodeVector(1); + } + TMap &operator= (const TMap &o) { NumUsed = 0; @@ -846,6 +858,12 @@ public: return *this; } + TMap &operator= (TMap &&o) + { + TransferFrom(o); + return *this; + } + //======================================================================= // // TransferFrom From 3aa9d6f8be34a2381e2432e7674ecbf65932c117 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Dec 2020 22:04:07 +0100 Subject: [PATCH 05/49] - MoveThing. # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 221 +++++++++++++++++------------- source/games/blood/src/actor.h | 2 +- source/games/blood/src/fx.cpp | 2 +- source/games/blood/src/nnexts.cpp | 2 +- 4 files changed, 128 insertions(+), 99 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index b698d7fe4..8b16aec7c 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4607,69 +4607,81 @@ static void ProcessTouchObjects(DBloodActor* actor) // //--------------------------------------------------------------------------- -void actAirDrag(spritetype *pSprite, int a2) +void actAirDrag(DBloodActor* actor, int a2) { - int vbp = 0; - int v4 = 0; + auto pSprite = &actor->s(); + + int wind_x = 0; + int wind_y = 0; int nSector = pSprite->sectnum; assert(nSector >= 0 && nSector < kMaxSectors); - sectortype *pSector = §or[nSector]; + sectortype* pSector = §or[nSector]; int nXSector = pSector->extra; if (nXSector > 0) { assert(nXSector < kMaxXSectors); - XSECTOR *pXSector = &xsector[nXSector]; + XSECTOR* pXSector = &xsector[nXSector]; if (pXSector->windVel && (pXSector->windAlways || pXSector->busy)) { - int vcx = pXSector->windVel<<12; - if (!pXSector->windAlways && pXSector->busy) - vcx = MulScale(vcx, pXSector->busy, 16); - vbp = MulScale(vcx, Cos(pXSector->windAng), 30); - v4 = MulScale(vcx, Sin(pXSector->windAng), 30); + int wind = pXSector->windVel << 12; + if (!pXSector->windAlways && pXSector->busy) wind = MulScale(wind, pXSector->busy, 16); + wind_x = MulScale(wind, Cos(pXSector->windAng), 30); + wind_y = MulScale(wind, Sin(pXSector->windAng), 30); } } - xvel[pSprite->index] += MulScale(vbp-xvel[pSprite->index], a2, 16); - yvel[pSprite->index] += MulScale(v4-yvel[pSprite->index], a2, 16); - zvel[pSprite->index] -= MulScale(zvel[pSprite->index], a2, 16); + actor->xvel() += MulScale(wind_x - actor->xvel(), a2, 16); + actor->yvel() += MulScale(wind_y - actor->yvel(), a2, 16); + actor->zvel() -= MulScale(actor->zvel(), a2, 16); } -int MoveThing(spritetype *pSprite) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +int MoveThing(DBloodActor* actor) { - int nXSprite = pSprite->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); - XSPRITE *pXSprite = &xsprite[nXSprite]; - int nSprite = pSprite->index; - int v8 = 0; + auto pSprite = &actor->s(); + assert(actor->hasX()); + XSPRITE* pXSprite = &actor->x(); + int lhit = 0; assert(pSprite->type >= kThingBase && pSprite->type < kThingMax); - const THINGINFO *pThingInfo = &thingInfo[pSprite->type-kThingBase]; + const THINGINFO* pThingInfo = &thingInfo[pSprite->type - kThingBase]; int nSector = pSprite->sectnum; assert(nSector >= 0 && nSector < kMaxSectors); int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); + + GetActorExtents(actor, &top, &bottom); const int bakCompat = enginecompatibility_mode; - if (xvel[nSprite] || yvel[nSprite]) + if (actor->xvel() || actor->yvel()) { short bakCstat = pSprite->cstat; pSprite->cstat &= ~257; if ((pSprite->owner >= 0) && !cl_bloodvanillaexplosions && !VanillaMode()) enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy - v8 = gSpriteHit[nXSprite].hit = ClipMove((int*)&pSprite->x, (int*)&pSprite->y, (int*)&pSprite->z, &nSector, xvel[nSprite]>>12, yvel[nSprite]>>12, pSprite->clipdist<<2, (pSprite->z-top)/4, (bottom-pSprite->z)/4, CLIPMASK0); + lhit = actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel() >> 12, actor->yvel() >> 12, pSprite->clipdist << 2, (pSprite->z - top) / 4, (bottom - pSprite->z) / 4, CLIPMASK0); enginecompatibility_mode = bakCompat; // restore pSprite->cstat = bakCstat; assert(nSector >= 0); if (pSprite->sectnum != nSector) { assert(nSector >= 0 && nSector < kMaxSectors); - ChangeSpriteSect(nSprite, nSector); + ChangeSpriteSect(pSprite->index, nSector); } - if ((gSpriteHit[nXSprite].hit&0xc000) == 0x8000) { - int nHitWall = gSpriteHit[nXSprite].hit&0x3fff; - actWallBounceVector((int*)&xvel[nSprite], (int*)&yvel[nSprite], nHitWall, pThingInfo->elastic); - switch (pSprite->type) { + + Collision coll(actor->hit().hit); + if (coll.type == kHitWall) + { + int nHitWall = coll.index; + actWallBounceVector(&actor->xvel(), &actor->yvel(), nHitWall, pThingInfo->elastic); + switch (pSprite->type) + { case kThingZombieHead: sfxPlay3DSound(pSprite, 607, 0, 0); - actDamageSprite(-1, pSprite, kDamageFall, 80); + actDamageSprite(nullptr, actor, kDamageFall, 80); break; + case kThingKickablePail: sfxPlay3DSound(pSprite, 374, 0, 0); break; @@ -4681,140 +4693,157 @@ int MoveThing(spritetype *pSprite) assert(nSector >= 0 && nSector < kMaxSectors); FindSector(pSprite->x, pSprite->y, pSprite->z, &nSector); } - if (zvel[nSprite]) - pSprite->z += zvel[nSprite]>>8; + + pSprite->z += actor->zvel() >> 8; + int ceilZ, ceilHit, floorZ, floorHit; - GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0); - GetSpriteExtents(pSprite, &top, &bottom); + GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); + GetActorExtents(actor, &top, &bottom); + if ((pSprite->flags & 2) && bottom < floorZ) { pSprite->z += 455; - zvel[nSprite] += 58254; + actor->zvel() += 58254; if (pSprite->type == kThingZombieHead) { - spritetype *pFX = gFX.fxSpawn(FX_27, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); - if (pFX) + auto* fxActor = gFX.fxSpawnActor(FX_27, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); + if (fxActor) { - int v34 = (PlayClock*3)&2047; - int v30 = (PlayClock*5)&2047; - int vbx = (PlayClock*11)&2047; + int v34 = (PlayClock * 3) & 2047; + int v30 = (PlayClock * 5) & 2047; + int vbx = (PlayClock * 11) & 2047; int v2c = 0x44444; int v28 = 0; int v24 = 0; - RotateVector(&v2c,&v28,vbx); - RotateVector(&v2c,&v24,v30); - RotateVector(&v28,&v24,v34); - xvel[pFX->index] = xvel[pSprite->index]+v2c; - yvel[pFX->index] = yvel[pSprite->index]+v28; - zvel[pFX->index] = zvel[pSprite->index]+v24; + RotateVector(&v2c, &v28, vbx); + RotateVector(&v2c, &v24, v30); + RotateVector(&v28, &v24, v34); + fxActor->xvel() = actor->xvel() + v2c; + fxActor->yvel() = actor->yvel() + v28; + fxActor->zvel() = actor->zvel() + v24; } } } - if (CheckLink(pSprite)) - GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0); - GetSpriteExtents(pSprite, &top, &bottom); + if (CheckLink(pSprite)) GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); + + GetActorExtents(actor, &top, &bottom); if (bottom >= floorZ) { - actTouchFloor(&bloodActors[pSprite->index], pSprite->sectnum); - gSpriteHit[nXSprite].florhit = floorHit; - pSprite->z += floorZ-bottom; - int v20 = zvel[nSprite]-velFloor[pSprite->sectnum]; + actTouchFloor(actor, pSprite->sectnum); + actor->hit().florhit = floorHit; + pSprite->z += floorZ - bottom; + + int v20 = actor->zvel() - velFloor[pSprite->sectnum]; if (v20 > 0) { pSprite->flags |= 4; - int vax = actFloorBounceVector((int*)&xvel[nSprite], (int*)&yvel[nSprite], (int*)&v20, pSprite->sectnum, pThingInfo->elastic); - int nDamage = MulScale(vax, vax, 30)-pThingInfo->dmgResist; - if (nDamage > 0) - actDamageSprite(nSprite, pSprite, kDamageFall, nDamage); - zvel[nSprite] = v20; - if (velFloor[pSprite->sectnum] == 0 && abs(zvel[nSprite]) < 0x10000) - { - zvel[nSprite] = 0; + int vax = actFloorBounceVector(&actor->xvel(), &actor->yvel(), (int*)&v20, pSprite->sectnum, pThingInfo->elastic); + int nDamage = MulScale(vax, vax, 30) - pThingInfo->dmgResist; + if (nDamage > 0) actDamageSprite(actor, actor, kDamageFall, nDamage); + actor->zvel() = v20; + if (velFloor[pSprite->sectnum] == 0 && abs(actor->zvel()) < 0x10000) + { + actor->zvel() = 0; pSprite->flags &= ~4; } - - switch (pSprite->type) { + + switch (pSprite->type) + { case kThingNapalmBall: - if (zvel[nSprite] == 0 || Chance(0xA000)) actNapalmMove(&bloodActors[pXSprite->reference]); + if (actor->zvel() == 0 || Chance(0xA000)) actNapalmMove(actor); break; + case kThingZombieHead: - if (abs(zvel[nSprite]) > 0x80000) { + if (abs(actor->zvel()) > 0x80000) + { sfxPlay3DSound(pSprite, 607, 0, 0); - actDamageSprite(-1, pSprite, kDamageFall, 80); + actDamageSprite(nullptr, actor, kDamageFall, 80); } break; + case kThingKickablePail: - if (abs(zvel[nSprite]) > 0x80000) + if (abs(actor->zvel()) > 0x80000) sfxPlay3DSound(pSprite, 374, 0, 0); break; } - v8 = 0x4000|nSector; + lhit = kHitSector | nSector; } - else if (zvel[nSprite] == 0) + else if (actor->zvel() == 0) pSprite->flags &= ~4; } else { - gSpriteHit[nXSprite].florhit = 0; + actor->hit().florhit = 0; - if (pSprite->flags&2) + if (pSprite->flags & 2) pSprite->flags |= 4; } + if (top <= ceilZ) { - gSpriteHit[nXSprite].ceilhit = ceilHit; - pSprite->z += ClipLow(ceilZ-top, 0); - if (zvel[nSprite] < 0) + actor->hit().ceilhit = ceilHit; + pSprite->z += ClipLow(ceilZ - top, 0); + if (actor->zvel() < 0) { - xvel[nSprite] = MulScale(xvel[nSprite], 0xc000, 16); - yvel[nSprite] = MulScale(yvel[nSprite], 0xc000, 16); - zvel[nSprite] = MulScale(-zvel[nSprite], 0x4000, 16); - switch (pSprite->type) { + actor->xvel() = MulScale(actor->xvel(), 0xc000, 16); + actor->yvel() = MulScale(actor->yvel(), 0xc000, 16); + actor->zvel() = MulScale(-actor->zvel(), 0x4000, 16); + + switch (pSprite->type) + { case kThingZombieHead: - if (abs(zvel[nSprite]) > 0x80000) { + if (abs(actor->zvel()) > 0x80000) + { sfxPlay3DSound(pSprite, 607, 0, 0); - actDamageSprite(-1, pSprite, kDamageFall, 80); + actDamageSprite(nullptr, actor, kDamageFall, 80); } break; + case kThingKickablePail: - if (abs(zvel[nSprite]) > 0x80000) + if (abs(actor->zvel()) > 0x80000) sfxPlay3DSound(pSprite, 374, 0, 0); break; } } } - else - gSpriteHit[nXSprite].ceilhit = 0; + else actor->hit().ceilhit = 0; + if (bottom >= floorZ) { - int nVel = approxDist(xvel[nSprite], yvel[nSprite]); + int nVel = approxDist(actor->xvel(), actor->yvel()); int nVelClipped = ClipHigh(nVel, 0x11111); if ((floorHit & 0xc000) == 0xc000) { int nHitSprite = floorHit & 0x3fff; if ((sprite[nHitSprite].cstat & 0x30) == 0) { - xvel[nSprite] += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); - yvel[nSprite] += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); - v8 = gSpriteHit[nXSprite].hit; + actor->xvel() += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); + actor->yvel() += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); + lhit = actor->hit().hit; } } if (nVel > 0) { int t = DivScale(nVelClipped, nVel, 16); - xvel[nSprite] -= MulScale(t, xvel[nSprite], 16); - yvel[nSprite] -= MulScale(t, yvel[nSprite], 16); + actor->xvel() -= MulScale(t, actor->xvel(), 16); + actor->yvel() -= MulScale(t, actor->yvel(), 16); } } - if (xvel[nSprite] || yvel[nSprite]) - pSprite->ang = getangle(xvel[nSprite], yvel[nSprite]); - return v8; + if (actor->xvel() || actor->yvel()) + pSprite->ang = getangle(actor->xvel(), actor->yvel()); + return lhit; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void MoveDude(spritetype *pSprite) { int nXSprite = pSprite->extra; @@ -5396,7 +5425,7 @@ int MoveMissile(spritetype *pSprite) gHitInfo.hitwall = -1; gHitInfo.hitsprite = -1; if (pSprite->type == kMissileFlameSpray) - actAirDrag(pSprite, 0x1000); + actAirDrag(&bloodActors[pSprite->index], 0x1000); int nSprite = pSprite->index; if (pXSprite->target != -1 && (xvel[nSprite] || yvel[nSprite] || zvel[nSprite])) { @@ -5896,14 +5925,14 @@ void actProcessSprites(void) yvel[nSprite] += dy; } } - actAirDrag(pSprite, 128); + actAirDrag(&bloodActors[pSprite->index], 128); if (((pSprite->index>>8)&15) == (gFrameCount&15) && (pSprite->flags&2)) pSprite->flags |= 4; if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) { - int hit = MoveThing(pSprite); + int hit = MoveThing(&bloodActors[pSprite->index]); if (hit) { int nXSprite = pSprite->extra; @@ -6348,9 +6377,9 @@ void actProcessSprites(void) } } if (pXSector && pXSector->Underwater) - actAirDrag(pSprite, 5376); + actAirDrag(&bloodActors[pSprite->index], 5376); else - actAirDrag(pSprite, 128); + actAirDrag(&bloodActors[pSprite->index], 128); if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) diff --git a/source/games/blood/src/actor.h b/source/games/blood/src/actor.h index 8eccca604..7dfed1524 100644 --- a/source/games/blood/src/actor.h +++ b/source/games/blood/src/actor.h @@ -228,7 +228,7 @@ void actKillDude(int a1, spritetype *pSprite, DAMAGE_TYPE a3, int a4); int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4); int actDamageSprite(DBloodActor* pSource, DBloodActor* pTarget, DAMAGE_TYPE damageType, int damage); void actHitcodeToData(int a1, HITINFO *pHitInfo, DBloodActor **actor, walltype **a7 = nullptr); -void actAirDrag(spritetype *pSprite, int a2); +void actAirDrag(DBloodActor *pSprite, int a2); int MoveThing(spritetype *pSprite); void MoveDude(spritetype *pSprite); int MoveMissile(spritetype *pSprite); diff --git a/source/games/blood/src/fx.cpp b/source/games/blood/src/fx.cpp index c156c9415..5db463572 100644 --- a/source/games/blood/src/fx.cpp +++ b/source/games/blood/src/fx.cpp @@ -204,7 +204,7 @@ void CFX::fxProcess(void) assert(nSector >= 0 && nSector < kMaxSectors); assert(pSprite->type < kFXMax); FXDATA *pFXData = &gFXData[pSprite->type]; - actAirDrag(pSprite, pFXData->drag); + actAirDrag(&bloodActors[pSprite->index], pFXData->drag); if (xvel[nSprite]) pSprite->x += xvel[nSprite]>>12; if (yvel[nSprite]) diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index b97ffbfb6..d7c97654b 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -1286,7 +1286,7 @@ void nnExtProcessSuperSprites() { } - actAirDrag(pDebris, airVel); + actAirDrag(&bloodActors[pDebris->index], airVel); if (pXDebris->physAttr & kPhysDebrisTouch) { PLAYER* pPlayer = NULL; From 4fed1debe437fc74cb9335707b49822439853fc5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Dec 2020 14:25:04 +0100 Subject: [PATCH 06/49] - moveDude part 1. --- source/games/blood/src/actor.cpp | 265 ++++++++++++------------------- 1 file changed, 100 insertions(+), 165 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 8b16aec7c..79f22205f 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4844,21 +4844,21 @@ int MoveThing(DBloodActor* actor) // //--------------------------------------------------------------------------- -void MoveDude(spritetype *pSprite) +void MoveDude(DBloodActor *actor) { - int nXSprite = pSprite->extra; - XSPRITE *pXSprite = &xsprite[nXSprite]; - int nSprite = pSprite->index; - PLAYER *pPlayer = NULL; - if (IsPlayerSprite(pSprite)) - pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; - if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { - Printf(PRINT_HIGH, "pSprite->type >= kDudeBase && pSprite->type < kDudeMax"); + auto const pSprite = &actor->s(); + auto const pXSprite = &actor->x(); + PLAYER *pPlayer = nullptr; + if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) + { + Printf(PRINT_HIGH, "%d: pSprite->type >= kDudeBase && pSprite->type < kDudeMax", pSprite->type); return; } + DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); int bz = (bottom-pSprite->z)/4; int tz = (pSprite->z-top)/4; int wd = pSprite->clipdist<<2; @@ -4866,12 +4866,13 @@ void MoveDude(spritetype *pSprite) int nAiStateType = (pXSprite->aiState) ? pXSprite->aiState->stateType : -1; assert(nSector >= 0 && nSector < kMaxSectors); - if (xvel[nSprite] || yvel[nSprite]) + + if (actor->xvel() || actor->yvel()) { if (pPlayer && gNoClip) { - pSprite->x += xvel[nSprite]>>12; - pSprite->y += yvel[nSprite]>>12; + pSprite->x += actor->xvel()>>12; + pSprite->y += actor->yvel()>>12; if (!FindSector(pSprite->x, pSprite->y, &nSector)) nSector = pSprite->sectnum; } @@ -4879,7 +4880,7 @@ void MoveDude(spritetype *pSprite) { short bakCstat = pSprite->cstat; pSprite->cstat &= ~257; - gSpriteHit[nXSprite].hit = ClipMove((int*)&pSprite->x, (int*)&pSprite->y, (int*)&pSprite->z, &nSector, xvel[nSprite]>>12, yvel[nSprite]>>12, wd, tz, bz, CLIPMASK0); + actor->hit().hit = ClipMove((int*)&pSprite->x, (int*)&pSprite->y, (int*)&pSprite->z, &nSector, actor->xvel()>>12, actor->yvel()>>12, wd, tz, bz, CLIPMASK0); if (nSector == -1) { nSector = pSprite->sectnum; @@ -4891,68 +4892,69 @@ void MoveDude(spritetype *pSprite) { short nSector2 = nSector; if (pushmove_old(&pSprite->x, &pSprite->y, &pSprite->z, &nSector2, wd, tz, bz, CLIPMASK0) == -1) - actDamageSprite(nSprite, pSprite, kDamageFall, 1000 << 4); + actDamageSprite(actor, actor, kDamageFall, 1000 << 4); if (nSector2 != -1) nSector = nSector2; } assert(nSector >= 0); pSprite->cstat = bakCstat; } - switch (gSpriteHit[nXSprite].hit&0xc000) + Collision coll = actor->hit().hit; + switch (actor->hit().hit&0xc000) { - case 0xc000: + case kHitSprite: { - int nHitSprite = gSpriteHit[nXSprite].hit&0x3fff; - spritetype *pHitSprite = &sprite[nHitSprite]; - XSPRITE *pHitXSprite = NULL; - // Should be pHitSprite here - if (pSprite->extra > 0) - pHitXSprite = &xsprite[pHitSprite->extra]; - int nOwner = pHitSprite->owner; + spritetype* pHitSprite = &coll.actor->s(); + XSPRITE* pHitXSprite = coll.actor->hasX() ? &coll.actor->x() : nullptr;; - if (pHitSprite->statnum == kStatProjectile && !(pHitSprite->flags&32) && pSprite->index != nOwner) + auto Owner = coll.actor->GetOwner(); + + if (pHitSprite->statnum == kStatProjectile && !(pHitSprite->flags&32) && actor != Owner) { HITINFO hitInfo = gHitInfo; - gHitInfo.hitsprite = nSprite; - actImpactMissile(&bloodActors[nHitSprite], 3); + gHitInfo.hitsprite = pSprite->index; + actImpactMissile(actor, 3); gHitInfo = hitInfo; } #ifdef NOONE_EXTENSIONS if (!gModernMap && pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) - trTriggerSprite(nHitSprite, pHitXSprite, kCmdSpriteTouch); + trTriggerSprite(coll.actor, kCmdSpriteTouch); #else if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) - trTriggerSprite(nHitSprite, pHitXSprite, kCmdSpriteTouch); + trTriggerSprite(coll.actor, kCmdSpriteTouch); #endif if (pDudeInfo->lockOut && pHitXSprite && pHitXSprite->Push && !pHitXSprite->key && !pHitXSprite->DudeLockout && !pHitXSprite->state && !pHitXSprite->busy && !pPlayer) - trTriggerSprite(nHitSprite, pHitXSprite, kCmdSpritePush); + trTriggerSprite(coll.actor, kCmdSpritePush); break; } - case 0x8000: + case kHitWall: { - int nHitWall = gSpriteHit[nXSprite].hit&0x3fff; + int nHitWall = coll.index; walltype *pHitWall = &wall[nHitWall]; XWALL *pHitXWall = NULL; if (pHitWall->extra > 0) pHitXWall = &xwall[pHitWall->extra]; if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) trTriggerWall(nHitWall, pHitXWall, kCmdWallPush); + if (pHitWall->nextsector != -1) { sectortype *pHitSector = §or[pHitWall->nextsector]; XSECTOR *pHitXSector = NULL; if (pHitSector->extra > 0) pHitXSector = &xsector[pHitSector->extra]; + if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer) trTriggerSector(pHitWall->nextsector, pHitXSector, kCmdSectorPush); + if (top < pHitSector->ceilingz || bottom > pHitSector->floorz) { // ??? } } - actWallBounceVector((int*)&xvel[nSprite], (int*)&yvel[nSprite], nHitWall, 0); + actWallBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), nHitWall, 0); break; } } @@ -4973,14 +4975,14 @@ void MoveDude(spritetype *pSprite) pXSector = NULL; if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); - ChangeSpriteSect(nSprite, nSector); + ChangeSpriteSect(pSprite->index, nSector); nXSector = sector[nSector].extra; pXSector = (nXSector > 0) ? &xsector[nXSector] : NULL; - if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) { - + if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) + { if (sector[nSector].type == kSectorTeleport) - pXSector->data = pPlayer ? nSprite : -1; + pXSector->data = pPlayer ? pSprite->index : -1; trTriggerSector(nSector, pXSector, kCmdSectorEnter); } @@ -5004,11 +5006,11 @@ void MoveDude(spritetype *pSprite) bDepth = 1; if (pPlayer) wd += 16; - if (zvel[nSprite]) - pSprite->z += zvel[nSprite]>>8; + if (actor->zvel()) + pSprite->z += actor->zvel()>>8; int ceilZ, ceilHit, floorZ, floorHit; GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); if (pSprite->flags & 2) { @@ -5040,10 +5042,10 @@ void MoveDude(spritetype *pSprite) if (vc) { pSprite->z += ((vc*4)/2)>>8; - zvel[nSprite] += vc; + actor->zvel() += vc; } } - if (pPlayer && zvel[nSprite] > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) + if (pPlayer && actor->zvel() > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) { const bool playerAlive = (pXSprite->health > 0) || VanillaMode(); // only trigger falling scream if player is alive or vanilla mode if (playerAlive) @@ -5059,7 +5061,8 @@ void MoveDude(spritetype *pSprite) GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); if (pPlayer) playerCorrectInertia(pPlayer, &oldpos); - switch (nLink) { + switch (nLink) + { case kMarkerLowStack: if (pPlayer == gView) setgotpic(sector[pSprite->sectnum].floorpicnum); @@ -5071,17 +5074,21 @@ void MoveDude(spritetype *pSprite) case kMarkerLowWater: case kMarkerLowGoo: pXSprite->medium = kMediumNormal; - if (pPlayer) { + if (pPlayer) + { pPlayer->posture = 0; pPlayer->bubbleTime = 0; - if (!pPlayer->cantJump && (pPlayer->input.actions & SB_JUMP)) { - zvel[nSprite] = -0x6aaaa; + if (!pPlayer->cantJump && (pPlayer->input.actions & SB_JUMP)) + { + actor->zvel() = -0x6aaaa; pPlayer->cantJump = 1; } sfxPlay3DSound(pSprite, 721, -1, 0); - } else { - - switch (pSprite->type) { + } + else + { + switch (pSprite->type) + { case kDudeCultistTommy: case kDudeCultistShotgun: aiNewState(&bloodActors[pXSprite->reference], &cultistGoto); @@ -5126,20 +5133,20 @@ void MoveDude(spritetype *pSprite) pPlayer->posture = 1; pXSprite->burnTime = 0; - pPlayer->bubbleTime = abs(zvel[nSprite]) >> 12; - evPost(nSprite, 3, 0, kCallbackPlayerBubble); + pPlayer->bubbleTime = abs(actor->zvel()) >> 12; + evPost(actor, 0, kCallbackPlayerBubble); sfxPlay3DSound(pSprite, 720, -1, 0); } else { - - switch (pSprite->type) { + switch (pSprite->type) + { case kDudeCultistTommy: case kDudeCultistShotgun: pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(&bloodActors[pXSprite->reference], &cultistSwimGoto); + aiNewState(actor, &cultistSwimGoto); break; case kDudeBurningCultist: { @@ -5151,28 +5158,28 @@ void MoveDude(spritetype *pSprite) if (fixRandomCultist) // fix burning cultists randomly switching types underwater pSprite->type = pSprite->inittype; // restore back to spawned cultist type pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(&bloodActors[pXSprite->reference], &cultistSwimGoto); + aiNewState(actor, &cultistSwimGoto); break; } case kDudeZombieAxeNormal: pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(&bloodActors[pXSprite->reference], &zombieAGoto); + aiNewState(actor, &zombieAGoto); break; case kDudeZombieButcher: pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(&bloodActors[pXSprite->reference], &zombieFGoto); + aiNewState(actor, &zombieFGoto); break; case kDudeGillBeast: pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(&bloodActors[pXSprite->reference], &gillBeastSwimGoto); + aiNewState(actor, &gillBeastSwimGoto); pSprite->flags &= ~6; break; @@ -5192,11 +5199,10 @@ void MoveDude(spritetype *pSprite) if (gModernMap) { if (pSprite->type == kDudeModernCustom) { - - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - if (!canSwim(pSprite)) - actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); + evPost(actor, 0, kCallbackEnemeyBubble); + if (!canSwim(pSprite)) actKillDude(actor, actor, kDamageFall, 1000 << 4); + break; } // continue patrol when fall into water @@ -5209,80 +5215,9 @@ void MoveDude(spritetype *pSprite) } break; } - /*case 13: - pXSprite->medium = kMediumGoo; - if (pPlayer) - { - pPlayer->changeTargetKin = 1; - pXSprite->burnTime = 0; - pPlayer->bubbleTime = abs(zvel[nSprite])>>12; - evPost(nSprite, 3, 0, kCallbackPlayerBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); } - else - { - switch (pSprite->type) - { - case kDudeCultistTommy: - case kDudeCultistShotgun: - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); - break; - case kDudeBurningCultist: - if (Chance(0x400)) - { - pSprite->type = kDudeCultistTommy; - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); } - else - { - pSprite->type = kDudeCultistShotgun; - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); - } - break; - case kDudeZombieAxeNormal: - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &zombieAGoto); - break; - case kDudeZombieButcher: - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &zombieFGoto); - break; - case kDudeGillBeast: - pXSprite->burnTime = 0; - evPost(nSprite, 3, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &gillBeastSwimGoto); - pSprite->flags &= ~6; - break; - case kDudeGargoyleFlesh: - case kDudeHellHound: - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: - case kDudeBat: - case kDudeRat: - case kDudeBurningInnocent: - actKillDude(pSprite->index, pSprite, kDamageFall, 1000<<4); - break; - } - } - break;*/ - } - } - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); if (pPlayer && bottom >= floorZ) { int floorZ2 = floorZ; @@ -5296,12 +5231,12 @@ void MoveDude(spritetype *pSprite) } if (floorZ <= bottom) { - gSpriteHit[nXSprite].florhit = floorHit; + actor->hit().florhit = floorHit; pSprite->z += floorZ-bottom; - int v30 = zvel[nSprite]-velFloor[pSprite->sectnum]; + int v30 = actor->zvel()-velFloor[pSprite->sectnum]; if (v30 > 0) { - int vax = actFloorBounceVector((int*)&xvel[nSprite], (int*)&yvel[nSprite], (int*)&v30, pSprite->sectnum, 0); + int vax = actFloorBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), (int*)&v30, pSprite->sectnum, 0); int nDamage = MulScale(vax, vax, 30); if (pPlayer) { @@ -5314,11 +5249,11 @@ void MoveDude(spritetype *pSprite) } nDamage -= 100<<4; if (nDamage > 0) - actDamageSprite(nSprite, pSprite, kDamageFall, nDamage); - zvel[nSprite] = v30; - if (abs(zvel[nSprite]) < 0x10000) + actDamageSprite(actor, actor, kDamageFall, nDamage); + actor->zvel() = v30; + if (abs(actor->zvel()) < 0x10000) { - zvel[nSprite] = velFloor[pSprite->sectnum]; + actor->zvel() = velFloor[pSprite->sectnum]; pSprite->flags &= ~4; } @@ -5337,12 +5272,12 @@ void MoveDude(spritetype *pSprite) { for (int i = 0; i < 7; i++) { - spritetype *pFX2 = gFX.fxSpawn(FX_14, pFX->sectnum, pFX->x, pFX->y, pFX->z, 0); + auto pFX2 = gFX.fxSpawnActor(FX_14, pFX->sectnum, pFX->x, pFX->y, pFX->z, 0); if (pFX2) { - xvel[pFX2->index] = Random2(0x6aaaa); - yvel[pFX2->index] = Random2(0x6aaaa); - zvel[pFX2->index] = -(int)Random(0xd5555); + pFX2->xvel() = Random2(0x6aaaa); + pFX2->yvel() = Random2(0x6aaaa); + pFX2->zvel() = -(int)Random(0xd5555); } } } @@ -5350,39 +5285,39 @@ void MoveDude(spritetype *pSprite) } } } - else if (zvel[nSprite] == 0) + else if (actor->zvel() == 0) pSprite->flags &= ~4; } else { - gSpriteHit[nXSprite].florhit = 0; + actor->hit().florhit = 0; if (pSprite->flags&2) pSprite->flags |= 4; } if (top <= ceilZ) { - gSpriteHit[nXSprite].ceilhit = ceilHit; + actor->hit().ceilhit = ceilHit; pSprite->z += ClipLow(ceilZ-top, 0); - if (zvel[nSprite] <= 0 && (pSprite->flags&4)) - zvel[nSprite] = MulScale(-zvel[nSprite], 0x2000, 16); + if (actor->zvel() <= 0 && (pSprite->flags&4)) + actor->zvel() = MulScale(-actor->zvel(), 0x2000, 16); } else - gSpriteHit[nXSprite].ceilhit = 0; - GetSpriteExtents(pSprite,&top,&bottom); + actor->hit().ceilhit = 0; + GetActorExtents(actor,&top,&bottom); pXSprite->height = ClipLow(floorZ-bottom, 0)>>8; - if (xvel[nSprite] || yvel[nSprite]) + if (actor->xvel() || actor->yvel()) { if ((floorHit & 0xc000) == 0xc000) { int nHitSprite = floorHit & 0x3fff; if ((sprite[nHitSprite].cstat & 0x30) == 0) { - xvel[nSprite] += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); - yvel[nSprite] += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); + actor->xvel() += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); + actor->yvel() += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); return; } } @@ -5394,11 +5329,11 @@ void MoveDude(spritetype *pSprite) int nDrag = gDudeDrag; if (pXSprite->height > 0) nDrag -= scale(gDudeDrag, pXSprite->height, 0x100); - xvel[nSprite] -= mulscale16r(xvel[nSprite], nDrag); - yvel[nSprite] -= mulscale16r(yvel[nSprite], nDrag); + actor->xvel() -= mulscale16r(actor->xvel(), nDrag); + actor->yvel() -= mulscale16r(actor->yvel(), nDrag); - if (approxDist(xvel[nSprite], yvel[nSprite]) < 0x1000) - xvel[nSprite] = yvel[nSprite] = 0; + if (approxDist(actor->xvel(), actor->yvel()) < 0x1000) + actor->xvel() = actor->yvel() = 0; } } @@ -6383,7 +6318,7 @@ void actProcessSprites(void) if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) - MoveDude(pSprite); + MoveDude(&bloodActors[pSprite->index]); } it.Reset(kStatFlare); while ((nSprite = it.NextIndex()) >= 0) From c1d52f7393015d94abb6818712f425fe12b78fdf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 4 Dec 2020 23:21:42 +0100 Subject: [PATCH 07/49] - replaced all occurences of gDudeExtra and moved that struct into DBloodActor. # Conflicts: # source/games/blood/src/ai.cpp --- source/games/blood/src/actor.cpp | 23 ++--- source/games/blood/src/ai.cpp | 133 +++++++++------------------ source/games/blood/src/ai.h | 1 - source/games/blood/src/aibat.cpp | 4 +- source/games/blood/src/aiboneel.cpp | 4 +- source/games/blood/src/aicerber.cpp | 2 +- source/games/blood/src/aigarg.cpp | 2 +- source/games/blood/src/aighost.cpp | 2 +- source/games/blood/src/aispid.cpp | 2 +- source/games/blood/src/aitchern.cpp | 2 +- source/games/blood/src/aiunicult.cpp | 6 +- source/games/blood/src/bloodactor.h | 5 +- source/games/blood/src/loadsave.cpp | 31 ++++++- source/games/blood/src/nnexts.cpp | 3 +- 14 files changed, 99 insertions(+), 121 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 79f22205f..0887f380b 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2972,7 +2972,7 @@ static bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType) aiGenDudeNewState(pSprite, &genDudeBurnGoto); actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth); if (pXSprite->burnTime <= 0) pXSprite->burnTime = 1200; - actor->dudeExtra().time = PlayClock + 360; + actor->dudeExtra.time = PlayClock + 360; return true; } @@ -3484,7 +3484,8 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag return; } - switch (pSprite->type) + auto Owner = actor->GetOwner(); + switch (pSprite->type) { case kDudeZombieAxeNormal: zombieAxeNormalDeath(actor, nSeq); @@ -3554,29 +3555,17 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag break; case kDudeSpiderBrown: - if (pSprite->owner != -1) - { - spritetype* pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } + if (Owner) Owner->dudeExtra.at6.u1.xval2--; genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); break; case kDudeSpiderRed: - if (pSprite->owner != -1) - { - spritetype* pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } + if (Owner) Owner->dudeExtra.at6.u1.xval2--; genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); break; case kDudeSpiderBlack: - if (pSprite->owner != -1) - { - spritetype* pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } + if (Owner) Owner->dudeExtra.at6.u1.xval2--; genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); break; diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index 3d88c236b..4f605171d 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -33,7 +33,6 @@ BEGIN_BLD_NS void RecoilDude(DBloodActor* actor); int cumulDamage[kMaxXSprites]; -DUDEEXTRA gDudeExtra[kMaxXSprites]; AISTATE genIdle = {kAiStateGenIdle, 0, -1, 0, NULL, NULL, NULL, NULL }; AISTATE genRecoil = {kAiStateRecoil, 5, -1, 20, NULL, NULL, NULL, &genIdle }; @@ -53,7 +52,8 @@ bool dudeIsPlayingSeq(spritetype *pSprite, int nSeq) void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4) { - DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; + auto actor = &bloodActors[pSprite->index]; + DUDEEXTRA *pDudeExtra = &actor->dudeExtra; if (a3 == AI_SFX_PRIORITY_0) sfxPlay3DSound(pSprite, a2, a4, 2); else if (a3 > pDudeExtra->prio || pDudeExtra->time <= PlayClock) @@ -321,7 +321,7 @@ void aiActivateDude(DBloodActor* actor) switch (pSprite->type) { case kDudePhantasm: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; @@ -340,7 +340,7 @@ void aiActivateDude(DBloodActor* actor) case kDudeCultistTNT: case kDudeCultistBeast: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) { @@ -378,7 +378,7 @@ void aiActivateDude(DBloodActor* actor) #ifdef NOONE_EXTENSIONS case kDudeModernCustom: { - DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1* pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) { @@ -397,7 +397,7 @@ void aiActivateDude(DBloodActor* actor) break; #endif case kDudeCultistTommyProne: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; pSprite->type = kDudeCultistTommy; if (pXSprite->target == -1) { @@ -430,7 +430,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeCultistShotgunProne: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; pSprite->type = kDudeCultistShotgun; @@ -474,7 +474,7 @@ void aiActivateDude(DBloodActor* actor) break; case kDudeBat: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; @@ -492,7 +492,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeBoneEel: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; @@ -509,7 +509,7 @@ void aiActivateDude(DBloodActor* actor) break; } case kDudeGillBeast: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; XSECTOR *pXSector = NULL; if (sector[pSprite->sectnum].extra > 0) pXSector = &xsector[sector[pSprite->sectnum].extra]; @@ -537,7 +537,7 @@ void aiActivateDude(DBloodActor* actor) break; } case kDudeZombieAxeNormal: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) @@ -567,7 +567,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeZombieAxeBuried: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->aiState == &zombieEIdle) @@ -576,7 +576,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeZombieAxeLaying: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->aiState == &zombieSIdle) @@ -584,7 +584,7 @@ void aiActivateDude(DBloodActor* actor) break; } case kDudeZombieButcher: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) @@ -612,7 +612,7 @@ void aiActivateDude(DBloodActor* actor) aiNewState(actor, &zombieFBurnChase); break; case kDudeGargoyleFlesh: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; @@ -630,7 +630,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeGargoyleStone: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; @@ -747,7 +747,7 @@ void aiActivateDude(DBloodActor* actor) } break; case kDudeSpiderMother: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 1; pDudeExtraE->xval1 = 0; pSprite->flags |= 2; @@ -763,7 +763,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeTinyCaleb: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) @@ -796,7 +796,7 @@ void aiActivateDude(DBloodActor* actor) } case kDudeBeast: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 1; pDudeExtraE->xval1 = 0; if (pXSprite->target == -1) @@ -944,9 +944,9 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType if (pSprite->type == kDudeModernCustomBurning) { - if (Chance(0x2000) && gDudeExtra[pSprite->extra].time < PlayClock) { + if (Chance(0x2000) && actor->dudeExtra.time < PlayClock) { playGenDudeSound(pSprite, kGenDudeSndBurning); - gDudeExtra[pSprite->extra].time = PlayClock + 360; + actor->dudeExtra.time = PlayClock + 360; } if (pXSprite->burnTime == 0) pXSprite->burnTime = 2400; @@ -992,7 +992,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType aiGenDudeNewState(pSprite, &genDudeBurnGoto); actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth); - gDudeExtra[pSprite->extra].time = PlayClock + 360; + actor->dudeExtra.time = PlayClock + 360; evKill(nSprite, 3, kCallbackFXFlameLick); } @@ -1030,7 +1030,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType if (nDmgType == kDamageTesla) { - DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; + DUDEEXTRA *pDudeExtra = &actor->dudeExtra; pDudeExtra->recoil = 1; } const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater @@ -1055,7 +1055,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType aiNewState(actor, &cultistBurnGoto); aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1); aiPlay3DSound(pSprite, 1031+Random(2), AI_SFX_PRIORITY_2, -1); - gDudeExtra[pSprite->extra].time = PlayClock+360; + actor->dudeExtra.time = PlayClock+360; actHealDude(pXSprite, dudeInfo[40].startHealth, dudeInfo[40].startHealth); evKill(nSprite, 3, kCallbackFXFlameLick); } @@ -1066,16 +1066,16 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType pSprite->type = kDudeBurningInnocent; aiNewState(actor, &cultistBurnGoto); aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1); - gDudeExtra[pSprite->extra].time = PlayClock+360; + actor->dudeExtra.time = PlayClock+360; actHealDude(pXSprite, dudeInfo[39].startHealth, dudeInfo[39].startHealth); evKill(nSprite, 3, kCallbackFXFlameLick); } break; case kDudeBurningCultist: - if (Chance(0x4000) && gDudeExtra[pSprite->extra].time < PlayClock) + if (Chance(0x4000) && actor->dudeExtra.time < PlayClock) { aiPlay3DSound(pSprite, 1031+Random(2), AI_SFX_PRIORITY_2, -1); - gDudeExtra[pSprite->extra].time = PlayClock+360; + actor->dudeExtra.time = PlayClock+360; } if (Chance(0x600) && (pXSprite->medium == kMediumWater || pXSprite->medium == kMediumGoo)) { @@ -1121,7 +1121,7 @@ int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType aiNewState(actor, &cultistBurnGoto); } aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1); - gDudeExtra[pSprite->extra].time = PlayClock+360; + actor->dudeExtra.time = PlayClock+360; actHealDude(pXSprite, dudeInfo[39].startHealth, dudeInfo[39].startHealth); evKill(nSprite, 3, kCallbackFXFlameLick); } @@ -1157,7 +1157,7 @@ void RecoilDude(DBloodActor* actor) auto pXSprite = &actor->x(); auto pSprite = &actor->s(); char v4 = Chance(0x8000); - DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; + DUDEEXTRA *pDudeExtra = &actor->dudeExtra; if (pSprite->statnum == kStatDude && (pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); switch (pSprite->type) { @@ -1573,15 +1573,15 @@ void aiInit(void) void aiInitSprite(spritetype *pSprite) { + auto actor = &bloodActors[pSprite->index]; int nXSprite = pSprite->extra; XSPRITE *pXSprite = &xsprite[nXSprite]; - auto actor = &bloodActors[pXSprite->reference]; int nSector = pSprite->sectnum; int nXSector = sector[nSector].extra; XSECTOR *pXSector = NULL; if (nXSector > 0) pXSector = &xsector[nXSector]; - DUDEEXTRA *pDudeExtra = &gDudeExtra[pSprite->extra]; + DUDEEXTRA *pDudeExtra = &actor->dudeExtra; pDudeExtra->recoil = 0; pDudeExtra->time = 0; @@ -1609,7 +1609,7 @@ void aiInitSprite(spritetype *pSprite) case kDudeCultistTNT: case kDudeCultistBeast: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &cultistIdle); @@ -1617,7 +1617,7 @@ void aiInitSprite(spritetype *pSprite) } case kDudeCultistTommyProne: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &fanaticProneIdle); @@ -1625,21 +1625,21 @@ void aiInitSprite(spritetype *pSprite) } case kDudeCultistShotgunProne: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &cultistProneIdle); break; } case kDudeZombieButcher: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &zombieFIdle); break; } case kDudeZombieAxeNormal: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &zombieAIdle); @@ -1647,7 +1647,7 @@ void aiInitSprite(spritetype *pSprite) } case kDudeZombieAxeLaying: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &zombieSIdle); @@ -1655,7 +1655,7 @@ void aiInitSprite(spritetype *pSprite) break; } case kDudeZombieAxeBuried: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &zombieEIdle); @@ -1663,7 +1663,7 @@ void aiInitSprite(spritetype *pSprite) } case kDudeGargoyleFlesh: case kDudeGargoyleStone: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; @@ -1675,7 +1675,7 @@ void aiInitSprite(spritetype *pSprite) aiNewState(actor, &gargoyleStatueIdle); break; case kDudeCerberusTwoHead: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &cerberusIdle); @@ -1689,7 +1689,7 @@ void aiInitSprite(spritetype *pSprite) break; case kDudePhantasm: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; @@ -1704,7 +1704,7 @@ void aiInitSprite(spritetype *pSprite) break; case kDudeBoneEel: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; @@ -1716,7 +1716,7 @@ void aiInitSprite(spritetype *pSprite) break; case kDudeBat: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval2 = 0; pDudeExtraE->xval3 = 0; pDudeExtraE->xval1 = 0; @@ -1727,7 +1727,7 @@ void aiInitSprite(spritetype *pSprite) case kDudeSpiderRed: case kDudeSpiderBlack: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; @@ -1736,7 +1736,7 @@ void aiInitSprite(spritetype *pSprite) } case kDudeSpiderMother: { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; @@ -1745,7 +1745,7 @@ void aiInitSprite(spritetype *pSprite) } case kDudeTchernobog: { - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[nXSprite].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; pDudeExtraE->xval2 = 0; pDudeExtraE->xval1 = 0; aiNewState(actor, &tchernobogIdle); @@ -1861,45 +1861,4 @@ void aiInitSprite(spritetype *pSprite) } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDEEXTRA* def) -{ - int empty = 0; - char empty2 = 0; - if (arc.isReading()) w = {}; - - if (arc.BeginObject(keyname)) - { - arc("time", w.time, &empty) - ("recoil", w.recoil, &empty) - ("prio", w.prio, &empty) - ("x1", w.at6.u1.xval1, &empty) - ("x2", w.at6.u1.xval2, &empty) - ("x3", w.at6.u1.xval3, &empty2) - .EndObject(); - } - return arc; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void SerializeAI(FSerializer& arc) -{ - if (arc.BeginObject("ai")) - { - arc.SparseArray("dudeextra", gDudeExtra, kMaxSprites, activeXSprites) - .EndObject(); - } -} - - END_BLD_NS diff --git a/source/games/blood/src/ai.h b/source/games/blood/src/ai.h index 8e68301ca..3b6e5b92f 100644 --- a/source/games/blood/src/ai.h +++ b/source/games/blood/src/ai.h @@ -87,7 +87,6 @@ struct TARGETTRACK { }; extern const int dword_138BB0[5]; -extern DUDEEXTRA gDudeExtra[]; bool dudeIsPlayingSeq(spritetype *pSprite, int nSeq); void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4); diff --git a/source/games/blood/src/aibat.cpp b/source/games/blood/src/aibat.cpp index 2eb89ed23..3525eb220 100644 --- a/source/games/blood/src/aibat.cpp +++ b/source/games/blood/src/aibat.cpp @@ -84,7 +84,7 @@ static void batThinkTarget(DBloodActor* actor) auto pSprite = &actor->s(); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; if (pDudeExtraE->xval3 && pDudeExtraE->xval2 < 10) pDudeExtraE->xval2++; else if (pDudeExtraE->xval2 >= 10 && pDudeExtraE->xval3) @@ -433,7 +433,7 @@ void batMoveToCeil(DBloodActor* actor) int nSector = pSprite->sectnum; if (z - pXSprite->targetZ < 0x1000) { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pSprite->flags = 0; aiNewState(actor, &batIdle); diff --git a/source/games/blood/src/aiboneel.cpp b/source/games/blood/src/aiboneel.cpp index 6c09d26de..af24c4699 100644 --- a/source/games/blood/src/aiboneel.cpp +++ b/source/games/blood/src/aiboneel.cpp @@ -95,7 +95,7 @@ static void eelThinkTarget(DBloodActor* actor) auto pSprite = &actor->s(); assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; if (pDudeExtraE->xval3 && pDudeExtraE->xval2 < 10) pDudeExtraE->xval2++; else if (pDudeExtraE->xval2 >= 10 && pDudeExtraE->xval3) @@ -436,7 +436,7 @@ void eelMoveToCeil(DBloodActor* actor) int nSector = pSprite->sectnum; if (z - pXSprite->targetZ < 0x1000) { - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = 0; pSprite->flags = 0; aiNewState(actor, &eelIdle); diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp index 3455c89dc..391031a36 100644 --- a/source/games/blood/src/aicerber.cpp +++ b/source/games/blood/src/aicerber.cpp @@ -266,7 +266,7 @@ static void cerberusThinkTarget(DBloodActor* actor) return; } DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; if (pDudeExtraE->xval3 && pDudeExtraE->xval2 < 10) pDudeExtraE->xval2++; else if (pDudeExtraE->xval2 >= 10 && pDudeExtraE->xval3) diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp index d0ce37bda..23dd564c5 100644 --- a/source/games/blood/src/aigarg.cpp +++ b/source/games/blood/src/aigarg.cpp @@ -215,7 +215,7 @@ static void gargThinkTarget(DBloodActor* actor) return; } DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; if (pDudeExtraE->xval3 && pDudeExtraE->xval2 < 10) pDudeExtraE->xval2++; else if (pDudeExtraE->xval2 >= 10 && pDudeExtraE->xval3) diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp index 2295cbffb..29c457ae6 100644 --- a/source/games/blood/src/aighost.cpp +++ b/source/games/blood/src/aighost.cpp @@ -191,7 +191,7 @@ static void ghostThinkTarget(DBloodActor* actor) return; } DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; if (pDudeExtraE->xval3 && pDudeExtraE->xval2 < 10) pDudeExtraE->xval2++; else if (pDudeExtraE->xval2 >= 10 && pDudeExtraE->xval3) diff --git a/source/games/blood/src/aispid.cpp b/source/games/blood/src/aispid.cpp index ced581fcb..bdf888a7b 100644 --- a/source/games/blood/src/aispid.cpp +++ b/source/games/blood/src/aispid.cpp @@ -146,7 +146,7 @@ void SpidBirthSeqCallback(int, DBloodActor* actor) DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); assert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites); spritetype *pTarget = &sprite[pXSprite->target]; - DUDEEXTRA_at6_u1 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1 *pDudeExtraE = &actor->dudeExtra.at6.u1; int dx = pXSprite->targetX-pSprite->x; int dy = pXSprite->targetY-pSprite->y; int nAngle = getangle(dx, dy); diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp index 17be3e2e5..1be20c9d2 100644 --- a/source/games/blood/src/aitchern.cpp +++ b/source/games/blood/src/aitchern.cpp @@ -233,7 +233,7 @@ static void sub_725A4(DBloodActor* actor) return; } DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - DUDEEXTRA_at6_u2 *pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u2; + DUDEEXTRA_at6_u2 *pDudeExtraE = &actor->dudeExtra.at6.u2; if (pDudeExtraE->xval2 && pDudeExtraE->xval1 < 10) pDudeExtraE->xval1++; else if (pDudeExtraE->xval1 >= 10 && pDudeExtraE->xval2) diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index 4e9ad295f..b09477f54 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -2215,10 +2215,12 @@ void genDudePostDeath(spritetype* pSprite, DAMAGE_TYPE damageType, int damage) { actPostSprite(pSprite->index, kStatThing); } -void aiGenDudeInitSprite(spritetype* pSprite, XSPRITE* pXSprite) { +void aiGenDudeInitSprite(spritetype* pSprite, XSPRITE* pXSprite) +{ + auto actor = &bloodActors[pSprite->index]; switch (pSprite->type) { case kDudeModernCustom: { - DUDEEXTRA_at6_u1* pDudeExtraE = &gDudeExtra[pSprite->extra].at6.u1; + DUDEEXTRA_at6_u1* pDudeExtraE = &actor->dudeExtra.at6.u1; pDudeExtraE->xval3 = pDudeExtraE->xval1 = 0; aiGenDudeNewState(pSprite, &genDudeIdleL); break; diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 79d5d051b..a7cdf3341 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -4,6 +4,8 @@ BEGIN_BLD_NS extern int cumulDamage[kMaxXSprites]; + + // Due to the messed up array storage of all the game data we cannot do any direct references here yet. We have to access everything via wrapper functions for now. // Note that the indexing is very inconsistent - partially by sprite index, partially by xsprite index. class DBloodActor @@ -13,6 +15,7 @@ class DBloodActor public: int dudeSlope; + DUDEEXTRA dudeExtra; DBloodActor() :index(int(this - base())) { /*assert(index >= 0 && index < kMaxSprites);*/ } DBloodActor& operator=(const DBloodActor& other) = default; @@ -20,6 +23,7 @@ public: void Clear() { dudeSlope = 0; + dudeExtra = {}; } bool hasX() { return sprite[index].extra > 0; } void addX() @@ -34,7 +38,6 @@ public: int& zvel() { return Blood::zvel[index]; } int& cumulDamage() { return Blood::cumulDamage[sprite[index].extra]; } - DUDEEXTRA& dudeExtra() { return gDudeExtra[sprite[index].extra]; } SPRITEMASS& spriteMass() { return gSpriteMass[sprite[index].extra]; } GENDUDEEXTRA& genDudeExtra() { return Blood::gGenDudeExtra[index]; } POINT3D& basePoint() { return Blood::baseSprite[index]; } diff --git a/source/games/blood/src/loadsave.cpp b/source/games/blood/src/loadsave.cpp index 7589b0e0e..f5d17b526 100644 --- a/source/games/blood/src/loadsave.cpp +++ b/source/games/blood/src/loadsave.cpp @@ -423,6 +423,32 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTA return arc; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDEEXTRA* def) +{ + int empty = 0; + char empty2 = 0; + if (arc.isReading()) w = {}; + + if (arc.BeginObject(keyname)) + { + arc("time", w.time, &empty) + ("recoil", w.recoil, &empty) + ("prio", w.prio, &empty) + ("x1", w.at6.u1.xval1, &empty) + ("x2", w.at6.u1.xval2, &empty) + ("x3", w.at6.u1.xval3, &empty2) + .EndObject(); + } + return arc; +} + + FSerializer& Serialize(FSerializer& arc, const char* keyname, DBloodActor& w, DBloodActor* def) { static DBloodActor nul; @@ -437,7 +463,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DBloodActor& w, DB // The rest is only relevant if the actor has an xsprite. if (w.s().extra > 0) { - arc("dudeslope", w.dudeSlope, def->dudeSlope); + arc("dudeslope", w.dudeSlope, def->dudeSlope) + ("dudeextra", w.dudeExtra, def->dudeExtra); } arc.EndObject(); } @@ -668,7 +695,6 @@ void SerializeSequences(FSerializer& arc); void SerializeWarp(FSerializer& arc); void SerializeTriggers(FSerializer& arc); void SerializeActor(FSerializer& arc); -void SerializeAI(FSerializer& arc); void SerializeGameStats(FSerializer& arc); void SerializePlayers(FSerializer& arc); void SerializeView(FSerializer& arc); @@ -700,7 +726,6 @@ void GameInterface::SerializeGameState(FSerializer& arc) SerializeState(arc); InitFreeList(nextXSprite, kMaxXSprites, activeXSprites); SerializeActor(arc); - SerializeAI(arc); SerializePlayers(arc); SerializeEvents(arc); SerializeGameStats(arc); diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index d7c97654b..2f5ec7175 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -2985,6 +2985,7 @@ void useSpriteDamager(XSPRITE* pXSource, int objType, int objIndex) { } void damageSprites(XSPRITE* pXSource, spritetype* pSprite) { + auto actor = &bloodActors[pSprite->index]; spritetype* pSource = &sprite[pXSource->reference]; if (!IsDudeSprite(pSprite) || !xspriRangeIsFine(pSprite->extra) || xsprite[pSprite->extra].health <= 0 || pXSource->data3 < 0) return; @@ -3078,7 +3079,7 @@ void damageSprites(XSPRITE* pXSource, spritetype* pSprite) { if (forceRecoil && !pPlayer) { pXSprite->data3 = 32767; - gDudeExtra[pSprite->extra].recoil = (dmgType == kDmgElectric) ? 1 : 0; + actor->dudeExtra.recoil = (dmgType == kDmgElectric) ? 1 : 0; if (pXSprite->aiState->stateType != kAiStateRecoil) RecoilDude(&bloodActors[pXSprite->reference]); } From 8c01c363a92cd0043a5643c39107c938c3662110 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 00:08:51 +0100 Subject: [PATCH 08/49] - replaced remaining access to sprite[] and xsprite[] in processed code. # Conflicts: # source/games/blood/src/actor.cpp # Conflicts: # source/games/blood/src/actor.cpp # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 72 ++++++++++++++--------------- source/games/blood/src/bloodactor.h | 12 +++++ 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 0887f380b..d476c873f 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4349,7 +4349,6 @@ static void checkHit(DBloodActor* actor) { auto actor2 = coll.actor; spritetype* pSprite2 = &actor2->s(); - //XSPRITE *pXSprite2 = &Xsprite[pSprite2->extra]; #ifdef NOONE_EXTENSIONS // add size shroom abilities @@ -4805,13 +4804,16 @@ int MoveThing(DBloodActor* actor) { int nVel = approxDist(actor->xvel(), actor->yvel()); int nVelClipped = ClipHigh(nVel, 0x11111); - if ((floorHit & 0xc000) == 0xc000) + Collision coll(floorHit); + + if (coll.type == kHitSprite) { - int nHitSprite = floorHit & 0x3fff; - if ((sprite[nHitSprite].cstat & 0x30) == 0) + auto hitActor = coll.actor; + auto hitSpr = &hitActor->s(); + if ((hitSpr->cstat & 0x30) == 0) { - actor->xvel() += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); - actor->yvel() += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); + actor->xvel() += MulScale(4, pSprite->x - hitSpr->x, 2); + actor->yvel() += MulScale(4, pSprite->y - hitSpr->y, 2); lhit = actor->hit().hit; } } @@ -4869,7 +4871,7 @@ void MoveDude(DBloodActor *actor) { short bakCstat = pSprite->cstat; pSprite->cstat &= ~257; - actor->hit().hit = ClipMove((int*)&pSprite->x, (int*)&pSprite->y, (int*)&pSprite->z, &nSector, actor->xvel()>>12, actor->yvel()>>12, wd, tz, bz, CLIPMASK0); + actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel()>>12, actor->yvel()>>12, wd, tz, bz, CLIPMASK0); if (nSector == -1) { nSector = pSprite->sectnum; @@ -4922,16 +4924,16 @@ void MoveDude(DBloodActor *actor) { int nHitWall = coll.index; walltype *pHitWall = &wall[nHitWall]; - XWALL *pHitXWall = NULL; - if (pHitWall->extra > 0) - pHitXWall = &xwall[pHitWall->extra]; + XWALL *pHitXWall = nullptr; + if (pHitWall->extra > 0) pHitXWall = &xwall[pHitWall->extra]; + if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) trTriggerWall(nHitWall, pHitXWall, kCmdWallPush); if (pHitWall->nextsector != -1) { sectortype *pHitSector = §or[pHitWall->nextsector]; - XSECTOR *pHitXSector = NULL; + XSECTOR *pHitXSector = nullptr; if (pHitSector->extra > 0) pHitXSector = &xsector[pHitSector->extra]; @@ -4961,13 +4963,13 @@ void MoveDude(DBloodActor *actor) if (nXSector > 0) pXSector = &xsector[nXSector]; else - pXSector = NULL; + pXSector = nullptr; if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); ChangeSpriteSect(pSprite->index, nSector); nXSector = sector[nSector].extra; - pXSector = (nXSector > 0) ? &xsector[nXSector] : NULL; + pXSector = (nXSector > 0) ? &xsector[nXSector] : nullptr; if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) { if (sector[nSector].type == kSectorTeleport) @@ -4977,26 +4979,21 @@ void MoveDude(DBloodActor *actor) nSector = pSprite->sectnum; } - char bUnderwater = 0; - char bDepth = 0; + int bUnderwater = 0; + int bDepth = 0; if (sector[nSector].extra > 0) { XSECTOR *pXSector = &xsector[sector[nSector].extra]; - if (pXSector->Underwater) - bUnderwater = 1; - if (pXSector->Depth) - bDepth = 1; + 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 (actor->zvel()) - pSprite->z += actor->zvel()>>8; + auto pUpperLink = getUpperLink(nSector); + auto pLowerLink = getLowerLink(nSector); + if (pUpperLink && (pUpperLink->s().type == kMarkerUpWater || pUpperLink->s().type == kMarkerUpGoo)) bDepth = 1; + if (pLowerLink && (pLowerLink->s().type == kMarkerLowWater || pLowerLink->s().type == kMarkerLowGoo)) bDepth = 1; + if (pPlayer) wd += 16; + if (actor->zvel()) pSprite->z += actor->zvel()>>8; + int ceilZ, ceilHit, floorZ, floorHit; GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); GetActorExtents(actor, &top, &bottom); @@ -5114,9 +5111,8 @@ void MoveDude(DBloodActor *actor) // look for palette in data2 of marker. If value <= 0, use default ones. if (gModernMap) { pPlayer->nWaterPal = 0; - int nXUpper = sprite[gUpperLink[nSector]].extra; - if (nXUpper >= 0) - pPlayer->nWaterPal = xsprite[nXUpper].data2; + auto pUpper = getUpperLink(nSector); + if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; } #endif @@ -5295,18 +5291,20 @@ void MoveDude(DBloodActor *actor) } else actor->hit().ceilhit = 0; + GetActorExtents(actor,&top,&bottom); pXSprite->height = ClipLow(floorZ-bottom, 0)>>8; if (actor->xvel() || actor->yvel()) { - if ((floorHit & 0xc000) == 0xc000) + Collision coll = floorHit; + if (coll.type == kHitSprite) { - int nHitSprite = floorHit & 0x3fff; - if ((sprite[nHitSprite].cstat & 0x30) == 0) + auto hitAct = coll.actor; + if ((hitAct->s().cstat & 0x30) == 0) { - actor->xvel() += MulScale(4, pSprite->x - sprite[nHitSprite].x, 2); - actor->yvel() += MulScale(4, pSprite->y - sprite[nHitSprite].y, 2); + actor->xvel() += MulScale(4, pSprite->x - hitAct->s().x, 2); + actor->yvel() += MulScale(4, pSprite->y - hitAct->s().y, 2); return; } } diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index a7cdf3341..1fe78d879 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -261,4 +261,16 @@ struct Collision }; +inline DBloodActor* getUpperLink(int sect) +{ + auto l = gUpperLink[sect]; + return l == -1 ? nullptr : &bloodActors[l]; +} + +inline DBloodActor* getLowerLink(int sect) +{ + auto l = gLowerLink[sect]; + return l == -1 ? nullptr : &bloodActors[l]; +} + END_BLD_NS From 29c2e68270eda569de3dd7796a843dd98bf4fa02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 10:40:13 +0100 Subject: [PATCH 09/49] - tabified MoveDude # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 133 ++++++++++++++++--------------- 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index d476c873f..f669d5b24 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4835,24 +4835,24 @@ int MoveThing(DBloodActor* actor) // //--------------------------------------------------------------------------- -void MoveDude(DBloodActor *actor) +void MoveDude(DBloodActor* actor) { auto const pSprite = &actor->s(); auto const pXSprite = &actor->x(); - PLAYER *pPlayer = nullptr; - if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; - if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) + PLAYER* pPlayer = nullptr; + if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; + if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { Printf(PRINT_HIGH, "%d: pSprite->type >= kDudeBase && pSprite->type < kDudeMax", pSprite->type); return; } - DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); + DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); int top, bottom; GetActorExtents(actor, &top, &bottom); - int bz = (bottom-pSprite->z)/4; - int tz = (pSprite->z-top)/4; - int wd = pSprite->clipdist<<2; + int bz = (bottom - pSprite->z) / 4; + int tz = (pSprite->z - top) / 4; + int wd = pSprite->clipdist << 2; int nSector = pSprite->sectnum; int nAiStateType = (pXSprite->aiState) ? pXSprite->aiState->stateType : -1; @@ -4862,8 +4862,8 @@ void MoveDude(DBloodActor *actor) { if (pPlayer && gNoClip) { - pSprite->x += actor->xvel()>>12; - pSprite->y += actor->yvel()>>12; + pSprite->x += actor->xvel() >> 12; + pSprite->y += actor->yvel() >> 12; if (!FindSector(pSprite->x, pSprite->y, &nSector)) nSector = pSprite->sectnum; } @@ -4871,12 +4871,12 @@ void MoveDude(DBloodActor *actor) { short bakCstat = pSprite->cstat; pSprite->cstat &= ~257; - actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel()>>12, actor->yvel()>>12, wd, tz, bz, CLIPMASK0); + actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel() >> 12, actor->yvel() >> 12, wd, tz, bz, CLIPMASK0); if (nSector == -1) { nSector = pSprite->sectnum; if (pSprite->statnum == kStatDude || pSprite->statnum == kStatThing) - actDamageSprite(pSprite->index, pSprite, kDamageFall, 1000<<4); + actDamageSprite(pSprite->index, pSprite, kDamageFall, 1000 << 4); } if (sector[nSector].type >= kSectorPath && sector[nSector].type <= kSectorRotate) @@ -4891,7 +4891,7 @@ void MoveDude(DBloodActor *actor) pSprite->cstat = bakCstat; } Collision coll = actor->hit().hit; - switch (actor->hit().hit&0xc000) + switch (actor->hit().hit & 0xc000) { case kHitSprite: { @@ -4900,20 +4900,20 @@ void MoveDude(DBloodActor *actor) auto Owner = coll.actor->GetOwner(); - if (pHitSprite->statnum == kStatProjectile && !(pHitSprite->flags&32) && actor != Owner) + if (pHitSprite->statnum == kStatProjectile && !(pHitSprite->flags & 32) && actor != Owner) { HITINFO hitInfo = gHitInfo; gHitInfo.hitsprite = pSprite->index; actImpactMissile(actor, 3); gHitInfo = hitInfo; } - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS if (!gModernMap && pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) trTriggerSprite(coll.actor, kCmdSpriteTouch); - #else +#else if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) trTriggerSprite(coll.actor, kCmdSpriteTouch); - #endif +#endif if (pDudeInfo->lockOut && pHitXSprite && pHitXSprite->Push && !pHitXSprite->key && !pHitXSprite->DudeLockout && !pHitXSprite->state && !pHitXSprite->busy && !pPlayer) trTriggerSprite(coll.actor, kCmdSpritePush); @@ -4923,8 +4923,8 @@ void MoveDude(DBloodActor *actor) case kHitWall: { int nHitWall = coll.index; - walltype *pHitWall = &wall[nHitWall]; - XWALL *pHitXWall = nullptr; + walltype* pHitWall = &wall[nHitWall]; + XWALL* pHitXWall = nullptr; if (pHitWall->extra > 0) pHitXWall = &xwall[pHitWall->extra]; if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) @@ -4932,8 +4932,8 @@ void MoveDude(DBloodActor *actor) if (pHitWall->nextsector != -1) { - sectortype *pHitSector = §or[pHitWall->nextsector]; - XSECTOR *pHitXSector = nullptr; + sectortype* pHitSector = §or[pHitWall->nextsector]; + XSECTOR* pHitXSector = nullptr; if (pHitSector->extra > 0) pHitXSector = &xsector[pHitSector->extra]; @@ -4958,7 +4958,7 @@ void MoveDude(DBloodActor *actor) if (pSprite->sectnum != nSector) { assert(nSector >= 0 && nSector < kMaxSectors); - XSECTOR *pXSector; + XSECTOR* pXSector; int nXSector = sector[pSprite->sectnum].extra; if (nXSector > 0) pXSector = &xsector[nXSector]; @@ -4967,10 +4967,10 @@ void MoveDude(DBloodActor *actor) if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); ChangeSpriteSect(pSprite->index, nSector); - + nXSector = sector[nSector].extra; pXSector = (nXSector > 0) ? &xsector[nXSector] : nullptr; - if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) + if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) { if (sector[nSector].type == kSectorTeleport) pXSector->data = pPlayer ? pSprite->index : -1; @@ -4983,7 +4983,7 @@ void MoveDude(DBloodActor *actor) int bDepth = 0; if (sector[nSector].extra > 0) { - XSECTOR *pXSector = &xsector[sector[nSector].extra]; + XSECTOR* pXSector = &xsector[sector[nSector].extra]; if (pXSector->Underwater) bUnderwater = 1; if (pXSector->Depth) bDepth = 1; } @@ -4992,10 +4992,10 @@ void MoveDude(DBloodActor *actor) if (pUpperLink && (pUpperLink->s().type == kMarkerUpWater || pUpperLink->s().type == kMarkerUpGoo)) bDepth = 1; if (pLowerLink && (pLowerLink->s().type == kMarkerLowWater || pLowerLink->s().type == kMarkerLowGoo)) bDepth = 1; if (pPlayer) wd += 16; - if (actor->zvel()) pSprite->z += actor->zvel()>>8; + if (actor->zvel()) pSprite->z += actor->zvel() >> 8; int ceilZ, ceilHit, floorZ, floorHit; - GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); + GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); GetActorExtents(actor, &top, &bottom); if (pSprite->flags & 2) @@ -5007,7 +5007,7 @@ void MoveDude(DBloodActor *actor) { int cz = getceilzofslope(nSector, pSprite->x, pSprite->y); if (cz > top) - vc += ((bottom-cz)*-80099) / (bottom-top); + vc += ((bottom - cz) * -80099) / (bottom - top); else vc = 0; } @@ -5015,7 +5015,7 @@ void MoveDude(DBloodActor *actor) { int fz = getflorzofslope(nSector, pSprite->x, pSprite->y); if (fz < bottom) - vc += ((bottom-fz)*-80099) / (bottom-top); + vc += ((bottom - fz) * -80099) / (bottom - top); } } else @@ -5027,7 +5027,7 @@ void MoveDude(DBloodActor *actor) } if (vc) { - pSprite->z += ((vc*4)/2)>>8; + pSprite->z += ((vc * 4) / 2) >> 8; actor->zvel() += vc; } } @@ -5044,10 +5044,10 @@ void MoveDude(DBloodActor *actor) int nLink = CheckLink(pSprite); if (nLink) { - GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); + GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); if (pPlayer) playerCorrectInertia(pPlayer, &oldpos); - switch (nLink) + switch (nLink) { case kMarkerLowStack: if (pPlayer == gView) @@ -5060,31 +5060,31 @@ void MoveDude(DBloodActor *actor) case kMarkerLowWater: case kMarkerLowGoo: pXSprite->medium = kMediumNormal; - if (pPlayer) + if (pPlayer) { pPlayer->posture = 0; pPlayer->bubbleTime = 0; - if (!pPlayer->cantJump && (pPlayer->input.actions & SB_JUMP)) + if (!pPlayer->cantJump && (pPlayer->input.actions & SB_JUMP)) { actor->zvel() = -0x6aaaa; pPlayer->cantJump = 1; } sfxPlay3DSound(pSprite, 721, -1, 0); - } - else + } + else { - switch (pSprite->type) + switch (pSprite->type) { - case kDudeCultistTommy: - case kDudeCultistShotgun: - aiNewState(&bloodActors[pXSprite->reference], &cultistGoto); - break; - case kDudeGillBeast: - aiNewState(&bloodActors[pXSprite->reference], &gillBeastGoto); - pSprite->flags |= 6; - break; - case kDudeBoneEel: - actKillDude(pSprite->index, pSprite, kDamageFall, 1000<<4); + case kDudeCultistTommy: + case kDudeCultistShotgun: + aiNewState(&bloodActors[pXSprite->reference], &cultistGoto); + break; + case kDudeGillBeast: + aiNewState(&bloodActors[pXSprite->reference], &gillBeastGoto); + pSprite->flags |= 6; + break; + case kDudeBoneEel: + actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); break; } @@ -5098,7 +5098,7 @@ void MoveDude(DBloodActor *actor) case kMarkerUpGoo: { int chance = 0xa00; int medium = kMediumWater; - if (nLink == kMarkerUpGoo){ + if (nLink == kMarkerUpGoo) { medium = kMediumGoo; chance = 0x400; } @@ -5107,9 +5107,10 @@ void MoveDude(DBloodActor *actor) if (pPlayer) { - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS // look for palette in data2 of marker. If value <= 0, use default ones. - if (gModernMap) { + if (gModernMap) + { pPlayer->nWaterPal = 0; auto pUpper = getUpperLink(nSector); if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; @@ -5124,7 +5125,7 @@ void MoveDude(DBloodActor *actor) } else { - switch (pSprite->type) + switch (pSprite->type) { case kDudeCultistTommy: case kDudeCultistShotgun: @@ -5207,7 +5208,7 @@ void MoveDude(DBloodActor *actor) { int floorZ2 = floorZ; int floorHit2 = floorHit; - GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); + GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); if (bottom <= floorZ && pSprite->z - floorZ2 < bz) { floorZ = floorZ2; @@ -5217,8 +5218,8 @@ void MoveDude(DBloodActor *actor) if (floorZ <= bottom) { actor->hit().florhit = floorHit; - pSprite->z += floorZ-bottom; - int v30 = actor->zvel()-velFloor[pSprite->sectnum]; + pSprite->z += floorZ - bottom; + int v30 = actor->zvel() - velFloor[pSprite->sectnum]; if (v30 > 0) { int vax = actFloorBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), (int*)&v30, pSprite->sectnum, 0); @@ -5227,12 +5228,12 @@ void MoveDude(DBloodActor *actor) { pPlayer->fallScream = 0; - if (nDamage > (15<<4) && (pSprite->flags&4)) + if (nDamage > (15 << 4) && (pSprite->flags & 4)) playerLandingSound(pPlayer); - if (nDamage > (30<<4)) + if (nDamage > (30 << 4)) sfxPlay3DSound(pSprite, 701, 0, 0); } - nDamage -= 100<<4; + nDamage -= 100 << 4; if (nDamage > 0) actDamageSprite(actor, actor, kDamageFall, nDamage); actor->zvel() = v30; @@ -5252,7 +5253,7 @@ void MoveDude(DBloodActor *actor) break; case kSurfLava: { - spritetype *pFX = gFX.fxSpawn(FX_10, pSprite->sectnum, pSprite->x, pSprite->y, floorZ, 0); + spritetype* pFX = gFX.fxSpawn(FX_10, pSprite->sectnum, pSprite->x, pSprite->y, floorZ, 0); if (pFX) { for (int i = 0; i < 7; i++) @@ -5278,23 +5279,23 @@ void MoveDude(DBloodActor *actor) { actor->hit().florhit = 0; - if (pSprite->flags&2) + if (pSprite->flags & 2) pSprite->flags |= 4; } if (top <= ceilZ) { actor->hit().ceilhit = ceilHit; - pSprite->z += ClipLow(ceilZ-top, 0); + pSprite->z += ClipLow(ceilZ - top, 0); - if (actor->zvel() <= 0 && (pSprite->flags&4)) + if (actor->zvel() <= 0 && (pSprite->flags & 4)) actor->zvel() = MulScale(-actor->zvel(), 0x2000, 16); } else actor->hit().ceilhit = 0; - GetActorExtents(actor,&top,&bottom); + GetActorExtents(actor, &top, &bottom); - pXSprite->height = ClipLow(floorZ-bottom, 0)>>8; + pXSprite->height = ClipLow(floorZ - bottom, 0) >> 8; if (actor->xvel() || actor->yvel()) { Collision coll = floorHit; @@ -5324,6 +5325,12 @@ void MoveDude(DBloodActor *actor) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + int MoveMissile(spritetype *pSprite) { int nXSprite = pSprite->extra; From ddcb12a8b2a8cf72d2ffbedfada36c06ac10bf30 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 12:17:28 +0100 Subject: [PATCH 10/49] - MoveMissile + actExplodeSprite. # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 359 ++++++++++++++-------------- source/games/blood/src/actor.h | 6 +- source/games/blood/src/nnexts.cpp | 2 +- source/games/blood/src/sfx.cpp | 23 +- source/games/blood/src/sound.h | 8 + source/games/blood/src/triggers.cpp | 8 +- 6 files changed, 196 insertions(+), 210 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index f669d5b24..da33fadee 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4010,12 +4010,12 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) int nDamage = (50 + Random(50)) << 4; actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); } - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); break; case kMissileFlareAlt: sfxKill3DSound(pMissile, -1, -1); - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); break; case kMissileFlareRegular: @@ -4072,7 +4072,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) break; case kMissileFireballCerberus: - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); if (hitCode == 3 && actorHit && actorHit->hasX()) { if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0) @@ -4083,11 +4083,11 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) int nDamage = (25 + Random(10)) << 4; actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); } - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); break; case kMissileFireballTchernobog: - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); if (hitCode == 3 && actorHit && actorHit->hasX()) { if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0) @@ -4098,7 +4098,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode) int nDamage = (25 + Random(10)) << 4; actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); } - actExplodeSprite(pMissile); + actExplodeSprite(missileActor); break; case kMissileEctoSkull: @@ -5331,63 +5331,53 @@ void MoveDude(DBloodActor* actor) // //--------------------------------------------------------------------------- -int MoveMissile(spritetype *pSprite) +int MoveMissile(DBloodActor* actor) { - int nXSprite = pSprite->extra; - XSPRITE *pXSprite = &xsprite[nXSprite]; - int vdi = -1; - spritetype *pOwner = NULL; + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + auto Owner = actor->GetOwner(); + int cliptype = -1; int bakCstat = 0; - if (pSprite->owner >= 0) + spritetype* pOwner = nullptr; + if (Owner && Owner->IsDudeActor()) { - int nOwner = pSprite->owner; - pOwner = &sprite[nOwner]; - if (IsDudeSprite(pOwner)) - { + pOwner = &Owner->s(); bakCstat = pOwner->cstat; pOwner->cstat &= ~257; } - else - pOwner = NULL; - } gHitInfo.hitsect = -1; gHitInfo.hitwall = -1; gHitInfo.hitsprite = -1; - if (pSprite->type == kMissileFlameSpray) - actAirDrag(&bloodActors[pSprite->index], 0x1000); - int nSprite = pSprite->index; - if (pXSprite->target != -1 && (xvel[nSprite] || yvel[nSprite] || zvel[nSprite])) + if (pSprite->type == kMissileFlameSpray) actAirDrag(actor, 0x1000); + + if (pXSprite->target != -1 && (actor->xvel() || actor->yvel() || actor->zvel())) { - spritetype *pTarget = &sprite[pXSprite->target]; - XSPRITE *pXTarget; - if (pTarget->extra > 0) - pXTarget = &xsprite[pTarget->extra]; - else - pXTarget = NULL; + auto target = actor->GetTarget(); + spritetype* pTarget = &target->s(); + XSPRITE* pXTarget = target->hasX() ? &target->x() : nullptr; + if (pTarget->statnum == kStatDude && pXTarget && pXTarget->health > 0) { - int nTargetAngle = getangle(-(pTarget->y-pSprite->y), pTarget->x-pSprite->x); + int nTargetAngle = getangle(-(pTarget->y - pSprite->y), pTarget->x - pSprite->x); int vx = missileInfo[pSprite->type - kMissileBase].velocity; int vy = 0; - RotatePoint(&vx, &vy, (nTargetAngle+1536)&2047, 0, 0); - xvel[nSprite] = vx; - yvel[nSprite] = vy; - int dx = pTarget->x-pSprite->x; - int dy = pTarget->y-pSprite->y; - int dz = pTarget->z-pSprite->z; - // Inlined - int vax = dz/10; - if (pTarget->z < pSprite->z) - vax = -vax; - zvel[nSprite] += vax; - ksqrt(dx*dx+dy*dy+dz*dz); + RotatePoint(&vx, &vy, (nTargetAngle + 1536) & 2047, 0, 0); + actor->xvel() = vx; + actor->yvel() = vy; + int dx = pTarget->x - pSprite->x; + int dy = pTarget->y - pSprite->y; + int dz = pTarget->z - pSprite->z; + + int deltaz = dz / 10; + if (pTarget->z < pSprite->z) deltaz = -deltaz; + actor->zvel() += deltaz; } } - int vx = xvel[nSprite]>>12; - int vy = yvel[nSprite]>>12; - int vz = zvel[nSprite]>>8; + int vx = actor->xvel() >> 12; + int vy = actor->yvel() >> 12; + int vz = actor->zvel() >> 8; int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); int i = 1; const int bakCompat = enginecompatibility_mode; const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) @@ -5404,95 +5394,88 @@ int MoveMissile(spritetype *pSprite) enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy pSprite->cstat &= ~257; // remove self collisions for accurate clipmove } - int vdx = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist<<2, (z-top)/4, (bottom-z)/4, CLIPMASK0); + Collision clipmoveresult = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist << 2, (z - top) / 4, (bottom - z) / 4, CLIPMASK0); enginecompatibility_mode = bakCompat; // restore pSprite->cstat = bakSpriteCstat; clipmoveboxtracenum = 3; short nSector = nSector2; if (nSector2 < 0) { - vdi = -1; + cliptype = -1; break; } - if (vdx) + if (clipmoveresult.type == kHitSprite) { - int nHitSprite = vdx & 0x3fff; - if ((vdx&0xc000) == 0xc000) - { - gHitInfo.hitsprite = nHitSprite; - vdi = 3; + gHitInfo.hitsprite = clipmoveresult.legacyVal; + cliptype = 3; } - else if ((vdx & 0xc000) == 0x8000) + else if (clipmoveresult.type == kHitWall) { - gHitInfo.hitwall = nHitSprite; - if (wall[nHitSprite].nextsector == -1) - vdi = 0; + gHitInfo.hitwall = clipmoveresult.index; + if (wall[clipmoveresult.index].nextsector == -1) cliptype = 0; else { int32_t fz, cz; - getzsofslope(wall[nHitSprite].nextsector, x, y, &cz, &fz); - if (z <= cz || z >= fz) - vdi = 0; - else - vdi = 4; + getzsofslope(wall[clipmoveresult.index].nextsector, x, y, &cz, &fz); + if (z <= cz || z >= fz) cliptype = 0; + else cliptype = 4; } } - } - if (vdi == 4) + if (cliptype == 4) { - walltype *pWall = &wall[gHitInfo.hitwall]; + walltype* pWall = &wall[gHitInfo.hitwall]; if (pWall->extra > 0) { - XWALL *pXWall = &xwall[pWall->extra]; + XWALL* pXWall = &xwall[pWall->extra]; if (pXWall->triggerVector) { trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact); - if (!(pWall->cstat&64)) + if (!(pWall->cstat & 64)) { - vdi = -1; + cliptype = -1; if (i-- > 0) continue; - vdi = 0; + cliptype = 0; break; } } } } - if (vdi >= 0 && vdi != 3) + if (cliptype >= 0 && cliptype != 3) { - int nAngle = getangle(xvel[nSprite], yvel[nSprite]); + int nAngle = getangle(actor->xvel(), actor->yvel()); x -= MulScale(Cos(nAngle), 16, 30); y -= MulScale(Sin(nAngle), 16, 30); - int nVel = approxDist(xvel[nSprite], yvel[nSprite]); - vz -= scale(0x100, zvel[nSprite], nVel); + int nVel = approxDist(actor->xvel(), actor->yvel()); + vz -= scale(0x100, actor->zvel(), nVel); updatesector(x, y, &nSector); nSector2 = nSector; } int ceilZ, ceilHit, floorZ, floorHit; - GetZRangeAtXYZ(x, y, z, nSector2, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0); - GetSpriteExtents(pSprite, &top, &bottom); + GetZRangeAtXYZ(x, y, z, nSector2, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); + GetActorExtents(actor, &top, &bottom); top += vz; bottom += vz; if (bottom >= floorZ) { - gSpriteHit[nXSprite].florhit = floorHit; - vz += floorZ-bottom; - vdi = 2; + actor->hit().florhit = floorHit; + vz += floorZ - bottom; + cliptype = 2; } if (top <= ceilZ) { - gSpriteHit[nXSprite].ceilhit = ceilHit; - vz += ClipLow(ceilZ-top, 0); - vdi = 1; + actor->hit().ceilhit = ceilHit; + vz += ClipLow(ceilZ - top, 0); + cliptype = 1; } pSprite->x = x; pSprite->y = y; - pSprite->z = z+vz; + pSprite->z = z + vz; updatesector(x, y, &nSector); if (nSector >= 0 && nSector != pSprite->sectnum) { assert(nSector >= 0 && nSector < kMaxSectors); - ChangeSpriteSect(nSprite, nSector); + ChangeSpriteSect(pSprite->index, nSector); } CheckLink(pSprite); gHitInfo.hitsect = pSprite->sectnum; @@ -5501,110 +5484,120 @@ int MoveMissile(spritetype *pSprite) gHitInfo.hitz = pSprite->z; break; } - if (pOwner) - pOwner->cstat = bakCstat; - return vdi; + if (pOwner) pOwner->cstat = bakCstat; + + return cliptype; } -void actExplodeSprite(spritetype *pSprite) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void actExplodeSprite(DBloodActor* actor) { - int nXSprite = pSprite->extra; - if (nXSprite <= 0 || nXSprite >= kMaxXSprites) - return; - if (pSprite->statnum == kStatExplosion) - return; + if (!actor->hasX()) return; + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + //auto Owner = actor->GetOwner(); + + if (pSprite->statnum == kStatExplosion) return; sfxKill3DSound(pSprite, -1, -1); evKill(pSprite->index, 3); + int nType = kExplosionStandard; switch (pSprite->type) { case kMissileFireballNapalm: nType = kExplosionNapalm; - seqSpawn(4, 3, nXSprite, -1); - if (Chance(0x8000)) - pSprite->cstat |= 4; + seqSpawn(4, actor, -1); + if (Chance(0x8000)) pSprite->cstat |= 4; sfxPlay3DSound(pSprite, 303, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kMissileFlareAlt: nType = kExplosionFireball; - seqSpawn(9, 3, nXSprite, -1); - if (Chance(0x8000)) - pSprite->cstat |= 4; - sfxPlay3DSound(pSprite, 306, 24+(pSprite->index&3), 1); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + seqSpawn(9, actor, -1); + if (Chance(0x8000)) pSprite->cstat |= 4; + sfxPlay3DSound(pSprite, 306, 24 + (pSprite->index & 3), FX_GlobalChannel); // ouch... + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kMissileFireballCerberus: case kMissileFireballTchernobog: nType = kExplosionFireball; - seqSpawn(5, 3, nXSprite, -1); + seqSpawn(5, actor, -1); sfxPlay3DSound(pSprite, 304, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kThingArmedTNTStick: nType = kExplosionSmall; - if (gSpriteHit[nXSprite].florhit == 0) seqSpawn(4,3,nXSprite,-1); - else seqSpawn(3,3,nXSprite,-1); + if (actor->hit().florhit == 0) seqSpawn(4, actor, -1); + else seqSpawn(3, actor, -1); sfxPlay3DSound(pSprite, 303, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kThingArmedProxBomb: case kThingArmedRemoteBomb: case kThingArmedTNTBundle: - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS case kModernThingTNTProx: - #endif +#endif nType = kExplosionStandard; - if (gSpriteHit[nXSprite].florhit == 0) - seqSpawn(4,3,nXSprite,-1); + if (actor->hit().florhit == 0) seqSpawn(4, actor, -1); else - seqSpawn(3,3,nXSprite,-1); + seqSpawn(3, actor, -1); sfxPlay3DSound(pSprite, 304, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kThingArmedSpray: nType = kExplosionSpray; - seqSpawn(5, 3, nXSprite, -1); + seqSpawn(5, actor, -1); sfxPlay3DSound(pSprite, 307, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; + case kThingTNTBarrel: { - spritetype *pSprite2 = actSpawnSprite_(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); - pSprite2->owner = pSprite->owner; + auto spawned = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); + spawned->SetOwner(actor->GetOwner()); if (actCheckRespawn(pSprite)) { - XSPRITE *pXSprite = &xsprite[nXSprite]; pXSprite->state = 1; - pXSprite->health = thingInfo[0].startHealth<<4; + pXSprite->health = thingInfo[0].startHealth << 4; } - else - actPostSprite(pSprite->index, kStatFree); + else actPostSprite(actor, kStatFree); + nType = kExplosionLarge; - nXSprite = pSprite2->extra; - seqSpawn(4, 3, nXSprite, -1); - sfxPlay3DSound(pSprite2, 305, -1, 0); - GibSprite(pSprite2, GIBTYPE_14, NULL, NULL); - pSprite = pSprite2; + seqSpawn(4, spawned, -1); + actor = spawned; + pSprite = &spawned->s(); + pXSprite = &spawned->x(); + + sfxPlay3DSound(pSprite, 305, -1, 0); + GibSprite(pSprite, GIBTYPE_14, nullptr, nullptr); break; } - case kTrapExploder: + case kTrapExploder: { // Defaults for exploder - nType = 1; int nSnd = 304; int nSeq = 4; + nType = 1; + int nSnd = 304; + int nSeq = 4; - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS // allow to customize hidden exploder trap - if (gModernMap) { - // Temp variables for override via data fields - int tSnd = 0; int tSeq = 0; - - - XSPRITE* pXSPrite = &xsprite[nXSprite]; - nType = pXSPrite->data1; // Explosion type - tSeq = pXSPrite->data2; // SEQ id - tSnd = pXSPrite->data3; // Sound Id + if (gModernMap) + { + nType = pXSprite->data1; // Explosion type + int tSeq = pXSprite->data2; // SEQ id + int tSnd = pXSprite->data3; // Sound Id if (nType <= 1 || nType > kExplodeMax) { nType = 1; nSeq = 4; nSnd = 304; } else if (nType == 2) { nSeq = 4; nSnd = 305; } @@ -5618,77 +5611,73 @@ void actExplodeSprite(spritetype *pSprite) if (tSeq > 0) nSeq = tSeq; if (tSnd > 0) nSnd = tSnd; } - #endif - - if (getSequence(nSeq)) - seqSpawn(nSeq, 3, nXSprite, -1); +#endif + if (getSequence(nSeq)) seqSpawn(nSeq, actor, -1); sfxPlay3DSound(pSprite, nSnd, -1, 0); + break; } - break; case kThingPodFireBall: nType = kExplosionFireball; - seqSpawn(9, 3, nXSprite, -1); + seqSpawn(9, actor, -1); sfxPlay3DSound(pSprite, 307, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); sub_746D4(pSprite, 240); break; + default: nType = kExplosionStandard; - seqSpawn(4, 3, nXSprite, -1); - if (Chance(0x8000)) - pSprite->cstat |= 4; + seqSpawn(4, actor, -1); + if (Chance(0x8000)) pSprite->cstat |= 4; sfxPlay3DSound(pSprite, 303, -1, 0); - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); break; } - int nSprite = pSprite->index; - xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0; - actPostSprite(nSprite, kStatExplosion); + actor->xvel() = actor->yvel() = actor->zvel() = 0; + actPostSprite(actor, kStatExplosion); pSprite->xrepeat = pSprite->yrepeat = explodeInfo[nType].repeat; pSprite->flags &= ~3; pSprite->type = nType; - const EXPLOSION *pExplodeInfo = &explodeInfo[nType]; - xsprite[nXSprite].target = 0; - xsprite[nXSprite].data1 = pExplodeInfo->ticks; - xsprite[nXSprite].data2 = pExplodeInfo->quakeEffect; - xsprite[nXSprite].data3 = pExplodeInfo->flashEffect; + const EXPLOSION* pExplodeInfo = &explodeInfo[nType]; + pXSprite->target = 0; + pXSprite->data1 = pExplodeInfo->ticks; + pXSprite->data2 = pExplodeInfo->quakeEffect; + pXSprite->data3 = pExplodeInfo->flashEffect; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void actActivateGibObject(DBloodActor* actor) { auto pXSprite = &actor->x(); auto pSprite = &actor->s(); - int vdx = ClipRange(pXSprite->data1, 0, 31); - int vc = ClipRange(pXSprite->data2, 0, 31); - int v4 = ClipRange(pXSprite->data3, 0, 31); - int vbp = pXSprite->data4; - int v8 = pXSprite->dropMsg; - if (vdx > 0) - GibSprite(pSprite, (GIBTYPE)(vdx-1), NULL, NULL); - if (vc > 0) - GibSprite(pSprite, (GIBTYPE)(vc-1), NULL, NULL); - if (v4 > 0 && pXSprite->burnTime > 0) - GibSprite(pSprite, (GIBTYPE)(v4-1), NULL, NULL); - if (vbp > 0) - sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, vbp, pSprite->sectnum); - if (v8 > 0) - actDropObject(pSprite, v8); - if (!(pSprite->cstat&32768) && !(pSprite->flags&kHitagRespawn)) - actPostSprite(pSprite->index, kStatFree); + int gib1 = ClipRange(pXSprite->data1, 0, 31); + int gib2 = ClipRange(pXSprite->data2, 0, 31); + int gib3 = ClipRange(pXSprite->data3, 0, 31); + int sound = pXSprite->data4; + int dropmsg = pXSprite->dropMsg; + + if (gib1 > 0) GibSprite(pSprite, (GIBTYPE)(gib1 - 1), nullptr, nullptr); + if (gib2 > 0) GibSprite(pSprite, (GIBTYPE)(gib2 - 1), nullptr, nullptr); + if (gib3 > 0 && pXSprite->burnTime > 0) GibSprite(pSprite, (GIBTYPE)(gib3 - 1), nullptr, nullptr); + if (sound > 0) sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, sound, pSprite->sectnum); + if (dropmsg > 0) actDropObject(pSprite, dropmsg); + + if (!(pSprite->cstat & 32768) && !(pSprite->flags & kHitagRespawn)) + actPostSprite(actor, kStatFree); } -bool IsUnderWater(spritetype *pSprite) -{ - int nSector = pSprite->sectnum; - int nXSector = sector[nSector].extra; - if (nXSector > 0 && nXSector < kMaxXSectors) - if (xsector[nXSector].Underwater) - return 1; - return 0; -} +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- void MakeSplash(DBloodActor *actor); @@ -5922,7 +5911,7 @@ void actProcessSprites(void) if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096)) break; assert(nObject >= 0 && nObject < kMaxSprites); - actExplodeSprite(pSprite); + actExplodeSprite(&bloodActors[pSprite->index]); break; } } @@ -5939,7 +5928,7 @@ void actProcessSprites(void) if (pSprite->flags & 32) continue; viewBackupSpriteLoc(nSprite, pSprite); - int hit = MoveMissile(pSprite); + int hit = MoveMissile(&bloodActors[nSprite]); if (hit >= 0) actImpactMissile(&bloodActors[pSprite->index], hit); } diff --git a/source/games/blood/src/actor.h b/source/games/blood/src/actor.h index 7dfed1524..73942d377 100644 --- a/source/games/blood/src/actor.h +++ b/source/games/blood/src/actor.h @@ -229,12 +229,8 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4); int actDamageSprite(DBloodActor* pSource, DBloodActor* pTarget, DAMAGE_TYPE damageType, int damage); void actHitcodeToData(int a1, HITINFO *pHitInfo, DBloodActor **actor, walltype **a7 = nullptr); void actAirDrag(DBloodActor *pSprite, int a2); -int MoveThing(spritetype *pSprite); -void MoveDude(spritetype *pSprite); -int MoveMissile(spritetype *pSprite); -void actExplodeSprite(spritetype *pSprite); +void actExplodeSprite(DBloodActor *pSprite); void actActivateGibObject(DBloodActor *actor); -bool IsUnderWater(spritetype *pSprite); void actProcessSprites(void); spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6); DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6); diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 2f5ec7175..c8539a6ec 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -5042,7 +5042,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite pXSprite->Proximity = 1; break; default: - actExplodeSprite(pSprite); + actExplodeSprite(&bloodActors[pSprite->index]); break; } } diff --git a/source/games/blood/src/sfx.cpp b/source/games/blood/src/sfx.cpp index f1dd417a6..8e0bdc95f 100644 --- a/source/games/blood/src/sfx.cpp +++ b/source/games/blood/src/sfx.cpp @@ -169,14 +169,7 @@ void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector) if (chan) chan->UserData = nSector; } -enum EPlayFlags -{ - FX_GlobalChannel = 1, - FX_SoundMatch = 2, - FX_ChannelMatch = 4, -}; - -void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume) +void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int playchannel, int playflags, int pitch, int volume) { if (!SoundEnabled() || soundId < 0 || !pSprite) return; auto sid = soundEngine->FindSoundByResID(soundId); @@ -188,17 +181,17 @@ void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitc sid = getSfx(sid, attenuation, pitch, volume); if (volume == -1) volume = 80; - if (a3 >= 0) + if (playchannel >= 0) { - a3++; // This is to make 0 a valid channel value. + playchannel++; // This is to make 0 a valid channel value. if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int { if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business. - if (chan->EntChannel == a3 && (chan->Source == pSprite || (a4 & FX_GlobalChannel) != 0)) + if (chan->EntChannel == playchannel && (chan->Source == pSprite || (playflags & FX_GlobalChannel) != 0)) { - if ((a4 & FX_ChannelMatch) != 0 && chan->EntChannel == a3) + if ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel) return true; - if ((a4 & FX_SoundMatch) != 0 && chan->OrgID == sid) + if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid) return true; soundEngine->StopChannel(chan); return -1; @@ -209,10 +202,10 @@ void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitc } auto sfx = soundEngine->GetSfx(sid); - EChanFlags flags = a3 == -1 ? CHANF_OVERLAP : CHANF_NONE; + EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE; if (sfx && sfx->LoopStart >= 0) flags |= CHANF_LOOP; - soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, a3, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f); + soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, playchannel, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f); } void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4) diff --git a/source/games/blood/src/sound.h b/source/games/blood/src/sound.h index 7b7659e2f..1d4845e7b 100644 --- a/source/games/blood/src/sound.h +++ b/source/games/blood/src/sound.h @@ -62,4 +62,12 @@ void ambProcess(void); void ambKillAll(void); void ambInit(void); +enum EPlayFlags +{ + FX_GlobalChannel = 1, + FX_SoundMatch = 2, + FX_ChannelMatch = 4, +}; + + END_BLD_NS diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index e535f9552..ade5acbcf 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -495,7 +495,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event) case kThingArmedTNTStick: case kThingArmedTNTBundle: case kThingArmedSpray: - actExplodeSprite(pSprite); + actExplodeSprite(&bloodActors[pSprite->index]); break; case kTrapExploder: switch (event.cmd) { @@ -504,13 +504,13 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event) break; default: pSprite->cstat &= (unsigned short)~CSTAT_SPRITE_INVISIBLE; - actExplodeSprite(pSprite); + actExplodeSprite(&bloodActors[pSprite->index]); break; } break; case kThingArmedRemoteBomb: if (pSprite->statnum != kStatRespawn) { - if (event.cmd != kCmdOn) actExplodeSprite(pSprite); + if (event.cmd != kCmdOn) actExplodeSprite(&bloodActors[pSprite->index]); else { sfxPlay3DSound(pSprite, 454, 0, 0); evPost(nSprite, 3, 18, kCmdOff); @@ -531,7 +531,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event) pXSprite->Proximity = 1; break; default: - actExplodeSprite(pSprite); + actExplodeSprite(&bloodActors[pSprite->index]); break; } } From 7faebdcbf13eb4a46aea68d0d67140547bf3154a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 12:54:26 +0100 Subject: [PATCH 11/49] - first two loops of actProcessSprites split off and redone. # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 272 ++++++++++++++-------------- source/games/blood/src/bloodactor.h | 5 + source/games/blood/src/view.h | 2 + 3 files changed, 140 insertions(+), 139 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index da33fadee..803781f4e 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5679,28 +5679,19 @@ void actActivateGibObject(DBloodActor* actor) // //--------------------------------------------------------------------------- -void MakeSplash(DBloodActor *actor); - -void actProcessSprites(void) +static void actCheckProximity() { - int nSprite; - int nNextSprite; - - #ifdef NOONE_EXTENSIONS - if (gModernMap) nnExtProcessSuperSprites(); - #endif + BloodStatIterator it(kStatThing); + while (auto actor = it.Next()) + { + spritetype* pSprite = &actor->s(); + if (pSprite->flags & 32) continue; - StatIterator it(kStatThing); - while ((nSprite = it.NextIndex()) >= 0) + if (actor->hasX()) { - spritetype *pSprite = &sprite[nSprite]; - - if (pSprite->flags&32) - continue; - int nXSprite = pSprite->extra; - if (nXSprite > 0) { - XSPRITE *pXSprite = &xsprite[nXSprite]; - switch (pSprite->type) { + XSPRITE* pXSprite = &actor->x(); + switch (pSprite->type) + { case kThingBloodBits: case kThingBloodChunks: case kThingZombieHead: @@ -5710,96 +5701,108 @@ void actProcessSprites(void) if (pXSprite->burnTime > 0) { - pXSprite->burnTime = ClipLow(pXSprite->burnTime-4,0); - actDamageSprite(pXSprite->burnSource, pSprite, kDamageBurn, 8); + pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0); + actDamageSprite(actor->GetBurnSource(), actor, kDamageFall, 8); } - - if (pXSprite->Proximity) { - #ifdef NOONE_EXTENSIONS + + if (pXSprite->Proximity) + { +#ifdef NOONE_EXTENSIONS // don't process locked or 1-shot things for proximity - if (gModernMap && (pXSprite->locked || pXSprite->isTriggered)) + if (gModernMap && (pXSprite->locked || pXSprite->isTriggered)) continue; - #endif - +#endif + if (pSprite->type == kThingDroppedLifeLeech) pXSprite->target = -1; - int nSprite2; - StatIterator it1(kStatDude); - while ((nSprite2 = it1.NextIndex()) >= 0) + BloodStatIterator it1(kStatDude); + while (auto dudeactor = it1.Next()) { - nNextSprite = it1.PeekIndex(); - spritetype *pSprite2 = &sprite[nSprite2]; + auto nextdude = it1.Peek(); + spritetype* pSprite2 = &dudeactor->s(); - if (pSprite2->flags&32) continue; - XSPRITE *pXSprite2 = &xsprite[pSprite2->extra]; - if ((unsigned int)pXSprite2->health > 0) { - - #ifdef NOONE_EXTENSIONS + if (pSprite2->flags & 32 || !dudeactor->hasX()) continue; + + XSPRITE* pXSprite2 = &dudeactor->x(); + if ((unsigned int)pXSprite2->health > 0) + { + int proxyDist = 96; +#ifdef NOONE_EXTENSIONS // allow dudeLockout for proximity flag - if (gModernMap && pSprite->type != kThingDroppedLifeLeech && pXSprite->DudeLockout && !IsPlayerSprite(pSprite2)) + if (gModernMap && pSprite->type != kThingDroppedLifeLeech && pXSprite->DudeLockout && !dudeactor->IsPlayerActor()) continue; - #endif - int proxyDist = 96; - #ifdef NOONE_EXTENSIONS if (pSprite->type == kModernThingEnemyLifeLeech) proxyDist = 512; - #endif - if (pSprite->type == kThingDroppedLifeLeech && pXSprite->target == -1) { - int nOwner = pSprite->owner; - spritetype *pOwner = &sprite[nOwner]; - if (!IsPlayerSprite(pOwner)) - continue; - PLAYER *pPlayer = &gPlayer[pOwner->type - kDudePlayer1]; - PLAYER *pPlayer2 = NULL; - if (IsPlayerSprite(pSprite2)) - pPlayer2 = &gPlayer[pSprite2->type - kDudePlayer1]; - if (nSprite2 == nOwner || pSprite2->type == kDudeZombieAxeBuried || pSprite2->type == kDudeRat || pSprite2->type == kDudeBat) - continue; - if (gGameOptions.nGameType == 3 && pPlayer2 && pPlayer->teamId == pPlayer2->teamId) - continue; - if (gGameOptions.nGameType == 1 && pPlayer2) - continue; +#endif + if (pSprite->type == kThingDroppedLifeLeech && pXSprite->target == -1) + { + auto Owner = actor->GetOwner(); + if (!Owner->IsPlayerActor()) continue; + + spritetype* pOwner = &Owner->s(); + PLAYER* pPlayer = &gPlayer[pOwner->type - kDudePlayer1]; + PLAYER* pPlayer2 = dudeactor->IsPlayerActor() ? &gPlayer[pSprite2->type - kDudePlayer1] : nullptr; + + if (dudeactor == Owner || pSprite2->type == kDudeZombieAxeBuried || pSprite2->type == kDudeRat || pSprite2->type == kDudeBat) continue; + if (gGameOptions.nGameType == 3 && pPlayer2 && pPlayer->teamId == pPlayer2->teamId) continue; + if (gGameOptions.nGameType == 1 && pPlayer2) continue; proxyDist = 512; } - - if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, proxyDist)) { - switch (pSprite->type) { + if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, proxyDist)) + { + switch (pSprite->type) + { case kThingDroppedLifeLeech: - if (!Chance(0x4000) && nNextSprite >= 0) continue; + if (!Chance(0x4000) && nextdude) continue; if (pSprite2->cstat & CLIPMASK0) pXSprite->target = pSprite2->index; else continue; break; - #ifdef NOONE_EXTENSIONS + +#ifdef NOONE_EXTENSIONS case kModernThingTNTProx: - if (!IsPlayerSprite(pSprite2)) continue; + if (!dudeactor->IsPlayerActor()) continue; pSprite->pal = 0; break; + case kModernThingEnemyLifeLeech: if (pXSprite->target != pSprite2->index) continue; break; - #endif +#endif + + default: + break; } if (pSprite->owner == -1) pSprite->owner = pSprite2->index; - trTriggerSprite(nSprite, pXSprite, kCmdSpriteProximity); + trTriggerSprite(actor, kCmdSpriteProximity); } } } } } } +} - it.Reset(kStatThing); - while ((nSprite = it.NextIndex()) >= 0) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void actCheckThings() +{ + BloodStatIterator it(kStatThing); + while (auto actor = it.Next()) { - spritetype *pSprite = &sprite[nSprite]; + spritetype* pSprite = &actor->s(); - if (pSprite->flags & 32) - continue; + if (pSprite->flags & 32) continue; + if (!actor->hasX()) continue; + + auto pXSprite = &actor->x(); int nSector = pSprite->sectnum; - int nXSprite = pSprite->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); + int nXSector = sector[nSector].extra; - XSECTOR *pXSector = NULL; + XSECTOR* pXSector = NULL; if (nXSector > 0) { assert(nXSector > 0 && nXSector < kMaxXSectors); @@ -5809,22 +5812,18 @@ void actProcessSprites(void) if (pXSector && pXSector->panVel && (pXSector->panAlways || pXSector->state || pXSector->busy)) { int nType = pSprite->type - kThingBase; - const THINGINFO *pThingInfo = &thingInfo[nType]; - if (pThingInfo->flags & 1) - - pSprite->flags |= 1; - if (pThingInfo->flags & 2) - - pSprite->flags |= 4; + const THINGINFO* pThingInfo = &thingInfo[nType]; + if (pThingInfo->flags & 1) pSprite->flags |= 1; + if (pThingInfo->flags & 2) pSprite->flags |= 4; } - if (pSprite->flags&3) + if (pSprite->flags & 3) { - viewBackupSpriteLoc(nSprite, pSprite); + viewBackupSpriteLoc(actor); if (pXSector && pXSector->panVel) { int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= bottom) { int angle = pXSector->panAngle; @@ -5832,95 +5831,91 @@ void actProcessSprites(void) if (pXSector->panAlways || pXSector->state || pXSector->busy) { speed = pXSector->panVel << 9; - if (!pXSector->panAlways && pXSector->busy) - speed = MulScale(speed, pXSector->busy, 16); + if (!pXSector->panAlways && pXSector->busy) speed = MulScale(speed, pXSector->busy, 16); } - if (sector[nSector].floorstat&64) - angle = (angle+GetWallAngle(sector[nSector].wallptr)+512)&2047; - int dx = MulScale(speed, Cos(angle), 30); - int dy = MulScale(speed, Sin(angle), 30); - xvel[nSprite] += dx; - yvel[nSprite] += dy; + if (sector[nSector].floorstat & 64) angle = (angle + GetWallAngle(sector[nSector].wallptr) + 512) & 2047; + + actor->xvel() += MulScale(speed, Cos(angle), 30); + actor->yvel() += MulScale(speed, Sin(angle), 30); } } - actAirDrag(&bloodActors[pSprite->index], 128); + actAirDrag(actor, 128); - if (((pSprite->index>>8)&15) == (gFrameCount&15) && (pSprite->flags&2)) - pSprite->flags |= 4; - if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || - velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) + if (((pSprite->index >> 8) & 15) == (gFrameCount & 15) && (pSprite->flags & 2)) pSprite->flags |= 4; + if ((pSprite->flags & 4) || actor->xvel() || actor->yvel() || actor->zvel() || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) { - int hit = MoveThing(&bloodActors[pSprite->index]); - if (hit) + Collision hit = MoveThing(actor); + if (hit.type) { - int nXSprite = pSprite->extra; - if (nXSprite) + if (pXSprite->Impact) trTriggerSprite(actor, kCmdOff); + + switch (pSprite->type) { - XSPRITE *pXSprite = &xsprite[nXSprite]; - if (pXSprite->Impact) - trTriggerSprite(nSprite, pXSprite, kCmdOff); - switch (pSprite->type) { case kThingDripWater: case kThingDripBlood: MakeSplash(&bloodActors[pXSprite->reference]); break; - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS case kModernThingThrowableRock: - seqSpawn(24, 3, nXSprite, -1); - if ((hit & 0xc000) == 0xc000) + seqSpawn(24, actor, -1); + if (hit.type = kHitSprite) { pSprite->xrepeat = 32; pSprite->yrepeat = 32; - int nObject = hit & 0x3fff; - assert(nObject >= 0 && nObject < kMaxSprites); - spritetype * pObject = &sprite[nObject]; - actDamageSprite(pSprite->owner, pObject, kDamageFall, pXSprite->data1); + actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, pXSprite->data1); } break; - #endif +#endif case kThingBone: - seqSpawn(24, 3, nXSprite, -1); - if ((hit&0xc000) == 0xc000) + seqSpawn(24, actor, -1); + if (hit.type = kHitSprite) { - int nObject = hit & 0x3fff; - assert(nObject >= 0 && nObject < kMaxSprites); - spritetype *pObject = &sprite[nObject]; - actDamageSprite(pSprite->owner, pObject, kDamageFall, 12); + actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); } break; + case kThingPodGreenBall: - if ((hit&0xc000) == 0x4000) + if (hit.type == kHitSector) { - actRadiusDamage(&bloodActors[pSprite->owner], pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, kDamageExplode, 6, 0); - evPost(pSprite->index, 3, 0, kCallbackFXPodBloodSplat); + actRadiusDamage(actor->GetOwner(), pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, kDamageExplode, 6, 0); + evPost(actor, 0, kCallbackFXPodBloodSplat); } - else + else if (hit.type == kHitSprite) { - int nObject = hit & 0x3fff; - if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096)) - break; - assert(nObject >= 0 && nObject < kMaxSprites); - spritetype *pObject = &sprite[nObject]; - actDamageSprite(pSprite->owner, pObject, kDamageFall, 12); - evPost(pSprite->index, 3, 0, kCallbackFXPodBloodSplat); + actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); + evPost(actor, 0, kCallbackFXPodBloodSplat); } break; + case kThingPodFireBall: - { - int nObject = hit & 0x3fff; - if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096)) + if (hit.type == kHitSprite) actExplodeSprite(actor); break; - assert(nObject >= 0 && nObject < kMaxSprites); - actExplodeSprite(&bloodActors[pSprite->index]); - break; } } } } } - } - } - it.Reset(kStatProjectile); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void MakeSplash(DBloodActor *actor); + +void actProcessSprites(void) +{ + #ifdef NOONE_EXTENSIONS + if (gModernMap) nnExtProcessSuperSprites(); + #endif + + actCheckProximity(); + actCheckThings(); + + int nSprite; + BloodStatIterator it(kStatProjectile); while ((nSprite = it.NextIndex()) >= 0) { spritetype *pSprite = &sprite[nSprite]; @@ -6201,7 +6196,6 @@ void actProcessSprites(void) StatIterator it1(kStatDude); while ((nSprite2 = it1.NextIndex()) >= 0) { - nNextSprite = it1.PeekIndex(); spritetype *pSprite2 = &sprite[nSprite2]; if (pSprite2->flags&32) diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 1fe78d879..0a150bab9 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -273,4 +273,9 @@ inline DBloodActor* getLowerLink(int sect) return l == -1 ? nullptr : &bloodActors[l]; } +inline void viewBackupSpriteLoc(DBloodActor* actor) +{ + viewBackupSpriteLoc(actor->s().index, &actor->s()); +} + END_BLD_NS diff --git a/source/games/blood/src/view.h b/source/games/blood/src/view.h index b3d55e111..aefecfdb4 100644 --- a/source/games/blood/src/view.h +++ b/source/games/blood/src/view.h @@ -177,4 +177,6 @@ inline void viewBackupSpriteLoc(int nSprite, spritetype *pSprite) } } +void viewBackupSpriteLoc(DBloodActor* actor); + END_BLD_NS From 2cfb4f908eaf8504c2a9e54174101e623cc9e04d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 16:23:01 +0100 Subject: [PATCH 12/49] - actProcessSprites done. # Conflicts: # source/games/blood/src/actor.cpp # Conflicts: # source/games/blood/src/actor.cpp # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 456 +++++++++++++++++-------------- source/games/blood/src/seq.cpp | 5 + source/games/blood/src/seq.h | 1 + 3 files changed, 258 insertions(+), 204 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 803781f4e..e92630513 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5903,167 +5903,165 @@ static void actCheckThings() // //--------------------------------------------------------------------------- -void MakeSplash(DBloodActor *actor); - -void actProcessSprites(void) +static void actCheckProjectiles() { - #ifdef NOONE_EXTENSIONS - if (gModernMap) nnExtProcessSuperSprites(); - #endif - - actCheckProximity(); - actCheckThings(); - - int nSprite; BloodStatIterator it(kStatProjectile); - while ((nSprite = it.NextIndex()) >= 0) + while (auto actor = it.Next()) { - spritetype *pSprite = &sprite[nSprite]; + spritetype* pSprite = &actor->s(); if (pSprite->flags & 32) continue; - viewBackupSpriteLoc(nSprite, pSprite); - int hit = MoveMissile(&bloodActors[nSprite]); - if (hit >= 0) - actImpactMissile(&bloodActors[pSprite->index], hit); + viewBackupSpriteLoc(actor); + int hit = MoveMissile(actor); + if (hit >= 0) actImpactMissile(&bloodActors[pSprite->index], hit); } - it.Reset(kStatExplosion); - while ((nSprite = it.NextIndex()) >= 0) +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void actCheckExplosion() +{ + BloodStatIterator it(kStatExplosion); + while (auto actor = it.Next()) { - uint8_t sectmap[(kMaxSectors+7)>>3]; - spritetype *pSprite = &sprite[nSprite]; + spritetype* pSprite = &actor->s(); if (pSprite->flags & 32) continue; - int nOwner = pSprite->owner; - auto pOwner = nOwner == -1? nullptr : &bloodActors[pSprite->owner]; + + if (!actor->hasX()) continue; + XSPRITE* pXSprite = &actor->x(); + + auto Owner = actor->GetOwner(); + auto pOwner = Owner ? &Owner->s() : nullptr; int nType = pSprite->type; assert(nType >= 0 && nType < kExplodeMax); - const EXPLOSION *pExplodeInfo = &explodeInfo[nType]; - int nXSprite = pSprite->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); - XSPRITE *pXSprite = &xsprite[nXSprite]; + const EXPLOSION* pExplodeInfo = &explodeInfo[nType]; int x = pSprite->x; int y = pSprite->y; int z = pSprite->z; int nSector = pSprite->sectnum; int radius = pExplodeInfo->radius; - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS // Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor // or of Hidden Exploder. if (gModernMap && pXSprite->data4 > 0) radius = pXSprite->data4; - #endif +#endif + + uint8_t sectormap[(kMaxSectors + 7) >> 3]; // GetClosestSpriteSectors() has issues checking some sectors due to optimizations // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions // so only allow this new checking method for dude spawned explosions short gAffectedXWalls[kMaxXWalls]; const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic - GetClosestSpriteSectors(nSector, x, y, radius, sectmap, gAffectedXWalls, newSectCheckMethod); + GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod); for (int i = 0; i < kMaxXWalls; i++) { int nWall = gAffectedXWalls[i]; if (nWall == -1) break; - XWALL *pXWall = &xwall[wall[nWall].extra]; + XWALL* pXWall = &xwall[wall[nWall].extra]; trTriggerWall(nWall, pXWall, kCmdWallImpact); } - - int nSprite2; - StatIterator it1(kStatDude); - while ((nSprite2 = it1.NextIndex()) >= 0) - { - DBloodActor* act2 = &bloodActors[nSprite2]; - spritetype *pDude = &act2->s(); - if (pDude->flags & 32) - continue; - if (TestBitString(sectmap, pDude->sectnum)) + BloodStatIterator it1(kStatDude); + while (auto dudeactor = it1.Next()) + { + spritetype* pDude = &dudeactor->s(); + + if (pDude->flags & 32) continue; + + if (TestBitString(sectormap, pDude->sectnum)) { if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius)) { if (pExplodeInfo->dmg && pXSprite->target == 0) { pXSprite->target = 1; - actDamageSprite(nOwner, pDude, kDamageFall, (pExplodeInfo->dmg+Random(pExplodeInfo->dmgRng))<<4); + actDamageSprite(Owner, dudeactor, kDamageFall, (pExplodeInfo->dmg + Random(pExplodeInfo->dmgRng)) << 4); } - if (pExplodeInfo->dmgType) - ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType); + if (pExplodeInfo->dmgType) ConcussSprite(actor, dudeactor, x, y, z, pExplodeInfo->dmgType); + if (pExplodeInfo->burnTime) { - assert(pDude->extra > 0 && pDude->extra < kMaxXSprites); - XSPRITE *pXDude = &xsprite[pDude->extra]; - if (!pXDude->burnTime) - evPost(nSprite2, 3, 0, kCallbackFXFlameLick); - actBurnSprite(pSprite->owner, pXDude, pExplodeInfo->burnTime<<2); + assert(dudeactor->hasX()); + XSPRITE* pXDude = &xsprite[pDude->extra]; + if (!pXDude->burnTime) evPost(dudeactor, 0, kCallbackFXFlameLick); + actBurnSprite(Owner, dudeactor, pExplodeInfo->burnTime << 2); } } } } - - it1.Reset(kStatThing); - while ((nSprite2 = it1.NextIndex()) >= 0) - { - auto act2 = &bloodActors[nSprite2]; - spritetype *pThing = &sprite[nSprite2]; - if (pThing->flags & 32) - continue; - if (TestBitString(sectmap, pThing->sectnum)) + it1.Reset(kStatThing); + while (auto thingactor = it1.Next()) + { + spritetype* pThing = &thingactor->s(); + + if (pThing->flags & 32) continue; + + if (TestBitString(sectormap, pThing->sectnum)) { - if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius)) + if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius) && thingactor->hasX()) { - XSPRITE *pXSprite2 = &xsprite[pThing->extra]; - if (!pXSprite2->locked) + XSPRITE* pXThing = &thingactor->x(); + if (!pXThing->locked) { - if (pExplodeInfo->dmgType) - ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType); + if (pExplodeInfo->dmgType) ConcussSprite(Owner, thingactor, x, y, z, pExplodeInfo->dmgType); + if (pExplodeInfo->burnTime) { - assert(pThing->extra > 0 && pThing->extra < kMaxXSprites); - XSPRITE *pXThing = &xsprite[pThing->extra]; if (pThing->type == kThingTNTBarrel && !pXThing->burnTime) - evPost(nSprite2, 3, 0, kCallbackFXFlameLick); - actBurnSprite(pSprite->owner, pXThing, pExplodeInfo->burnTime<<2); + evPost(thingactor, 0, kCallbackFXFlameLick); + actBurnSprite(Owner, thingactor, pExplodeInfo->burnTime << 2); } } } } } - + for (int p = connecthead; p >= 0; p = connectpoint2[p]) { - spritetype *pSprite2 = gPlayer[p].pSprite; - int dx = (x - pSprite2->x)>>4; - int dy = (y - pSprite2->y)>>4; - int dz = (z - pSprite2->z)>>8; - int nDist = dx*dx+dy*dy+dz*dz+0x40000; + spritetype* pSprite2 = gPlayer[p].pSprite; + int dx = (x - pSprite2->x) >> 4; + int dy = (y - pSprite2->y) >> 4; + int dz = (z - pSprite2->z) >> 8; + int nDist = dx * dx + dy * dy + dz * dz + 0x40000; int t = DivScale(pXSprite->data2, nDist, 16); gPlayer[p].flickerEffect += t; } - #ifdef NOONE_EXTENSIONS - if (pXSprite->data1 != 0) { - +#ifdef NOONE_EXTENSIONS + if (pXSprite->data1 != 0) + { // add impulse for sprites from physics list - if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0) { - for (int i = 0; i < gPhysSpritesCount; i++) { + if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0) + { + for (int i = 0; i < gPhysSpritesCount; i++) + { if (gPhysSpritesList[i] == -1) continue; - else if (sprite[gPhysSpritesList[i]].sectnum < 0 || (sprite[gPhysSpritesList[i]].flags & kHitagFree) != 0) - continue; + auto physactor = &bloodActors[gPhysSpritesList[i]]; + spritetype* pDebris = &physactor->s(); + if (pDebris->sectnum < 0 || (pDebris->flags & kHitagFree) != 0) continue; - spritetype* pDebris = &sprite[gPhysSpritesList[i]]; - if (!TestBitString(sectmap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; - else debrisConcuss(nOwner, i, x, y, z, pExplodeInfo->dmgType); + if (!TestBitString(sectormap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; + else debrisConcuss(Owner ? Owner->s().index : -1, i, x, y, z, pExplodeInfo->dmgType); } } // trigger sprites from impact list if (gImpactSpritesCount > 0) { - for (int i = 0; i < gImpactSpritesCount; i++) { + for (int i = 0; i < gImpactSpritesCount; i++) + { if (gImpactSpritesList[i] == -1) continue; else if (sprite[gImpactSpritesList[i]].sectnum < 0 || (sprite[gImpactSpritesList[i]].flags & kHitagFree) != 0) continue; @@ -6072,87 +6070,105 @@ void actProcessSprites(void) if (pImpact->extra <= 0) continue; XSPRITE* pXImpact = &xsprite[pImpact->extra]; - if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectmap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) + if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) continue; - + trTriggerSprite(pImpact->index, pXImpact, kCmdSpriteImpact); } } } - - if (!gModernMap || !(pSprite->flags & kModernTypeFlag1)) { - // if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually - // via sprite statnum 2. + + if (!gModernMap || !(pSprite->flags & kModernTypeFlag1)) + { + // if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually via sprite statnum 2. pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); } - #else +#else pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); - #endif +#endif - if (pXSprite->data1 == 0 && pXSprite->data2 == 0 && pXSprite->data3 == 0 && seqGetStatus(3, nXSprite) < 0) - actPostSprite(nSprite, kStatFree); + if (pXSprite->data1 == 0 && pXSprite->data2 == 0 && pXSprite->data3 == 0 && seqGetStatus(actor) < 0) + actPostSprite(actor, kStatFree); } - - it.Reset(kStatTraps); - while ((nSprite = it.NextIndex()) >= 0) - { - spritetype *pSprite = &sprite[nSprite]; +} - if (pSprite->flags & 32) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void actCheckTraps() +{ + BloodStatIterator it(kStatTraps); + while (auto actor = it.Next()) + { + spritetype* pSprite = &actor->s(); + + if ((pSprite->flags & 32) || !actor->hasX()) continue; - int nXSprite = pSprite->extra; - //assert(nXSprite > 0 && nXSprite < kMaxXSprites); - if (nXSprite <= 0 || nXSprite >= kMaxXSprites) - continue; - XSPRITE *pXSprite = &xsprite[nXSprite]; + + XSPRITE* pXSprite = &actor->x(); switch (pSprite->type) { case kTrapSawCircular: - pXSprite->data2 = ClipLow(pXSprite->data2-4, 0); + pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); break; + case kTrapFlame: - if (pXSprite->state && seqGetStatus(3, nXSprite) < 0) { + if (pXSprite->state && seqGetStatus(actor) < 0) + { int x = pSprite->x; int y = pSprite->y; int z = pSprite->z; - int t = (pXSprite->data1<<23)/120; + int t = (pXSprite->data1 << 23) / 120; int dx = MulScale(t, Cos(pSprite->ang), 30); int dy = MulScale(t, Sin(pSprite->ang), 30); for (int i = 0; i < 2; i++) { - spritetype *pFX = gFX.fxSpawn(FX_32, pSprite->sectnum, x, y, z, 0); + auto pFX = gFX.fxSpawnActor(FX_32, pSprite->sectnum, x, y, z, 0); if (pFX) { - xvel[pFX->index] = dx + Random2(0x8888); - yvel[pFX->index] = dy + Random2(0x8888); - zvel[pFX->index] = Random2(0x8888); + pFX->xvel() = dx + Random2(0x8888); + pFX->yvel() = dy + Random2(0x8888); + pFX->zvel() = Random2(0x8888); } - x += (dx/2)>>12; - y += (dy/2)>>12; + x += (dx / 2) >> 12; + y += (dy / 2) >> 12; } dy = SinScale16(pSprite->ang); dx = CosScale16(pSprite->ang); - gVectorData[kVectorTchernobogBurn].maxDist = pXSprite->data1<<9; + gVectorData[kVectorTchernobogBurn].maxDist = pXSprite->data1 << 9; actFireVector(pSprite, 0, 0, dx, dy, Random2(0x8888), kVectorTchernobogBurn); } break; } } - it.Reset(kStatDude); - while ((nSprite = it.NextIndex()) >= 0) +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void actCheckDudes() +{ + BloodStatIterator it(kStatDude); + while (auto actor = it.Next()) { - spritetype *pSprite = &sprite[nSprite]; + spritetype* pSprite = &actor->s(); if (pSprite->flags & 32) continue; - int nXSprite = pSprite->extra; - if (nXSprite > 0) + + if (actor->hasX()) { - XSPRITE *pXSprite = &xsprite[nXSprite]; + XSPRITE* pXSprite = &actor->x(); const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick if ((pXSprite->burnTime > 0) || fixBurnGlitch) { @@ -6162,104 +6178,105 @@ void actProcessSprites(void) case kDudeBurningCultist: case kDudeBurningZombieAxe: case kDudeBurningZombieButcher: - actDamageSprite(pXSprite->burnSource, pSprite, kDamageBurn, 8); + actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8); break; + default: - pXSprite->burnTime = ClipLow(pXSprite->burnTime-4, 0); - actDamageSprite(pXSprite->burnSource, pSprite, kDamageBurn, 8); + pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0); + actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8); break; } } - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS // handle incarnations of custom dude - if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->sysData1 == kGenDudeTransformStatus) { - xvel[pSprite->index] = yvel[pSprite->index] = 0; - if (seqGetStatus(3, nXSprite) < 0) - genDudeTransform(pSprite); + if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->sysData1 == kGenDudeTransformStatus) + { + actor->xvel() = actor->yvel() = 0; + if (seqGetStatus(actor) < 0) genDudeTransform(pSprite); } - #endif +#endif if (pSprite->type == kDudeCerberusTwoHead) { - if (pXSprite->health <= 0 && seqGetStatus(3, nXSprite) < 0) + if (pXSprite->health <= 0 && seqGetStatus(actor) < 0) { - pXSprite->health = dudeInfo[28].startHealth<<4; + pXSprite->health = dudeInfo[28].startHealth << 4; pSprite->type = kDudeCerberusOneHead; - if (pXSprite->target != -1) - aiSetTarget(pXSprite, pXSprite->target); - aiActivateDude(&bloodActors[pXSprite->reference]); + if (pXSprite->target != -1) aiSetTarget(pXSprite, pXSprite->target); + aiActivateDude(actor); } } if (pXSprite->Proximity && !pXSprite->isTriggered) { - int nSprite2; - StatIterator it1(kStatDude); - while ((nSprite2 = it1.NextIndex()) >= 0) + BloodStatIterator it1(kStatDude); + while (auto actor2 = it1.Next()) { - spritetype *pSprite2 = &sprite[nSprite2]; + spritetype* pSprite2 = &actor->s(); + if (pSprite2->flags & 32) continue; - if (pSprite2->flags&32) - continue; - XSPRITE *pXSprite2 = &xsprite[pSprite2->extra]; - if ((unsigned int)pXSprite2->health > 0 && IsPlayerSprite(pSprite2)) { + XSPRITE* pXSprite2 = &actor->x(); + + if ((unsigned int)pXSprite2->health > 0 && IsPlayerSprite(pSprite2)) + { if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128)) - trTriggerSprite(nSprite, pXSprite, kCmdSpriteProximity); + trTriggerSprite(actor, kCmdSpriteProximity); } } } - if (IsPlayerSprite(pSprite)) + if (actor->IsPlayerActor()) { - PLAYER *pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; - if (pPlayer->voodooTargets) - voodooTarget(pPlayer); - if (pPlayer->hand && Chance(0x8000)) - actDamageSprite(nSprite, pSprite, kDamageDrown, 12); + PLAYER* pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; + if (pPlayer->voodooTargets) voodooTarget(pPlayer); + if (pPlayer->hand && Chance(0x8000)) actDamageSprite(actor, actor, kDamageDrown, 12); + if (pPlayer->isUnderwater) { char bActive = packItemActive(pPlayer, 1); - if (bActive || pPlayer->godMode) - pPlayer->underwaterTime = 1200; - else - pPlayer->underwaterTime = ClipLow(pPlayer->underwaterTime-4, 0); + + if (bActive || pPlayer->godMode) pPlayer->underwaterTime = 1200; + else pPlayer->underwaterTime = ClipLow(pPlayer->underwaterTime - 4, 0); + if (pPlayer->underwaterTime < 1080 && packCheckItem(pPlayer, 1) && !bActive) packUseItem(pPlayer, 1); + if (!pPlayer->underwaterTime) { pPlayer->chokeEffect += 4; if (Chance(pPlayer->chokeEffect)) - actDamageSprite(nSprite, pSprite, kDamageDrown, 3<<4); + actDamageSprite(actor, actor, kDamageDrown, 3 << 4); } else pPlayer->chokeEffect = 0; - if (xvel[nSprite] || yvel[nSprite]) + + if (actor->xvel() || actor->yvel()) sfxPlay3DSound(pSprite, 709, 100, 2); - pPlayer->bubbleTime = ClipLow(pPlayer->bubbleTime-4, 0); + + pPlayer->bubbleTime = ClipLow(pPlayer->bubbleTime - 4, 0); } else if (gGameOptions.nGameType == 0) { if (pPlayer->pXSprite->health > 0 && pPlayer->restTime >= 1200 && Chance(0x200)) { pPlayer->restTime = -1; - sfxPlay3DSound(pSprite, 3100+Random(11), 0, 2); + sfxPlay3DSound(pSprite, 3100 + Random(11), 0, 2); } } } - ProcessTouchObjects(&bloodActors[pSprite->index]); + ProcessTouchObjects(actor); } } - it.Reset(kStatDude); - while ((nSprite = it.NextIndex()) >= 0) - { - spritetype *pSprite = &sprite[nSprite]; - if (pSprite->flags & 32) - continue; - int nXSprite = pSprite->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); + it.Reset(kStatDude); + while (auto actor = it.Next()) + { + spritetype* pSprite = &actor->s(); + if (pSprite->flags & 32 || !actor->hasX()) continue; + int nSector = pSprite->sectnum; - viewBackupSpriteLoc(nSprite, pSprite); + viewBackupSpriteLoc(actor); int nXSector = sector[nSector].extra; - XSECTOR *pXSector = NULL; + XSECTOR* pXSector = NULL; + if (nXSector > 0) { assert(nXSector > 0 && nXSector < kMaxXSectors); @@ -6269,7 +6286,7 @@ void actProcessSprites(void) if (pXSector) { int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); + GetActorExtents(actor, &top, &bottom); if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= bottom) { int angle = pXSector->panAngle; @@ -6280,64 +6297,95 @@ void actProcessSprites(void) if (!pXSector->panAlways && pXSector->busy) speed = MulScale(speed, pXSector->busy, 16); } - if (sector[nSector].floorstat&64) - angle = (angle+GetWallAngle(sector[nSector].wallptr)+512)&2047; + if (sector[nSector].floorstat & 64) + angle = (angle + GetWallAngle(sector[nSector].wallptr) + 512) & 2047; int dx = MulScale(speed, Cos(angle), 30); int dy = MulScale(speed, Sin(angle), 30); - xvel[nSprite] += dx; - yvel[nSprite] += dy; + actor->xvel() += dx; + actor->yvel() += dy; } } - if (pXSector && pXSector->Underwater) - actAirDrag(&bloodActors[pSprite->index], 5376); - else - actAirDrag(&bloodActors[pSprite->index], 128); + if (pXSector && pXSector->Underwater) actAirDrag(actor, 5376); + else actAirDrag(actor, 128); - if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || - velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) - MoveDude(&bloodActors[pSprite->index]); + if ((pSprite->flags & 4) || actor->xvel() || actor->yvel() || actor->zvel() || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) + MoveDude(actor); } - it.Reset(kStatFlare); - while ((nSprite = it.NextIndex()) >= 0) - { - spritetype *pSprite = &sprite[nSprite]; +} - if (pSprite->flags & 32) - continue; - int nXSprite = pSprite->extra; - assert(nXSprite > 0 && nXSprite < kMaxXSprites); - XSPRITE *pXSprite = &xsprite[nXSprite]; - int nTarget = pXSprite->target; - assert(nTarget >= 0); - viewBackupSpriteLoc(nSprite, pSprite); - assert(nTarget < kMaxSprites); - spritetype *pTarget = &sprite[nTarget]; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void actCheckFlares() +{ + BloodStatIterator it(kStatFlare); + while (auto actor = it.Next()) + { + spritetype* pSprite = &actor->s(); + if ((pSprite->flags & 32) || !actor->hasX()) continue; + + XSPRITE* pXSprite = &actor->x(); + auto target = actor->GetTarget(); + if (!target) continue; + + viewBackupSpriteLoc(actor); + spritetype* pTarget = &target->s(); if (pTarget->statnum == kMaxStatus) { GibSprite(pSprite, GIBTYPE_17, NULL, NULL); - actPostSprite(pSprite->index, kStatFree); + actPostSprite(actor, kStatFree); } if (pTarget->extra > 0 && xsprite[pTarget->extra].health > 0) { - int x = pTarget->x+mulscale30r(Cos(pXSprite->goalAng+pTarget->ang), pTarget->clipdist*2); - int y = pTarget->y+mulscale30r(Sin(pXSprite->goalAng+pTarget->ang), pTarget->clipdist*2); - int z = pTarget->z+pXSprite->targetZ; + int x = pTarget->x + mulscale30r(Cos(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); + int y = pTarget->y + mulscale30r(Sin(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); + int z = pTarget->z + pXSprite->targetZ; vec3_t pos = { x, y, z }; - setsprite(nSprite,&pos); - xvel[nSprite] = xvel[nTarget]; - yvel[nSprite] = yvel[nTarget]; - zvel[nSprite] = zvel[nTarget]; + setsprite(pSprite->index, &pos); + actor->xvel() = target->xvel(); + actor->yvel() = target->yvel(); + actor->zvel() = target->zvel(); } else { GibSprite(pSprite, GIBTYPE_17, NULL, NULL); - actPostSprite(pSprite->index, kStatFree); + actPostSprite(actor, kStatFree); } } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void actProcessSprites(void) +{ +#ifdef NOONE_EXTENSIONS + if (gModernMap) nnExtProcessSuperSprites(); +#endif + + actCheckProximity(); + actCheckThings(); + actCheckProjectiles(); + actCheckExplosion(); + actCheckTraps(); + actCheckDudes(); + actCheckFlares(); aiProcessDudes(); gFX.fxProcess(); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6) { int nSprite = InsertSprite(nSector, nStat); diff --git a/source/games/blood/src/seq.cpp b/source/games/blood/src/seq.cpp index 0bf150b03..c886849b0 100644 --- a/source/games/blood/src/seq.cpp +++ b/source/games/blood/src/seq.cpp @@ -482,6 +482,11 @@ SEQINST* GetInstance(DBloodActor* actor) return activeList.get(3, actor->s().index); } +int seqGetStatus(DBloodActor* actor) +{ + return seqGetStatus(3, actor->s().index); +} + void seqKill(int type, int nXIndex) { activeList.remove(type, nXIndex); diff --git a/source/games/blood/src/seq.h b/source/games/blood/src/seq.h index 66031819f..3d547e9ef 100644 --- a/source/games/blood/src/seq.h +++ b/source/games/blood/src/seq.h @@ -107,6 +107,7 @@ void seqKill(int a1, int a2); void seqKill(DBloodActor* actor); void seqKillAll(void); int seqGetStatus(int a1, int a2); +int seqGetStatus(DBloodActor*); int seqGetID(int a1, int a2); void seqProcess(int a1); From ebdb4927cccd246a4c2bf1be6930084b2f52cfb9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Aug 2021 14:32:32 +0200 Subject: [PATCH 13/49] - got rid of a few sprite/xsprite references. # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index e92630513..89c64d72d 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5994,7 +5994,7 @@ static void actCheckExplosion() if (pExplodeInfo->burnTime) { assert(dudeactor->hasX()); - XSPRITE* pXDude = &xsprite[pDude->extra]; + XSPRITE* pXDude = &dudeactor->x(); if (!pXDude->burnTime) evPost(dudeactor, 0, kCallbackFXFlameLick); actBurnSprite(Owner, dudeactor, pExplodeInfo->burnTime << 2); } @@ -6063,17 +6063,18 @@ static void actCheckExplosion() for (int i = 0; i < gImpactSpritesCount; i++) { if (gImpactSpritesList[i] == -1) continue; - else if (sprite[gImpactSpritesList[i]].sectnum < 0 || (sprite[gImpactSpritesList[i]].flags & kHitagFree) != 0) + auto impactactor = &bloodActors[gImpactSpritesList[i]]; + auto impactsprite = &impactactor->s(); + if (impactsprite->sectnum < 0 || (impactsprite->flags & kHitagFree) != 0) continue; - spritetype* pImpact = &sprite[gImpactSpritesList[i]]; - if (pImpact->extra <= 0) + if (impactsprite->extra <= 0) continue; - XSPRITE* pXImpact = &xsprite[pImpact->extra]; - if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) + XSPRITE* pXImpact = &impactactor->x(); + if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, impactsprite->sectnum) || !CheckProximity(impactsprite, x, y, z, nSector, radius)) continue; - trTriggerSprite(pImpact->index, pXImpact, kCmdSpriteImpact); + trTriggerSprite(impactsprite->index, pXImpact, kCmdSpriteImpact); } } @@ -6333,12 +6334,13 @@ void actCheckFlares() viewBackupSpriteLoc(actor); spritetype* pTarget = &target->s(); + auto pXTarget = target->hasX()? &target->x() : nullptr; if (pTarget->statnum == kMaxStatus) { GibSprite(pSprite, GIBTYPE_17, NULL, NULL); actPostSprite(actor, kStatFree); } - if (pTarget->extra > 0 && xsprite[pTarget->extra].health > 0) + if (pXTarget && pXTarget->health > 0) { int x = pTarget->x + mulscale30r(Cos(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); int y = pTarget->y + mulscale30r(Sin(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); From ac40e86ab2bb4a07cb3b3045df3635859d078b06 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 5 Dec 2020 17:24:27 +0100 Subject: [PATCH 14/49] - actSpawnSprite # Conflicts: # source/games/blood/src/actor.cpp # Conflicts: # source/games/blood/src/actor.cpp --- source/games/blood/src/actor.cpp | 44 ++++++++++++++-------------- source/games/blood/src/actor.h | 1 - source/games/blood/src/aiunicult.cpp | 6 ++-- source/games/blood/src/bloodactor.h | 5 ++++ source/games/blood/src/fx.cpp | 3 +- source/games/blood/src/player.cpp | 3 +- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 89c64d72d..01b1cb57c 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2779,7 +2779,7 @@ static DBloodActor* actSpawnFloor(DBloodActor* actor) int y = pSprite->y; updatesector(x, y, §or); int zFloor = getflorzofslope(sector, x, y); - auto* spawned = actSpawnSprite(sector, x, y, zFloor, 3, 0); + auto spawned = actSpawnSprite(sector, x, y, zFloor, 3, 0); if (spawned) spawned->s().cstat &= ~257; return spawned; } @@ -6388,42 +6388,40 @@ void actProcessSprites(void) // //--------------------------------------------------------------------------- -spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6) +DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool setextra) { int nSprite = InsertSprite(nSector, nStat); - if (nSprite >= 0) - sprite[nSprite].extra = -1; + if (nSprite >= 0) sprite[nSprite].extra = -1; else { - StatIterator it(kStatPurge); + BloodStatIterator it(kStatPurge); nSprite = it.NextIndex(); assert(nSprite >= 0); assert(nSector >= 0 && nSector < kMaxSectors); ChangeSpriteSect(nSprite, nSector); actPostSprite(nSprite, nStat); } + DBloodActor* actor = &bloodActors[nSprite]; + vec3_t pos = { x, y, z }; setsprite(nSprite, &pos); - spritetype *pSprite = &sprite[nSprite]; + spritetype* pSprite = &actor->s(); pSprite->type = kSpriteDecoration; - if (a6 && pSprite->extra == -1) + if (setextra && !actor->hasX()) { - int nXSprite = dbInsertXSprite(nSprite); - gSpriteHit[nXSprite].florhit = 0; - gSpriteHit[nXSprite].ceilhit = 0; - if (!VanillaMode()) - xsprite[nXSprite].target = -1; + actor->addExtra(); + actor->hit().florhit = 0; + actor->hit().ceilhit = 0; + if (!VanillaMode()) actor->SetTarget(nullptr); } - return pSprite; + return actor; } -DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6) -{ - auto spr = actSpawnSprite_(nSector, x, y, z, nStat, a6); - return &bloodActors[spr->index]; -} - -spritetype * actSpawnSprite(spritetype *pSource, int nStat); +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- spritetype *actSpawnDude(spritetype *pSource, short nType, int a3, int a4) { @@ -6520,7 +6518,8 @@ spritetype * actSpawnSprite(spritetype *pSource, int nStat) spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType) { assert(nThingType >= kThingBase && nThingType < kThingMax); - spritetype *pSprite = actSpawnSprite_(nSector, x, y, z, 4, 1); + auto actor = actSpawnSprite(nSector, x, y, z, 4, 1); + spritetype* pSprite = &actor->s(); int nType = nThingType-kThingBase; int nThing = pSprite->index; int nXThing = pSprite->extra; @@ -6661,7 +6660,8 @@ spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5, y = gHitInfo.hity-MulScale(pMissileInfo->clipDist<<1, Sin(pSprite->ang), 28); } } - spritetype *pMissile = actSpawnSprite_(pSprite->sectnum, x, y, z, 5, 1); + auto actor = actSpawnSprite(pSprite->sectnum, x, y, z, 5, 1); + spritetype* pMissile = &actor->s(); int nMissile = pMissile->index; show2dsprite.Set(nMissile); pMissile->type = nType; diff --git a/source/games/blood/src/actor.h b/source/games/blood/src/actor.h index 73942d377..6bd3b4206 100644 --- a/source/games/blood/src/actor.h +++ b/source/games/blood/src/actor.h @@ -232,7 +232,6 @@ void actAirDrag(DBloodActor *pSprite, int a2); void actExplodeSprite(DBloodActor *pSprite); void actActivateGibObject(DBloodActor *actor); void actProcessSprites(void); -spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6); DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6); spritetype *actSpawnDude(spritetype *pSource, short nType, int a3, int a4); spritetype * actSpawnSprite(spritetype *pSource, int nStat); diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index b09477f54..ee73a3014 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -1593,8 +1593,10 @@ void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT event) } } -bool doExplosion(spritetype* pSprite, int nType) { - spritetype* pExplosion = actSpawnSprite_(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, kStatExplosion, true); +bool doExplosion(spritetype* pSprite, int nType) +{ + auto actor = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, kStatExplosion, true); + spritetype* pExplosion = &actor->s(); if (pExplosion->extra < 0 || pExplosion->extra >= kMaxXSprites) return false; diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 0a150bab9..338fc8c24 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -128,6 +128,11 @@ public: } } + void addExtra() + { + if (s().extra <= 0) s().extra = dbInsertXSprite(index); + } + }; extern DBloodActor bloodActors[kMaxSprites]; diff --git a/source/games/blood/src/fx.cpp b/source/games/blood/src/fx.cpp index 5db463572..34bf2a367 100644 --- a/source/games/blood/src/fx.cpp +++ b/source/games/blood/src/fx.cpp @@ -165,7 +165,8 @@ spritetype * CFX::fxSpawn(FX_ID nFx, int nSector, int x, int y, int z, unsigned return NULL; destroy(nSprite); } - spritetype *pSprite = actSpawnSprite_(nSector, x, y, z, 1, 0); + auto actor = actSpawnSprite(nSector, x, y, z, 1, 0); + spritetype* pSprite = &actor->s(); pSprite->type = nFx; pSprite->picnum = pFX->picnum; pSprite->cstat |= pFX->cstat; diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index c0b0b7ca4..c524aa521 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -660,7 +660,8 @@ void playerStart(int nPlayer, int bNewLevel) pStartZone = &gStartZone[Random(8)]; } - spritetype *pSprite = actSpawnSprite_(pStartZone->sectnum, pStartZone->x, pStartZone->y, pStartZone->z, 6, 1); + auto actor = actSpawnSprite(pStartZone->sectnum, pStartZone->x, pStartZone->y, pStartZone->z, 6, 1); + spritetype* pSprite = &actor->s(); assert(pSprite->extra > 0 && pSprite->extra < kMaxXSprites); XSPRITE *pXSprite = &xsprite[pSprite->extra]; pPlayer->pSprite = pSprite; From 0e7c61dc333a07ca6d43a9f859ea6770c39e91da Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 23 Aug 2021 19:21:41 +0200 Subject: [PATCH 15/49] - tabified code. --- source/games/blood/src/actor.cpp | 1870 +++++++++++++++--------------- 1 file changed, 935 insertions(+), 935 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 01b1cb57c..1084ce51f 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4601,22 +4601,22 @@ void actAirDrag(DBloodActor* actor, int a2) int wind_x = 0; int wind_y = 0; - int nSector = pSprite->sectnum; - assert(nSector >= 0 && nSector < kMaxSectors); + int nSector = pSprite->sectnum; + assert(nSector >= 0 && nSector < kMaxSectors); sectortype* pSector = §or[nSector]; - int nXSector = pSector->extra; - if (nXSector > 0) - { - assert(nXSector < kMaxXSectors); + int nXSector = pSector->extra; + if (nXSector > 0) + { + assert(nXSector < kMaxXSectors); XSECTOR* pXSector = &xsector[nXSector]; - if (pXSector->windVel && (pXSector->windAlways || pXSector->busy)) - { + if (pXSector->windVel && (pXSector->windAlways || pXSector->busy)) + { int wind = pXSector->windVel << 12; if (!pXSector->windAlways && pXSector->busy) wind = MulScale(wind, pXSector->busy, 16); wind_x = MulScale(wind, Cos(pXSector->windAng), 30); wind_y = MulScale(wind, Sin(pXSector->windAng), 30); - } - } + } + } actor->xvel() += MulScale(wind_x - actor->xvel(), a2, 16); actor->yvel() += MulScale(wind_y - actor->yvel(), a2, 16); actor->zvel() -= MulScale(actor->zvel(), a2, 16); @@ -4634,29 +4634,29 @@ int MoveThing(DBloodActor* actor) assert(actor->hasX()); XSPRITE* pXSprite = &actor->x(); int lhit = 0; - assert(pSprite->type >= kThingBase && pSprite->type < kThingMax); + assert(pSprite->type >= kThingBase && pSprite->type < kThingMax); const THINGINFO* pThingInfo = &thingInfo[pSprite->type - kThingBase]; - int nSector = pSprite->sectnum; - assert(nSector >= 0 && nSector < kMaxSectors); - int top, bottom; + int nSector = pSprite->sectnum; + assert(nSector >= 0 && nSector < kMaxSectors); + int top, bottom; GetActorExtents(actor, &top, &bottom); - const int bakCompat = enginecompatibility_mode; + const int bakCompat = enginecompatibility_mode; if (actor->xvel() || actor->yvel()) - { - short bakCstat = pSprite->cstat; - pSprite->cstat &= ~257; - if ((pSprite->owner >= 0) && !cl_bloodvanillaexplosions && !VanillaMode()) - enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy + { + short bakCstat = pSprite->cstat; + pSprite->cstat &= ~257; + if ((pSprite->owner >= 0) && !cl_bloodvanillaexplosions && !VanillaMode()) + enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy lhit = actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel() >> 12, actor->yvel() >> 12, pSprite->clipdist << 2, (pSprite->z - top) / 4, (bottom - pSprite->z) / 4, CLIPMASK0); - enginecompatibility_mode = bakCompat; // restore - pSprite->cstat = bakCstat; - assert(nSector >= 0); - if (pSprite->sectnum != nSector) - { - assert(nSector >= 0 && nSector < kMaxSectors); + enginecompatibility_mode = bakCompat; // restore + pSprite->cstat = bakCstat; + assert(nSector >= 0); + if (pSprite->sectnum != nSector) + { + assert(nSector >= 0 && nSector < kMaxSectors); ChangeSpriteSect(pSprite->index, nSector); - } + } Collision coll(actor->hit().hit); if (coll.type == kHitWall) @@ -4665,165 +4665,165 @@ int MoveThing(DBloodActor* actor) actWallBounceVector(&actor->xvel(), &actor->yvel(), nHitWall, pThingInfo->elastic); switch (pSprite->type) { - case kThingZombieHead: - sfxPlay3DSound(pSprite, 607, 0, 0); + case kThingZombieHead: + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - break; + break; - case kThingKickablePail: - sfxPlay3DSound(pSprite, 374, 0, 0); - break; - } - } - } - else - { - assert(nSector >= 0 && nSector < kMaxSectors); - FindSector(pSprite->x, pSprite->y, pSprite->z, &nSector); - } + case kThingKickablePail: + sfxPlay3DSound(pSprite, 374, 0, 0); + break; + } + } + } + else + { + assert(nSector >= 0 && nSector < kMaxSectors); + FindSector(pSprite->x, pSprite->y, pSprite->z, &nSector); + } pSprite->z += actor->zvel() >> 8; - int ceilZ, ceilHit, floorZ, floorHit; + int ceilZ, ceilHit, floorZ, floorHit; GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); GetActorExtents(actor, &top, &bottom); - if ((pSprite->flags & 2) && bottom < floorZ) - { - pSprite->z += 455; + if ((pSprite->flags & 2) && bottom < floorZ) + { + pSprite->z += 455; actor->zvel() += 58254; - if (pSprite->type == kThingZombieHead) - { + if (pSprite->type == kThingZombieHead) + { auto* fxActor = gFX.fxSpawnActor(FX_27, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0); if (fxActor) - { + { int v34 = (PlayClock * 3) & 2047; int v30 = (PlayClock * 5) & 2047; int vbx = (PlayClock * 11) & 2047; - int v2c = 0x44444; - int v28 = 0; - int v24 = 0; + int v2c = 0x44444; + int v28 = 0; + int v24 = 0; RotateVector(&v2c, &v28, vbx); RotateVector(&v2c, &v24, v30); RotateVector(&v28, &v24, v34); fxActor->xvel() = actor->xvel() + v2c; fxActor->yvel() = actor->yvel() + v28; fxActor->zvel() = actor->zvel() + v24; - } - } - } + } + } + } if (CheckLink(pSprite)) GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); GetActorExtents(actor, &top, &bottom); - if (bottom >= floorZ) - { + if (bottom >= floorZ) + { actTouchFloor(actor, pSprite->sectnum); actor->hit().florhit = floorHit; pSprite->z += floorZ - bottom; int v20 = actor->zvel() - velFloor[pSprite->sectnum]; - if (v20 > 0) - { + if (v20 > 0) + { - pSprite->flags |= 4; + pSprite->flags |= 4; int vax = actFloorBounceVector(&actor->xvel(), &actor->yvel(), (int*)&v20, pSprite->sectnum, pThingInfo->elastic); int nDamage = MulScale(vax, vax, 30) - pThingInfo->dmgResist; if (nDamage > 0) actDamageSprite(actor, actor, kDamageFall, nDamage); actor->zvel() = v20; if (velFloor[pSprite->sectnum] == 0 && abs(actor->zvel()) < 0x10000) - { + { actor->zvel() = 0; - pSprite->flags &= ~4; - } + pSprite->flags &= ~4; + } switch (pSprite->type) { - case kThingNapalmBall: + case kThingNapalmBall: if (actor->zvel() == 0 || Chance(0xA000)) actNapalmMove(actor); - break; + break; - case kThingZombieHead: + case kThingZombieHead: if (abs(actor->zvel()) > 0x80000) { - sfxPlay3DSound(pSprite, 607, 0, 0); + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - } - break; + } + break; - case kThingKickablePail: + case kThingKickablePail: if (abs(actor->zvel()) > 0x80000) - sfxPlay3DSound(pSprite, 374, 0, 0); - break; - } + sfxPlay3DSound(pSprite, 374, 0, 0); + break; + } lhit = kHitSector | nSector; - } + } else if (actor->zvel() == 0) - pSprite->flags &= ~4; - } - else - { + pSprite->flags &= ~4; + } + else + { actor->hit().florhit = 0; if (pSprite->flags & 2) - pSprite->flags |= 4; - } + pSprite->flags |= 4; + } - if (top <= ceilZ) - { + if (top <= ceilZ) + { actor->hit().ceilhit = ceilHit; pSprite->z += ClipLow(ceilZ - top, 0); if (actor->zvel() < 0) - { + { actor->xvel() = MulScale(actor->xvel(), 0xc000, 16); actor->yvel() = MulScale(actor->yvel(), 0xc000, 16); actor->zvel() = MulScale(-actor->zvel(), 0x4000, 16); switch (pSprite->type) { - case kThingZombieHead: + case kThingZombieHead: if (abs(actor->zvel()) > 0x80000) { - sfxPlay3DSound(pSprite, 607, 0, 0); + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - } - break; + } + break; - case kThingKickablePail: + case kThingKickablePail: if (abs(actor->zvel()) > 0x80000) - sfxPlay3DSound(pSprite, 374, 0, 0); - break; - } - } - } + sfxPlay3DSound(pSprite, 374, 0, 0); + break; + } + } + } else actor->hit().ceilhit = 0; - if (bottom >= floorZ) - { + if (bottom >= floorZ) + { int nVel = approxDist(actor->xvel(), actor->yvel()); - int nVelClipped = ClipHigh(nVel, 0x11111); + int nVelClipped = ClipHigh(nVel, 0x11111); Collision coll(floorHit); if (coll.type == kHitSprite) - { + { auto hitActor = coll.actor; auto hitSpr = &hitActor->s(); if ((hitSpr->cstat & 0x30) == 0) - { + { actor->xvel() += MulScale(4, pSprite->x - hitSpr->x, 2); actor->yvel() += MulScale(4, pSprite->y - hitSpr->y, 2); lhit = actor->hit().hit; - } - } - if (nVel > 0) - { - int t = DivScale(nVelClipped, nVel, 16); + } + } + if (nVel > 0) + { + int t = DivScale(nVelClipped, nVel, 16); actor->xvel() -= MulScale(t, actor->xvel(), 16); actor->yvel() -= MulScale(t, actor->yvel(), 16); - } - } + } + } if (actor->xvel() || actor->yvel()) pSprite->ang = getangle(actor->xvel(), actor->yvel()); return lhit; @@ -4843,233 +4843,233 @@ void MoveDude(DBloodActor* actor) if (actor->IsPlayerActor()) pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; if (!(pSprite->type >= kDudeBase && pSprite->type < kDudeMax)) { - Printf(PRINT_HIGH, "%d: pSprite->type >= kDudeBase && pSprite->type < kDudeMax", pSprite->type); - return; - } + Printf(PRINT_HIGH, "%d: pSprite->type >= kDudeBase && pSprite->type < kDudeMax", pSprite->type); + return; + } DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); - int top, bottom; - GetActorExtents(actor, &top, &bottom); + int top, bottom; + GetActorExtents(actor, &top, &bottom); int bz = (bottom - pSprite->z) / 4; int tz = (pSprite->z - top) / 4; int wd = pSprite->clipdist << 2; - int nSector = pSprite->sectnum; - int nAiStateType = (pXSprite->aiState) ? pXSprite->aiState->stateType : -1; + int nSector = pSprite->sectnum; + int nAiStateType = (pXSprite->aiState) ? pXSprite->aiState->stateType : -1; - assert(nSector >= 0 && nSector < kMaxSectors); + assert(nSector >= 0 && nSector < kMaxSectors); - if (actor->xvel() || actor->yvel()) - { - if (pPlayer && gNoClip) - { + if (actor->xvel() || actor->yvel()) + { + if (pPlayer && gNoClip) + { pSprite->x += actor->xvel() >> 12; pSprite->y += actor->yvel() >> 12; - if (!FindSector(pSprite->x, pSprite->y, &nSector)) - nSector = pSprite->sectnum; - } - else - { - short bakCstat = pSprite->cstat; - pSprite->cstat &= ~257; + if (!FindSector(pSprite->x, pSprite->y, &nSector)) + nSector = pSprite->sectnum; + } + else + { + short bakCstat = pSprite->cstat; + pSprite->cstat &= ~257; actor->hit().hit = ClipMove(&pSprite->x, &pSprite->y, &pSprite->z, &nSector, actor->xvel() >> 12, actor->yvel() >> 12, wd, tz, bz, CLIPMASK0); - if (nSector == -1) - { - nSector = pSprite->sectnum; - if (pSprite->statnum == kStatDude || pSprite->statnum == kStatThing) + if (nSector == -1) + { + nSector = pSprite->sectnum; + if (pSprite->statnum == kStatDude || pSprite->statnum == kStatThing) actDamageSprite(pSprite->index, pSprite, kDamageFall, 1000 << 4); - } + } - if (sector[nSector].type >= kSectorPath && sector[nSector].type <= kSectorRotate) - { - short nSector2 = nSector; - if (pushmove_old(&pSprite->x, &pSprite->y, &pSprite->z, &nSector2, wd, tz, bz, CLIPMASK0) == -1) - actDamageSprite(actor, actor, kDamageFall, 1000 << 4); - if (nSector2 != -1) - nSector = nSector2; - } - assert(nSector >= 0); - pSprite->cstat = bakCstat; - } + if (sector[nSector].type >= kSectorPath && sector[nSector].type <= kSectorRotate) + { + short nSector2 = nSector; + if (pushmove_old(&pSprite->x, &pSprite->y, &pSprite->z, &nSector2, wd, tz, bz, CLIPMASK0) == -1) + actDamageSprite(actor, actor, kDamageFall, 1000 << 4); + if (nSector2 != -1) + nSector = nSector2; + } + assert(nSector >= 0); + pSprite->cstat = bakCstat; + } Collision coll = actor->hit().hit; switch (actor->hit().hit & 0xc000) - { - case kHitSprite: - { + { + case kHitSprite: + { spritetype* pHitSprite = &coll.actor->s(); XSPRITE* pHitXSprite = coll.actor->hasX() ? &coll.actor->x() : nullptr;; auto Owner = coll.actor->GetOwner(); if (pHitSprite->statnum == kStatProjectile && !(pHitSprite->flags & 32) && actor != Owner) - { - HITINFO hitInfo = gHitInfo; - gHitInfo.hitsprite = pSprite->index; - actImpactMissile(actor, 3); - gHitInfo = hitInfo; - } + { + HITINFO hitInfo = gHitInfo; + gHitInfo.hitsprite = pSprite->index; + actImpactMissile(actor, 3); + gHitInfo = hitInfo; + } #ifdef NOONE_EXTENSIONS - if (!gModernMap && pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) - trTriggerSprite(coll.actor, kCmdSpriteTouch); + if (!gModernMap && pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) + trTriggerSprite(coll.actor, kCmdSpriteTouch); #else - if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) - trTriggerSprite(coll.actor, kCmdSpriteTouch); + if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) + trTriggerSprite(coll.actor, kCmdSpriteTouch); #endif - if (pDudeInfo->lockOut && pHitXSprite && pHitXSprite->Push && !pHitXSprite->key && !pHitXSprite->DudeLockout && !pHitXSprite->state && !pHitXSprite->busy && !pPlayer) - trTriggerSprite(coll.actor, kCmdSpritePush); + if (pDudeInfo->lockOut && pHitXSprite && pHitXSprite->Push && !pHitXSprite->key && !pHitXSprite->DudeLockout && !pHitXSprite->state && !pHitXSprite->busy && !pPlayer) + trTriggerSprite(coll.actor, kCmdSpritePush); - break; - } - case kHitWall: - { - int nHitWall = coll.index; + break; + } + case kHitWall: + { + int nHitWall = coll.index; walltype* pHitWall = &wall[nHitWall]; XWALL* pHitXWall = nullptr; - if (pHitWall->extra > 0) pHitXWall = &xwall[pHitWall->extra]; + if (pHitWall->extra > 0) pHitXWall = &xwall[pHitWall->extra]; - if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) - trTriggerWall(nHitWall, pHitXWall, kCmdWallPush); + if (pDudeInfo->lockOut && pHitXWall && pHitXWall->triggerPush && !pHitXWall->key && !pHitXWall->dudeLockout && !pHitXWall->state && !pHitXWall->busy && !pPlayer) + trTriggerWall(nHitWall, pHitXWall, kCmdWallPush); - if (pHitWall->nextsector != -1) - { + if (pHitWall->nextsector != -1) + { sectortype* pHitSector = §or[pHitWall->nextsector]; XSECTOR* pHitXSector = nullptr; - if (pHitSector->extra > 0) - pHitXSector = &xsector[pHitSector->extra]; + if (pHitSector->extra > 0) + pHitXSector = &xsector[pHitSector->extra]; - if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer) - trTriggerSector(pHitWall->nextsector, pHitXSector, kCmdSectorPush); + if (pDudeInfo->lockOut && pHitXSector && pHitXSector->Wallpush && !pHitXSector->Key && !pHitXSector->dudeLockout && !pHitXSector->state && !pHitXSector->busy && !pPlayer) + trTriggerSector(pHitWall->nextsector, pHitXSector, kCmdSectorPush); - if (top < pHitSector->ceilingz || bottom > pHitSector->floorz) - { - // ??? - } - } - actWallBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), nHitWall, 0); - break; - } - } - } - else - { - assert(nSector >= 0 && nSector < kMaxSectors); - FindSector(pSprite->x, pSprite->y, pSprite->z, &nSector); - } - if (pSprite->sectnum != nSector) - { - assert(nSector >= 0 && nSector < kMaxSectors); + if (top < pHitSector->ceilingz || bottom > pHitSector->floorz) + { + // ??? + } + } + actWallBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), nHitWall, 0); + break; + } + } + } + else + { + assert(nSector >= 0 && nSector < kMaxSectors); + FindSector(pSprite->x, pSprite->y, pSprite->z, &nSector); + } + if (pSprite->sectnum != nSector) + { + assert(nSector >= 0 && nSector < kMaxSectors); XSECTOR* pXSector; - int nXSector = sector[pSprite->sectnum].extra; - if (nXSector > 0) - pXSector = &xsector[nXSector]; - else - pXSector = nullptr; - if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) - trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); - ChangeSpriteSect(pSprite->index, nSector); + int nXSector = sector[pSprite->sectnum].extra; + if (nXSector > 0) + pXSector = &xsector[nXSector]; + else + pXSector = nullptr; + if (pXSector && pXSector->Exit && (pPlayer || !pXSector->dudeLockout)) + trTriggerSector(pSprite->sectnum, pXSector, kCmdSectorExit); + ChangeSpriteSect(pSprite->index, nSector); - nXSector = sector[nSector].extra; - pXSector = (nXSector > 0) ? &xsector[nXSector] : nullptr; + nXSector = sector[nSector].extra; + pXSector = (nXSector > 0) ? &xsector[nXSector] : nullptr; if (pXSector && pXSector->Enter && (pPlayer || !pXSector->dudeLockout)) { - if (sector[nSector].type == kSectorTeleport) - pXSector->data = pPlayer ? pSprite->index : -1; - trTriggerSector(nSector, pXSector, kCmdSectorEnter); - } + if (sector[nSector].type == kSectorTeleport) + pXSector->data = pPlayer ? pSprite->index : -1; + trTriggerSector(nSector, pXSector, kCmdSectorEnter); + } - nSector = pSprite->sectnum; - } - int bUnderwater = 0; - int bDepth = 0; - if (sector[nSector].extra > 0) - { + nSector = pSprite->sectnum; + } + int bUnderwater = 0; + int bDepth = 0; + if (sector[nSector].extra > 0) + { XSECTOR* pXSector = &xsector[sector[nSector].extra]; - if (pXSector->Underwater) bUnderwater = 1; - if (pXSector->Depth) bDepth = 1; - } - auto pUpperLink = getUpperLink(nSector); - auto pLowerLink = getLowerLink(nSector); - if (pUpperLink && (pUpperLink->s().type == kMarkerUpWater || pUpperLink->s().type == kMarkerUpGoo)) bDepth = 1; - if (pLowerLink && (pLowerLink->s().type == kMarkerLowWater || pLowerLink->s().type == kMarkerLowGoo)) bDepth = 1; - if (pPlayer) wd += 16; + if (pXSector->Underwater) bUnderwater = 1; + if (pXSector->Depth) bDepth = 1; + } + auto pUpperLink = getUpperLink(nSector); + auto pLowerLink = getLowerLink(nSector); + if (pUpperLink && (pUpperLink->s().type == kMarkerUpWater || pUpperLink->s().type == kMarkerUpGoo)) bDepth = 1; + if (pLowerLink && (pLowerLink->s().type == kMarkerLowWater || pLowerLink->s().type == kMarkerLowGoo)) bDepth = 1; + if (pPlayer) wd += 16; if (actor->zvel()) pSprite->z += actor->zvel() >> 8; - int ceilZ, ceilHit, floorZ, floorHit; + int ceilZ, ceilHit, floorZ, floorHit; GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); - GetActorExtents(actor, &top, &bottom); + GetActorExtents(actor, &top, &bottom); - if (pSprite->flags & 2) - { - int vc = 58254; - if (bDepth) - { - if (bUnderwater) - { - int cz = getceilzofslope(nSector, pSprite->x, pSprite->y); - if (cz > top) + if (pSprite->flags & 2) + { + int vc = 58254; + if (bDepth) + { + if (bUnderwater) + { + int cz = getceilzofslope(nSector, pSprite->x, pSprite->y); + if (cz > top) vc += ((bottom - cz) * -80099) / (bottom - top); - else - vc = 0; - } - else - { - int fz = getflorzofslope(nSector, pSprite->x, pSprite->y); - if (fz < bottom) + else + vc = 0; + } + else + { + int fz = getflorzofslope(nSector, pSprite->x, pSprite->y); + if (fz < bottom) vc += ((bottom - fz) * -80099) / (bottom - top); - } - } - else - { - if (bUnderwater) - vc = 0; - else if (bottom >= floorZ) - vc = 0; - } - if (vc) - { + } + } + else + { + if (bUnderwater) + vc = 0; + else if (bottom >= floorZ) + vc = 0; + } + if (vc) + { pSprite->z += ((vc * 4) / 2) >> 8; - actor->zvel() += vc; - } - } - if (pPlayer && actor->zvel() > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) - { - const bool playerAlive = (pXSprite->health > 0) || VanillaMode(); // only trigger falling scream if player is alive or vanilla mode - if (playerAlive) - { - pPlayer->fallScream = 1; - sfxPlay3DSound(pSprite, 719, 0, 0); - } - } - vec3_t const oldpos = pSprite->pos; - int nLink = CheckLink(pSprite); - if (nLink) - { + actor->zvel() += vc; + } + } + if (pPlayer && actor->zvel() > 0x155555 && !pPlayer->fallScream && pXSprite->height > 0) + { + const bool playerAlive = (pXSprite->health > 0) || VanillaMode(); // only trigger falling scream if player is alive or vanilla mode + if (playerAlive) + { + pPlayer->fallScream = 1; + sfxPlay3DSound(pSprite, 719, 0, 0); + } + } + vec3_t const oldpos = pSprite->pos; + int nLink = CheckLink(pSprite); + if (nLink) + { GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, wd, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); - if (pPlayer) - playerCorrectInertia(pPlayer, &oldpos); + if (pPlayer) + playerCorrectInertia(pPlayer, &oldpos); switch (nLink) { - case kMarkerLowStack: - if (pPlayer == gView) - setgotpic(sector[pSprite->sectnum].floorpicnum); - break; - case kMarkerUpStack: - if (pPlayer == gView) - setgotpic(sector[pSprite->sectnum].ceilingpicnum); - break; - case kMarkerLowWater: - case kMarkerLowGoo: - pXSprite->medium = kMediumNormal; + case kMarkerLowStack: + if (pPlayer == gView) + setgotpic(sector[pSprite->sectnum].floorpicnum); + break; + case kMarkerUpStack: + if (pPlayer == gView) + setgotpic(sector[pSprite->sectnum].ceilingpicnum); + break; + case kMarkerLowWater: + case kMarkerLowGoo: + pXSprite->medium = kMediumNormal; if (pPlayer) { - pPlayer->posture = 0; - pPlayer->bubbleTime = 0; + pPlayer->posture = 0; + pPlayer->bubbleTime = 0; if (!pPlayer->cantJump && (pPlayer->input.actions & SB_JUMP)) { - actor->zvel() = -0x6aaaa; - pPlayer->cantJump = 1; - } - sfxPlay3DSound(pSprite, 721, -1, 0); + actor->zvel() = -0x6aaaa; + pPlayer->cantJump = 1; + } + sfxPlay3DSound(pSprite, 721, -1, 0); } else { @@ -5085,244 +5085,244 @@ void MoveDude(DBloodActor* actor) break; case kDudeBoneEel: actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); - break; - } + break; + } - #ifdef NOONE_EXTENSIONS - if (IsDudeSprite(pSprite) && pXSprite->health > 0 && aiInPatrolState(nAiStateType)) - aiPatrolState(pSprite, kAiStatePatrolMoveL); // continue patrol when going from water - #endif - } - break; - case kMarkerUpWater: - case kMarkerUpGoo: - { - int chance = 0xa00; int medium = kMediumWater; + #ifdef NOONE_EXTENSIONS + if (IsDudeSprite(pSprite) && pXSprite->health > 0 && aiInPatrolState(nAiStateType)) + aiPatrolState(pSprite, kAiStatePatrolMoveL); // continue patrol when going from water + #endif + } + break; + case kMarkerUpWater: + case kMarkerUpGoo: + { + int chance = 0xa00; int medium = kMediumWater; if (nLink == kMarkerUpGoo) { - medium = kMediumGoo; - chance = 0x400; - } + medium = kMediumGoo; + chance = 0x400; + } - pXSprite->medium = medium; + pXSprite->medium = medium; - if (pPlayer) - { + if (pPlayer) + { #ifdef NOONE_EXTENSIONS - // look for palette in data2 of marker. If value <= 0, use default ones. - if (gModernMap) + // look for palette in data2 of marker. If value <= 0, use default ones. + if (gModernMap) { - pPlayer->nWaterPal = 0; - auto pUpper = getUpperLink(nSector); - if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; - } - #endif + pPlayer->nWaterPal = 0; + auto pUpper = getUpperLink(nSector); + if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; + } + #endif - pPlayer->posture = 1; - pXSprite->burnTime = 0; - pPlayer->bubbleTime = abs(actor->zvel()) >> 12; - evPost(actor, 0, kCallbackPlayerBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - } - else - { + pPlayer->posture = 1; + pXSprite->burnTime = 0; + pPlayer->bubbleTime = abs(actor->zvel()) >> 12; + evPost(actor, 0, kCallbackPlayerBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + } + else + { switch (pSprite->type) { - case kDudeCultistTommy: - case kDudeCultistShotgun: - pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); - break; - case kDudeBurningCultist: - { - const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater - if (Chance(chance)) - pSprite->type = kDudeCultistTommy; - else - pSprite->type = kDudeCultistShotgun; - if (fixRandomCultist) // fix burning cultists randomly switching types underwater - pSprite->type = pSprite->inittype; // restore back to spawned cultist type - pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); - break; - } - case kDudeZombieAxeNormal: - pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &zombieAGoto); - break; - case kDudeZombieButcher: - pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &zombieFGoto); - break; - case kDudeGillBeast: - pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); - sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &gillBeastSwimGoto); + case kDudeCultistTommy: + case kDudeCultistShotgun: + pXSprite->burnTime = 0; + evPost(actor, 0, kCallbackEnemeyBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + aiNewState(actor, &cultistSwimGoto); + break; + case kDudeBurningCultist: + { + const bool fixRandomCultist = !cl_bloodvanillaenemies && (pSprite->inittype >= kDudeBase) && (pSprite->inittype < kDudeMax) && !VanillaMode(); // fix burning cultists randomly switching types underwater + if (Chance(chance)) + pSprite->type = kDudeCultistTommy; + else + pSprite->type = kDudeCultistShotgun; + if (fixRandomCultist) // fix burning cultists randomly switching types underwater + pSprite->type = pSprite->inittype; // restore back to spawned cultist type + pXSprite->burnTime = 0; + evPost(actor, 0, kCallbackEnemeyBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + aiNewState(actor, &cultistSwimGoto); + break; + } + case kDudeZombieAxeNormal: + pXSprite->burnTime = 0; + evPost(actor, 0, kCallbackEnemeyBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + aiNewState(actor, &zombieAGoto); + break; + case kDudeZombieButcher: + pXSprite->burnTime = 0; + evPost(actor, 0, kCallbackEnemeyBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + aiNewState(actor, &zombieFGoto); + break; + case kDudeGillBeast: + pXSprite->burnTime = 0; + evPost(actor, 0, kCallbackEnemeyBubble); + sfxPlay3DSound(pSprite, 720, -1, 0); + aiNewState(actor, &gillBeastSwimGoto); - pSprite->flags &= ~6; - break; - case kDudeGargoyleFlesh: - case kDudeHellHound: - case kDudeSpiderBrown: - case kDudeSpiderRed: - case kDudeSpiderBlack: - case kDudeBat: - case kDudeRat: - case kDudeBurningInnocent: - actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); - break; - } + pSprite->flags &= ~6; + break; + case kDudeGargoyleFlesh: + case kDudeHellHound: + case kDudeSpiderBrown: + case kDudeSpiderRed: + case kDudeSpiderBlack: + case kDudeBat: + case kDudeRat: + case kDudeBurningInnocent: + actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); + break; + } - #ifdef NOONE_EXTENSIONS - if (gModernMap) { + #ifdef NOONE_EXTENSIONS + if (gModernMap) { - if (pSprite->type == kDudeModernCustom) { + if (pSprite->type == kDudeModernCustom) { evPost(actor, 0, kCallbackEnemeyBubble); if (!canSwim(pSprite)) actKillDude(actor, actor, kDamageFall, 1000 << 4); break; - } + } - // continue patrol when fall into water - if (IsDudeSprite(pSprite) && pXSprite->health > 0 && aiInPatrolState(nAiStateType)) - aiPatrolState(pSprite, kAiStatePatrolMoveW); + // continue patrol when fall into water + if (IsDudeSprite(pSprite) && pXSprite->health > 0 && aiInPatrolState(nAiStateType)) + aiPatrolState(pSprite, kAiStatePatrolMoveW); - } - #endif + } + #endif - } - break; - } - } - } - GetActorExtents(actor, &top, &bottom); - if (pPlayer && bottom >= floorZ) - { - int floorZ2 = floorZ; - int floorHit2 = floorHit; + } + break; + } + } + } + GetActorExtents(actor, &top, &bottom); + if (pPlayer && bottom >= floorZ) + { + int floorZ2 = floorZ; + int floorHit2 = floorHit; GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR); - if (bottom <= floorZ && pSprite->z - floorZ2 < bz) - { - floorZ = floorZ2; - floorHit = floorHit2; - } - } - if (floorZ <= bottom) - { - actor->hit().florhit = floorHit; + if (bottom <= floorZ && pSprite->z - floorZ2 < bz) + { + floorZ = floorZ2; + floorHit = floorHit2; + } + } + if (floorZ <= bottom) + { + actor->hit().florhit = floorHit; pSprite->z += floorZ - bottom; int v30 = actor->zvel() - velFloor[pSprite->sectnum]; - if (v30 > 0) - { - int vax = actFloorBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), (int*)&v30, pSprite->sectnum, 0); - int nDamage = MulScale(vax, vax, 30); - if (pPlayer) - { - pPlayer->fallScream = 0; + if (v30 > 0) + { + int vax = actFloorBounceVector((int*)&actor->xvel(), (int*)&actor->yvel(), (int*)&v30, pSprite->sectnum, 0); + int nDamage = MulScale(vax, vax, 30); + if (pPlayer) + { + pPlayer->fallScream = 0; if (nDamage > (15 << 4) && (pSprite->flags & 4)) - playerLandingSound(pPlayer); + playerLandingSound(pPlayer); if (nDamage > (30 << 4)) - sfxPlay3DSound(pSprite, 701, 0, 0); - } + sfxPlay3DSound(pSprite, 701, 0, 0); + } nDamage -= 100 << 4; - if (nDamage > 0) - actDamageSprite(actor, actor, kDamageFall, nDamage); - actor->zvel() = v30; - if (abs(actor->zvel()) < 0x10000) - { - actor->zvel() = velFloor[pSprite->sectnum]; + if (nDamage > 0) + actDamageSprite(actor, actor, kDamageFall, nDamage); + actor->zvel() = v30; + if (abs(actor->zvel()) < 0x10000) + { + actor->zvel() = velFloor[pSprite->sectnum]; - pSprite->flags &= ~4; - } - else + pSprite->flags &= ~4; + } + else - pSprite->flags |= 4; - switch (tileGetSurfType(floorHit)) - { - case kSurfWater: - gFX.fxSpawn(FX_9, pSprite->sectnum, pSprite->x, pSprite->y, floorZ, 0); - break; - case kSurfLava: - { + pSprite->flags |= 4; + switch (tileGetSurfType(floorHit)) + { + case kSurfWater: + gFX.fxSpawn(FX_9, pSprite->sectnum, pSprite->x, pSprite->y, floorZ, 0); + break; + case kSurfLava: + { spritetype* pFX = gFX.fxSpawn(FX_10, pSprite->sectnum, pSprite->x, pSprite->y, floorZ, 0); - if (pFX) - { - for (int i = 0; i < 7; i++) - { - auto pFX2 = gFX.fxSpawnActor(FX_14, pFX->sectnum, pFX->x, pFX->y, pFX->z, 0); - if (pFX2) - { - pFX2->xvel() = Random2(0x6aaaa); + if (pFX) + { + for (int i = 0; i < 7; i++) + { + auto pFX2 = gFX.fxSpawnActor(FX_14, pFX->sectnum, pFX->x, pFX->y, pFX->z, 0); + if (pFX2) + { + pFX2->xvel() = Random2(0x6aaaa); pFX2->yvel() = Random2(0x6aaaa); pFX2->zvel() = -(int)Random(0xd5555); - } - } - } - break; - } - } - } - else if (actor->zvel() == 0) + } + } + } + break; + } + } + } + else if (actor->zvel() == 0) - pSprite->flags &= ~4; - } - else - { - actor->hit().florhit = 0; + pSprite->flags &= ~4; + } + else + { + actor->hit().florhit = 0; if (pSprite->flags & 2) - pSprite->flags |= 4; - } - if (top <= ceilZ) - { - actor->hit().ceilhit = ceilHit; + pSprite->flags |= 4; + } + if (top <= ceilZ) + { + actor->hit().ceilhit = ceilHit; pSprite->z += ClipLow(ceilZ - top, 0); if (actor->zvel() <= 0 && (pSprite->flags & 4)) - actor->zvel() = MulScale(-actor->zvel(), 0x2000, 16); - } - else - actor->hit().ceilhit = 0; + actor->zvel() = MulScale(-actor->zvel(), 0x2000, 16); + } + else + actor->hit().ceilhit = 0; GetActorExtents(actor, &top, &bottom); pXSprite->height = ClipLow(floorZ - bottom, 0) >> 8; - if (actor->xvel() || actor->yvel()) - { + if (actor->xvel() || actor->yvel()) + { Collision coll = floorHit; - if (coll.type == kHitSprite) - { - auto hitAct = coll.actor; - if ((hitAct->s().cstat & 0x30) == 0) - { - actor->xvel() += MulScale(4, pSprite->x - hitAct->s().x, 2); - actor->yvel() += MulScale(4, pSprite->y - hitAct->s().y, 2); - return; - } - } - int nXSector = sector[pSprite->sectnum].extra; - if (nXSector > 0 && xsector[nXSector].Underwater) - return; - if (pXSprite->height >= 0x100) - return; - int nDrag = gDudeDrag; - if (pXSprite->height > 0) - nDrag -= scale(gDudeDrag, pXSprite->height, 0x100); - actor->xvel() -= mulscale16r(actor->xvel(), nDrag); - actor->yvel() -= mulscale16r(actor->yvel(), nDrag); + if (coll.type == kHitSprite) + { + auto hitAct = coll.actor; + if ((hitAct->s().cstat & 0x30) == 0) + { + actor->xvel() += MulScale(4, pSprite->x - hitAct->s().x, 2); + actor->yvel() += MulScale(4, pSprite->y - hitAct->s().y, 2); + return; + } + } + int nXSector = sector[pSprite->sectnum].extra; + if (nXSector > 0 && xsector[nXSector].Underwater) + return; + if (pXSprite->height >= 0x100) + return; + int nDrag = gDudeDrag; + if (pXSprite->height > 0) + nDrag -= scale(gDudeDrag, pXSprite->height, 0x100); + actor->xvel() -= mulscale16r(actor->xvel(), nDrag); + actor->yvel() -= mulscale16r(actor->yvel(), nDrag); - if (approxDist(actor->xvel(), actor->yvel()) < 0x1000) - actor->xvel() = actor->yvel() = 0; - } + if (approxDist(actor->xvel(), actor->yvel()) < 0x1000) + actor->xvel() = actor->yvel() = 0; + } } //--------------------------------------------------------------------------- @@ -5337,30 +5337,30 @@ int MoveMissile(DBloodActor* actor) auto pXSprite = &actor->x(); auto Owner = actor->GetOwner(); int cliptype = -1; - int bakCstat = 0; + int bakCstat = 0; spritetype* pOwner = nullptr; if (Owner && Owner->IsDudeActor()) - { + { pOwner = &Owner->s(); - bakCstat = pOwner->cstat; - pOwner->cstat &= ~257; - } - gHitInfo.hitsect = -1; - gHitInfo.hitwall = -1; - gHitInfo.hitsprite = -1; + bakCstat = pOwner->cstat; + pOwner->cstat &= ~257; + } + gHitInfo.hitsect = -1; + gHitInfo.hitwall = -1; + gHitInfo.hitsprite = -1; if (pSprite->type == kMissileFlameSpray) actAirDrag(actor, 0x1000); if (pXSprite->target != -1 && (actor->xvel() || actor->yvel() || actor->zvel())) - { + { auto target = actor->GetTarget(); spritetype* pTarget = &target->s(); XSPRITE* pXTarget = target->hasX() ? &target->x() : nullptr; - if (pTarget->statnum == kStatDude && pXTarget && pXTarget->health > 0) - { + if (pTarget->statnum == kStatDude && pXTarget && pXTarget->health > 0) + { int nTargetAngle = getangle(-(pTarget->y - pSprite->y), pTarget->x - pSprite->x); - int vx = missileInfo[pSprite->type - kMissileBase].velocity; - int vy = 0; + int vx = missileInfo[pSprite->type - kMissileBase].velocity; + int vy = 0; RotatePoint(&vx, &vy, (nTargetAngle + 1536) & 2047, 0, 0); actor->xvel() = vx; actor->yvel() = vy; @@ -5371,119 +5371,119 @@ int MoveMissile(DBloodActor* actor) int deltaz = dz / 10; if (pTarget->z < pSprite->z) deltaz = -deltaz; actor->zvel() += deltaz; - } - } + } + } int vx = actor->xvel() >> 12; int vy = actor->yvel() >> 12; int vz = actor->zvel() >> 8; - int top, bottom; + int top, bottom; GetActorExtents(actor, &top, &bottom); - int i = 1; - const int bakCompat = enginecompatibility_mode; - const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) - while (1) - { - int x = pSprite->x; - int y = pSprite->y; - int z = pSprite->z; - int nSector2 = pSprite->sectnum; - clipmoveboxtracenum = 1; - const short bakSpriteCstat = pSprite->cstat; - if (pOwner && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) - { - enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy - pSprite->cstat &= ~257; // remove self collisions for accurate clipmove - } + int i = 1; + const int bakCompat = enginecompatibility_mode; + const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) + while (1) + { + int x = pSprite->x; + int y = pSprite->y; + int z = pSprite->z; + int nSector2 = pSprite->sectnum; + clipmoveboxtracenum = 1; + const short bakSpriteCstat = pSprite->cstat; + if (pOwner && !isFlameSprite && !cl_bloodvanillaexplosions && !VanillaMode()) + { + enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy + pSprite->cstat &= ~257; // remove self collisions for accurate clipmove + } Collision clipmoveresult = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist << 2, (z - top) / 4, (bottom - z) / 4, CLIPMASK0); - enginecompatibility_mode = bakCompat; // restore - pSprite->cstat = bakSpriteCstat; - clipmoveboxtracenum = 3; - short nSector = nSector2; - if (nSector2 < 0) - { + enginecompatibility_mode = bakCompat; // restore + pSprite->cstat = bakSpriteCstat; + clipmoveboxtracenum = 3; + short nSector = nSector2; + if (nSector2 < 0) + { cliptype = -1; - break; - } + break; + } if (clipmoveresult.type == kHitSprite) - { + { gHitInfo.hitsprite = clipmoveresult.legacyVal; cliptype = 3; - } + } else if (clipmoveresult.type == kHitWall) - { + { gHitInfo.hitwall = clipmoveresult.index; if (wall[clipmoveresult.index].nextsector == -1) cliptype = 0; - else - { - int32_t fz, cz; + else + { + int32_t fz, cz; getzsofslope(wall[clipmoveresult.index].nextsector, x, y, &cz, &fz); if (z <= cz || z >= fz) cliptype = 0; else cliptype = 4; - } - } + } + } if (cliptype == 4) - { + { walltype* pWall = &wall[gHitInfo.hitwall]; - if (pWall->extra > 0) - { + if (pWall->extra > 0) + { XWALL* pXWall = &xwall[pWall->extra]; - if (pXWall->triggerVector) - { - trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact); + if (pXWall->triggerVector) + { + trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact); if (!(pWall->cstat & 64)) - { + { cliptype = -1; - if (i-- > 0) - continue; + if (i-- > 0) + continue; cliptype = 0; - break; - } - } - } - } + break; + } + } + } + } if (cliptype >= 0 && cliptype != 3) - { + { int nAngle = getangle(actor->xvel(), actor->yvel()); - x -= MulScale(Cos(nAngle), 16, 30); - y -= MulScale(Sin(nAngle), 16, 30); + x -= MulScale(Cos(nAngle), 16, 30); + y -= MulScale(Sin(nAngle), 16, 30); int nVel = approxDist(actor->xvel(), actor->yvel()); vz -= scale(0x100, actor->zvel(), nVel); - updatesector(x, y, &nSector); - nSector2 = nSector; - } - int ceilZ, ceilHit, floorZ, floorHit; + updatesector(x, y, &nSector); + nSector2 = nSector; + } + int ceilZ, ceilHit, floorZ, floorHit; GetZRangeAtXYZ(x, y, z, nSector2, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0); GetActorExtents(actor, &top, &bottom); - top += vz; - bottom += vz; - if (bottom >= floorZ) - { + top += vz; + bottom += vz; + if (bottom >= floorZ) + { actor->hit().florhit = floorHit; vz += floorZ - bottom; cliptype = 2; - } - if (top <= ceilZ) - { + } + if (top <= ceilZ) + { actor->hit().ceilhit = ceilHit; vz += ClipLow(ceilZ - top, 0); cliptype = 1; - } - pSprite->x = x; - pSprite->y = y; + } + pSprite->x = x; + pSprite->y = y; pSprite->z = z + vz; - updatesector(x, y, &nSector); - if (nSector >= 0 && nSector != pSprite->sectnum) - { - assert(nSector >= 0 && nSector < kMaxSectors); + updatesector(x, y, &nSector); + if (nSector >= 0 && nSector != pSprite->sectnum) + { + assert(nSector >= 0 && nSector < kMaxSectors); ChangeSpriteSect(pSprite->index, nSector); - } - CheckLink(pSprite); - gHitInfo.hitsect = pSprite->sectnum; - gHitInfo.hitx = pSprite->x; - gHitInfo.hity = pSprite->y; - gHitInfo.hitz = pSprite->z; - break; - } + } + CheckLink(pSprite); + gHitInfo.hitsect = pSprite->sectnum; + gHitInfo.hitx = pSprite->x; + gHitInfo.hity = pSprite->y; + gHitInfo.hitz = pSprite->z; + break; + } if (pOwner) pOwner->cstat = bakCstat; return cliptype; @@ -5503,78 +5503,78 @@ void actExplodeSprite(DBloodActor* actor) //auto Owner = actor->GetOwner(); if (pSprite->statnum == kStatExplosion) return; - sfxKill3DSound(pSprite, -1, -1); - evKill(pSprite->index, 3); + sfxKill3DSound(pSprite, -1, -1); + evKill(pSprite->index, 3); - int nType = kExplosionStandard; + int nType = kExplosionStandard; - switch (pSprite->type) - { - case kMissileFireballNapalm: - nType = kExplosionNapalm; + switch (pSprite->type) + { + case kMissileFireballNapalm: + nType = kExplosionNapalm; seqSpawn(4, actor, -1); if (Chance(0x8000)) pSprite->cstat |= 4; - sfxPlay3DSound(pSprite, 303, -1, 0); + sfxPlay3DSound(pSprite, 303, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kMissileFlareAlt: - nType = kExplosionFireball; + case kMissileFlareAlt: + nType = kExplosionFireball; seqSpawn(9, actor, -1); if (Chance(0x8000)) pSprite->cstat |= 4; sfxPlay3DSound(pSprite, 306, 24 + (pSprite->index & 3), FX_GlobalChannel); // ouch... GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kMissileFireballCerberus: - case kMissileFireballTchernobog: - nType = kExplosionFireball; + case kMissileFireballCerberus: + case kMissileFireballTchernobog: + nType = kExplosionFireball; seqSpawn(5, actor, -1); - sfxPlay3DSound(pSprite, 304, -1, 0); + sfxPlay3DSound(pSprite, 304, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kThingArmedTNTStick: - nType = kExplosionSmall; + case kThingArmedTNTStick: + nType = kExplosionSmall; if (actor->hit().florhit == 0) seqSpawn(4, actor, -1); else seqSpawn(3, actor, -1); - sfxPlay3DSound(pSprite, 303, -1, 0); + sfxPlay3DSound(pSprite, 303, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kThingArmedProxBomb: - case kThingArmedRemoteBomb: - case kThingArmedTNTBundle: + case kThingArmedProxBomb: + case kThingArmedRemoteBomb: + case kThingArmedTNTBundle: #ifdef NOONE_EXTENSIONS - case kModernThingTNTProx: + case kModernThingTNTProx: #endif - nType = kExplosionStandard; + nType = kExplosionStandard; if (actor->hit().florhit == 0) seqSpawn(4, actor, -1); - else + else seqSpawn(3, actor, -1); - sfxPlay3DSound(pSprite, 304, -1, 0); + sfxPlay3DSound(pSprite, 304, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kThingArmedSpray: - nType = kExplosionSpray; + case kThingArmedSpray: + nType = kExplosionSpray; seqSpawn(5, actor, -1); - sfxPlay3DSound(pSprite, 307, -1, 0); + sfxPlay3DSound(pSprite, 307, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; + break; - case kThingTNTBarrel: - { + case kThingTNTBarrel: + { auto spawned = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); spawned->SetOwner(actor->GetOwner()); - if (actCheckRespawn(pSprite)) - { - pXSprite->state = 1; + if (actCheckRespawn(pSprite)) + { + pXSprite->state = 1; pXSprite->health = thingInfo[0].startHealth << 4; - } + } else actPostSprite(actor, kStatFree); - nType = kExplosionLarge; + nType = kExplosionLarge; seqSpawn(4, spawned, -1); actor = spawned; pSprite = &spawned->s(); @@ -5582,8 +5582,8 @@ void actExplodeSprite(DBloodActor* actor) sfxPlay3DSound(pSprite, 305, -1, 0); GibSprite(pSprite, GIBTYPE_14, nullptr, nullptr); - break; - } + break; + } case kTrapExploder: { // Defaults for exploder @@ -5592,53 +5592,53 @@ void actExplodeSprite(DBloodActor* actor) int nSeq = 4; #ifdef NOONE_EXTENSIONS - // allow to customize hidden exploder trap + // allow to customize hidden exploder trap if (gModernMap) { nType = pXSprite->data1; // Explosion type int tSeq = pXSprite->data2; // SEQ id int tSnd = pXSprite->data3; // Sound Id - if (nType <= 1 || nType > kExplodeMax) { nType = 1; nSeq = 4; nSnd = 304; } - else if (nType == 2) { nSeq = 4; nSnd = 305; } - else if (nType == 3) { nSeq = 9; nSnd = 307; } - else if (nType == 4) { nSeq = 5; nSnd = 307; } - else if (nType <= 6) { nSeq = 4; nSnd = 303; } - else if (nType == 7) { nSeq = 4; nSnd = 303; } - else if (nType == 8) { nType = 0; nSeq = 3; nSnd = 303; } + if (nType <= 1 || nType > kExplodeMax) { nType = 1; nSeq = 4; nSnd = 304; } + else if (nType == 2) { nSeq = 4; nSnd = 305; } + else if (nType == 3) { nSeq = 9; nSnd = 307; } + else if (nType == 4) { nSeq = 5; nSnd = 307; } + else if (nType <= 6) { nSeq = 4; nSnd = 303; } + else if (nType == 7) { nSeq = 4; nSnd = 303; } + else if (nType == 8) { nType = 0; nSeq = 3; nSnd = 303; } - // Override previous sound and seq assigns - if (tSeq > 0) nSeq = tSeq; - if (tSnd > 0) nSnd = tSnd; - } + // Override previous sound and seq assigns + if (tSeq > 0) nSeq = tSeq; + if (tSnd > 0) nSnd = tSnd; + } #endif if (getSequence(nSeq)) seqSpawn(nSeq, actor, -1); sfxPlay3DSound(pSprite, nSnd, -1, 0); break; } - case kThingPodFireBall: - nType = kExplosionFireball; + case kThingPodFireBall: + nType = kExplosionFireball; seqSpawn(9, actor, -1); - sfxPlay3DSound(pSprite, 307, -1, 0); + sfxPlay3DSound(pSprite, 307, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - sub_746D4(pSprite, 240); - break; + sub_746D4(pSprite, 240); + break; - default: - nType = kExplosionStandard; + default: + nType = kExplosionStandard; seqSpawn(4, actor, -1); if (Chance(0x8000)) pSprite->cstat |= 4; - sfxPlay3DSound(pSprite, 303, -1, 0); + sfxPlay3DSound(pSprite, 303, -1, 0); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr); - break; - } + break; + } actor->xvel() = actor->yvel() = actor->zvel() = 0; actPostSprite(actor, kStatExplosion); - pSprite->xrepeat = pSprite->yrepeat = explodeInfo[nType].repeat; + pSprite->xrepeat = pSprite->yrepeat = explodeInfo[nType].repeat; - pSprite->flags &= ~3; - pSprite->type = nType; + pSprite->flags &= ~3; + pSprite->type = nType; const EXPLOSION* pExplodeInfo = &explodeInfo[nType]; pXSprite->target = 0; pXSprite->data1 = pExplodeInfo->ticks; @@ -5654,8 +5654,8 @@ void actExplodeSprite(DBloodActor* actor) void actActivateGibObject(DBloodActor* actor) { - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); int gib1 = ClipRange(pXSprite->data1, 0, 31); int gib2 = ClipRange(pXSprite->data2, 0, 31); @@ -5688,35 +5688,35 @@ static void actCheckProximity() if (pSprite->flags & 32) continue; if (actor->hasX()) - { + { XSPRITE* pXSprite = &actor->x(); switch (pSprite->type) { - case kThingBloodBits: - case kThingBloodChunks: - case kThingZombieHead: - if (pXSprite->locked && PlayClock >= pXSprite->targetX) pXSprite->locked = 0; - break; - } + case kThingBloodBits: + case kThingBloodChunks: + case kThingZombieHead: + if (pXSprite->locked && PlayClock >= pXSprite->targetX) pXSprite->locked = 0; + break; + } - if (pXSprite->burnTime > 0) - { + if (pXSprite->burnTime > 0) + { pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0); actDamageSprite(actor->GetBurnSource(), actor, kDamageFall, 8); - } + } if (pXSprite->Proximity) { #ifdef NOONE_EXTENSIONS - // don't process locked or 1-shot things for proximity + // don't process locked or 1-shot things for proximity if (gModernMap && (pXSprite->locked || pXSprite->isTriggered)) - continue; + continue; #endif - if (pSprite->type == kThingDroppedLifeLeech) pXSprite->target = -1; + if (pSprite->type == kThingDroppedLifeLeech) pXSprite->target = -1; BloodStatIterator it1(kStatDude); while (auto dudeactor = it1.Next()) - { + { auto nextdude = it1.Peek(); spritetype* pSprite2 = &dudeactor->s(); @@ -5727,11 +5727,11 @@ static void actCheckProximity() { int proxyDist = 96; #ifdef NOONE_EXTENSIONS - // allow dudeLockout for proximity flag + // allow dudeLockout for proximity flag if (gModernMap && pSprite->type != kThingDroppedLifeLeech && pXSprite->DudeLockout && !dudeactor->IsPlayerActor()) - continue; + continue; - if (pSprite->type == kModernThingEnemyLifeLeech) proxyDist = 512; + if (pSprite->type == kModernThingEnemyLifeLeech) proxyDist = 512; #endif if (pSprite->type == kThingDroppedLifeLeech && pXSprite->target == -1) { @@ -5745,41 +5745,41 @@ static void actCheckProximity() if (dudeactor == Owner || pSprite2->type == kDudeZombieAxeBuried || pSprite2->type == kDudeRat || pSprite2->type == kDudeBat) continue; if (gGameOptions.nGameType == 3 && pPlayer2 && pPlayer->teamId == pPlayer2->teamId) continue; if (gGameOptions.nGameType == 1 && pPlayer2) continue; - proxyDist = 512; - } + proxyDist = 512; + } if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, proxyDist)) { switch (pSprite->type) { - case kThingDroppedLifeLeech: + case kThingDroppedLifeLeech: if (!Chance(0x4000) && nextdude) continue; - if (pSprite2->cstat & CLIPMASK0) pXSprite->target = pSprite2->index; - else continue; - break; + if (pSprite2->cstat & CLIPMASK0) pXSprite->target = pSprite2->index; + else continue; + break; #ifdef NOONE_EXTENSIONS - case kModernThingTNTProx: + case kModernThingTNTProx: if (!dudeactor->IsPlayerActor()) continue; - pSprite->pal = 0; - break; + pSprite->pal = 0; + break; - case kModernThingEnemyLifeLeech: - if (pXSprite->target != pSprite2->index) continue; - break; + case kModernThingEnemyLifeLeech: + if (pXSprite->target != pSprite2->index) continue; + break; #endif default: break; - } - if (pSprite->owner == -1) pSprite->owner = pSprite2->index; + } + if (pSprite->owner == -1) pSprite->owner = pSprite2->index; trTriggerSprite(actor, kCmdSpriteProximity); - } - } - } - } - } - } + } + } + } + } + } + } } //--------------------------------------------------------------------------- @@ -5792,109 +5792,109 @@ static void actCheckThings() { BloodStatIterator it(kStatThing); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); if (pSprite->flags & 32) continue; if (!actor->hasX()) continue; auto pXSprite = &actor->x(); - int nSector = pSprite->sectnum; + int nSector = pSprite->sectnum; - int nXSector = sector[nSector].extra; + int nXSector = sector[nSector].extra; XSECTOR* pXSector = NULL; - if (nXSector > 0) - { - assert(nXSector > 0 && nXSector < kMaxXSectors); - assert(xsector[nXSector].reference == nSector); - pXSector = &xsector[nXSector]; - } - if (pXSector && pXSector->panVel && (pXSector->panAlways || pXSector->state || pXSector->busy)) - { - int nType = pSprite->type - kThingBase; + if (nXSector > 0) + { + assert(nXSector > 0 && nXSector < kMaxXSectors); + assert(xsector[nXSector].reference == nSector); + pXSector = &xsector[nXSector]; + } + if (pXSector && pXSector->panVel && (pXSector->panAlways || pXSector->state || pXSector->busy)) + { + int nType = pSprite->type - kThingBase; const THINGINFO* pThingInfo = &thingInfo[nType]; if (pThingInfo->flags & 1) pSprite->flags |= 1; if (pThingInfo->flags & 2) pSprite->flags |= 4; - } + } if (pSprite->flags & 3) - { + { viewBackupSpriteLoc(actor); - if (pXSector && pXSector->panVel) - { - int top, bottom; + if (pXSector && pXSector->panVel) + { + int top, bottom; GetActorExtents(actor, &top, &bottom); - if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= bottom) - { - int angle = pXSector->panAngle; - int speed = 0; - if (pXSector->panAlways || pXSector->state || pXSector->busy) - { - speed = pXSector->panVel << 9; + if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= 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 = MulScale(speed, pXSector->busy, 16); - } + } if (sector[nSector].floorstat & 64) angle = (angle + GetWallAngle(sector[nSector].wallptr) + 512) & 2047; actor->xvel() += MulScale(speed, Cos(angle), 30); actor->yvel() += MulScale(speed, Sin(angle), 30); - } - } + } + } actAirDrag(actor, 128); if (((pSprite->index >> 8) & 15) == (gFrameCount & 15) && (pSprite->flags & 2)) pSprite->flags |= 4; if ((pSprite->flags & 4) || actor->xvel() || actor->yvel() || actor->zvel() || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) - { + { Collision hit = MoveThing(actor); if (hit.type) - { + { if (pXSprite->Impact) trTriggerSprite(actor, kCmdOff); switch (pSprite->type) - { - case kThingDripWater: - case kThingDripBlood: - MakeSplash(&bloodActors[pXSprite->reference]); - break; + { + case kThingDripWater: + case kThingDripBlood: + MakeSplash(&bloodActors[pXSprite->reference]); + break; #ifdef NOONE_EXTENSIONS - case kModernThingThrowableRock: + case kModernThingThrowableRock: seqSpawn(24, actor, -1); if (hit.type = kHitSprite) - { - pSprite->xrepeat = 32; - pSprite->yrepeat = 32; + { + pSprite->xrepeat = 32; + pSprite->yrepeat = 32; actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, pXSprite->data1); - } - break; + } + break; #endif - case kThingBone: + case kThingBone: seqSpawn(24, actor, -1); if (hit.type = kHitSprite) - { + { actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); - } - break; + } + break; - case kThingPodGreenBall: + case kThingPodGreenBall: if (hit.type == kHitSector) - { + { actRadiusDamage(actor->GetOwner(), pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, kDamageExplode, 6, 0); evPost(actor, 0, kCallbackFXPodBloodSplat); - } + } else if (hit.type == kHitSprite) - { + { actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); evPost(actor, 0, kCallbackFXPodBloodSplat); - } - break; + } + break; - case kThingPodFireBall: + case kThingPodFireBall: if (hit.type == kHitSprite) actExplodeSprite(actor); - break; - } - } - } - } - } + break; + } + } + } + } + } } //--------------------------------------------------------------------------- @@ -5907,15 +5907,15 @@ static void actCheckProjectiles() { BloodStatIterator it(kStatProjectile); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); - if (pSprite->flags & 32) - continue; + if (pSprite->flags & 32) + continue; viewBackupSpriteLoc(actor); int hit = MoveMissile(actor); if (hit >= 0) actImpactMissile(&bloodActors[pSprite->index], hit); - } + } } //--------------------------------------------------------------------------- @@ -5928,174 +5928,174 @@ static void actCheckExplosion() { BloodStatIterator it(kStatExplosion); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); - if (pSprite->flags & 32) - continue; + if (pSprite->flags & 32) + continue; if (!actor->hasX()) continue; XSPRITE* pXSprite = &actor->x(); auto Owner = actor->GetOwner(); auto pOwner = Owner ? &Owner->s() : nullptr; - int nType = pSprite->type; - assert(nType >= 0 && nType < kExplodeMax); + int nType = pSprite->type; + assert(nType >= 0 && nType < kExplodeMax); const EXPLOSION* pExplodeInfo = &explodeInfo[nType]; - int x = pSprite->x; - int y = pSprite->y; - int z = pSprite->z; - int nSector = pSprite->sectnum; - int radius = pExplodeInfo->radius; + int x = pSprite->x; + int y = pSprite->y; + int z = pSprite->z; + int nSector = pSprite->sectnum; + int radius = pExplodeInfo->radius; #ifdef NOONE_EXTENSIONS - // Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor - // or of Hidden Exploder. - if (gModernMap && pXSprite->data4 > 0) - radius = pXSprite->data4; + // Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor + // or of Hidden Exploder. + if (gModernMap && pXSprite->data4 > 0) + radius = pXSprite->data4; #endif uint8_t sectormap[(kMaxSectors + 7) >> 3]; - // GetClosestSpriteSectors() has issues checking some sectors due to optimizations - // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions - // so only allow this new checking method for dude spawned explosions - short gAffectedXWalls[kMaxXWalls]; - const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic - GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod); - - for (int i = 0; i < kMaxXWalls; i++) - { - int nWall = gAffectedXWalls[i]; - if (nWall == -1) - break; + // GetClosestSpriteSectors() has issues checking some sectors due to optimizations + // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions + // so only allow this new checking method for dude spawned explosions + short gAffectedXWalls[kMaxXWalls]; + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic + GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod); + + for (int i = 0; i < kMaxXWalls; i++) + { + int nWall = gAffectedXWalls[i]; + if (nWall == -1) + break; XWALL* pXWall = &xwall[wall[nWall].extra]; - trTriggerWall(nWall, pXWall, kCmdWallImpact); - } + trTriggerWall(nWall, pXWall, kCmdWallImpact); + } BloodStatIterator it1(kStatDude); while (auto dudeactor = it1.Next()) - { + { spritetype* pDude = &dudeactor->s(); if (pDude->flags & 32) continue; if (TestBitString(sectormap, pDude->sectnum)) - { - if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius)) - { - if (pExplodeInfo->dmg && pXSprite->target == 0) - { - pXSprite->target = 1; + { + if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius)) + { + if (pExplodeInfo->dmg && pXSprite->target == 0) + { + pXSprite->target = 1; actDamageSprite(Owner, dudeactor, kDamageFall, (pExplodeInfo->dmg + Random(pExplodeInfo->dmgRng)) << 4); - } + } if (pExplodeInfo->dmgType) ConcussSprite(actor, dudeactor, x, y, z, pExplodeInfo->dmgType); - if (pExplodeInfo->burnTime) - { + if (pExplodeInfo->burnTime) + { assert(dudeactor->hasX()); XSPRITE* pXDude = &dudeactor->x(); if (!pXDude->burnTime) evPost(dudeactor, 0, kCallbackFXFlameLick); actBurnSprite(Owner, dudeactor, pExplodeInfo->burnTime << 2); - } - } - } - } + } + } + } + } - it1.Reset(kStatThing); + it1.Reset(kStatThing); while (auto thingactor = it1.Next()) - { + { spritetype* pThing = &thingactor->s(); if (pThing->flags & 32) continue; if (TestBitString(sectormap, pThing->sectnum)) - { + { if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius) && thingactor->hasX()) - { + { XSPRITE* pXThing = &thingactor->x(); if (!pXThing->locked) - { + { if (pExplodeInfo->dmgType) ConcussSprite(Owner, thingactor, x, y, z, pExplodeInfo->dmgType); - if (pExplodeInfo->burnTime) - { - if (pThing->type == kThingTNTBarrel && !pXThing->burnTime) + if (pExplodeInfo->burnTime) + { + if (pThing->type == kThingTNTBarrel && !pXThing->burnTime) evPost(thingactor, 0, kCallbackFXFlameLick); actBurnSprite(Owner, thingactor, pExplodeInfo->burnTime << 2); - } - } - } - } - } + } + } + } + } + } - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { + for (int p = connecthead; p >= 0; p = connectpoint2[p]) + { spritetype* pSprite2 = gPlayer[p].pSprite; int dx = (x - pSprite2->x) >> 4; int dy = (y - pSprite2->y) >> 4; int dz = (z - pSprite2->z) >> 8; int nDist = dx * dx + dy * dy + dz * dz + 0x40000; - int t = DivScale(pXSprite->data2, nDist, 16); - gPlayer[p].flickerEffect += t; - } + int t = DivScale(pXSprite->data2, nDist, 16); + gPlayer[p].flickerEffect += t; + } #ifdef NOONE_EXTENSIONS if (pXSprite->data1 != 0) { - // add impulse for sprites from physics list + // add impulse for sprites from physics list if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0) { for (int i = 0; i < gPhysSpritesCount; i++) { - if (gPhysSpritesList[i] == -1) continue; + if (gPhysSpritesList[i] == -1) continue; auto physactor = &bloodActors[gPhysSpritesList[i]]; spritetype* pDebris = &physactor->s(); if (pDebris->sectnum < 0 || (pDebris->flags & kHitagFree) != 0) continue; if (!TestBitString(sectormap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; else debrisConcuss(Owner ? Owner->s().index : -1, i, x, y, z, pExplodeInfo->dmgType); - } - } + } + } - // trigger sprites from impact list - if (gImpactSpritesCount > 0) { + // trigger sprites from impact list + if (gImpactSpritesCount > 0) { for (int i = 0; i < gImpactSpritesCount; i++) { - if (gImpactSpritesList[i] == -1) continue; + if (gImpactSpritesList[i] == -1) continue; auto impactactor = &bloodActors[gImpactSpritesList[i]]; auto impactsprite = &impactactor->s(); if (impactsprite->sectnum < 0 || (impactsprite->flags & kHitagFree) != 0) - continue; + continue; if (impactsprite->extra <= 0) - continue; + continue; XSPRITE* pXImpact = &impactactor->x(); if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, impactsprite->sectnum) || !CheckProximity(impactsprite, x, y, z, nSector, radius)) - continue; + continue; trTriggerSprite(impactsprite->index, pXImpact, kCmdSpriteImpact); - } - } + } + } - } + } if (!gModernMap || !(pSprite->flags & kModernTypeFlag1)) { // if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually via sprite statnum 2. - pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); - pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); - pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); - } + pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); + pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); + pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); + } #else - pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); - pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); - pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); + pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); + pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); + pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); #endif if (pXSprite->data1 == 0 && pXSprite->data2 == 0 && pXSprite->data3 == 0 && seqGetStatus(actor) < 0) actPostSprite(actor, kStatFree); - } + } } //--------------------------------------------------------------------------- @@ -6108,47 +6108,47 @@ static void actCheckTraps() { BloodStatIterator it(kStatTraps); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); if ((pSprite->flags & 32) || !actor->hasX()) - continue; + continue; XSPRITE* pXSprite = &actor->x(); - switch (pSprite->type) { - case kTrapSawCircular: + switch (pSprite->type) { + case kTrapSawCircular: pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); - break; + break; - case kTrapFlame: + case kTrapFlame: if (pXSprite->state && seqGetStatus(actor) < 0) { - int x = pSprite->x; - int y = pSprite->y; - int z = pSprite->z; + int x = pSprite->x; + int y = pSprite->y; + int z = pSprite->z; int t = (pXSprite->data1 << 23) / 120; - int dx = MulScale(t, Cos(pSprite->ang), 30); - int dy = MulScale(t, Sin(pSprite->ang), 30); - for (int i = 0; i < 2; i++) - { + int dx = MulScale(t, Cos(pSprite->ang), 30); + int dy = MulScale(t, Sin(pSprite->ang), 30); + for (int i = 0; i < 2; i++) + { auto pFX = gFX.fxSpawnActor(FX_32, pSprite->sectnum, x, y, z, 0); - if (pFX) - { + if (pFX) + { pFX->xvel() = dx + Random2(0x8888); pFX->yvel() = dy + Random2(0x8888); pFX->zvel() = Random2(0x8888); - } + } x += (dx / 2) >> 12; y += (dy / 2) >> 12; - } - dy = SinScale16(pSprite->ang); - dx = CosScale16(pSprite->ang); + } + dy = SinScale16(pSprite->ang); + dx = CosScale16(pSprite->ang); gVectorData[kVectorTchernobogBurn].maxDist = pXSprite->data1 << 9; - actFireVector(pSprite, 0, 0, dx, dy, Random2(0x8888), kVectorTchernobogBurn); - } - break; - } - } + actFireVector(pSprite, 0, 0, dx, dy, Random2(0x8888), kVectorTchernobogBurn); + } + break; + } + } } //--------------------------------------------------------------------------- @@ -6161,57 +6161,57 @@ static void actCheckDudes() { BloodStatIterator it(kStatDude); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); - if (pSprite->flags & 32) - continue; + if (pSprite->flags & 32) + continue; if (actor->hasX()) - { + { XSPRITE* pXSprite = &actor->x(); - const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick - if ((pXSprite->burnTime > 0) || fixBurnGlitch) - { - switch (pSprite->type) - { - case kDudeBurningInnocent: - case kDudeBurningCultist: - case kDudeBurningZombieAxe: - case kDudeBurningZombieButcher: + const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick + if ((pXSprite->burnTime > 0) || fixBurnGlitch) + { + switch (pSprite->type) + { + case kDudeBurningInnocent: + case kDudeBurningCultist: + case kDudeBurningZombieAxe: + case kDudeBurningZombieButcher: actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8); - break; + break; - default: + default: pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0); actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8); - break; - } - } + break; + } + } #ifdef NOONE_EXTENSIONS - // handle incarnations of custom dude + // handle incarnations of custom dude if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->sysData1 == kGenDudeTransformStatus) { actor->xvel() = actor->yvel() = 0; if (seqGetStatus(actor) < 0) genDudeTransform(pSprite); - } + } #endif - if (pSprite->type == kDudeCerberusTwoHead) - { + if (pSprite->type == kDudeCerberusTwoHead) + { if (pXSprite->health <= 0 && seqGetStatus(actor) < 0) - { + { pXSprite->health = dudeInfo[28].startHealth << 4; - pSprite->type = kDudeCerberusOneHead; + pSprite->type = kDudeCerberusOneHead; if (pXSprite->target != -1) aiSetTarget(pXSprite, pXSprite->target); aiActivateDude(actor); - } - } - if (pXSprite->Proximity && !pXSprite->isTriggered) - { + } + } + if (pXSprite->Proximity && !pXSprite->isTriggered) + { BloodStatIterator it1(kStatDude); while (auto actor2 = it1.Next()) - { + { spritetype* pSprite2 = &actor->s(); if (pSprite2->flags & 32) continue; @@ -6219,99 +6219,99 @@ static void actCheckDudes() if ((unsigned int)pXSprite2->health > 0 && IsPlayerSprite(pSprite2)) { - if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128)) + if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128)) trTriggerSprite(actor, kCmdSpriteProximity); - } - } - } + } + } + } if (actor->IsPlayerActor()) - { + { PLAYER* pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; if (pPlayer->voodooTargets) voodooTarget(pPlayer); if (pPlayer->hand && Chance(0x8000)) actDamageSprite(actor, actor, kDamageDrown, 12); - if (pPlayer->isUnderwater) - { - char bActive = packItemActive(pPlayer, 1); + if (pPlayer->isUnderwater) + { + char bActive = packItemActive(pPlayer, 1); if (bActive || pPlayer->godMode) pPlayer->underwaterTime = 1200; else pPlayer->underwaterTime = ClipLow(pPlayer->underwaterTime - 4, 0); - if (pPlayer->underwaterTime < 1080 && packCheckItem(pPlayer, 1) && !bActive) - packUseItem(pPlayer, 1); + if (pPlayer->underwaterTime < 1080 && packCheckItem(pPlayer, 1) && !bActive) + packUseItem(pPlayer, 1); - if (!pPlayer->underwaterTime) - { - pPlayer->chokeEffect += 4; - if (Chance(pPlayer->chokeEffect)) + if (!pPlayer->underwaterTime) + { + pPlayer->chokeEffect += 4; + if (Chance(pPlayer->chokeEffect)) actDamageSprite(actor, actor, kDamageDrown, 3 << 4); - } - else - pPlayer->chokeEffect = 0; + } + else + pPlayer->chokeEffect = 0; if (actor->xvel() || actor->yvel()) - sfxPlay3DSound(pSprite, 709, 100, 2); + sfxPlay3DSound(pSprite, 709, 100, 2); pPlayer->bubbleTime = ClipLow(pPlayer->bubbleTime - 4, 0); - } - else if (gGameOptions.nGameType == 0) - { - if (pPlayer->pXSprite->health > 0 && pPlayer->restTime >= 1200 && Chance(0x200)) - { - pPlayer->restTime = -1; + } + else if (gGameOptions.nGameType == 0) + { + if (pPlayer->pXSprite->health > 0 && pPlayer->restTime >= 1200 && Chance(0x200)) + { + pPlayer->restTime = -1; sfxPlay3DSound(pSprite, 3100 + Random(11), 0, 2); - } - } - } + } + } + } ProcessTouchObjects(actor); - } - } + } + } - it.Reset(kStatDude); + it.Reset(kStatDude); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); if (pSprite->flags & 32 || !actor->hasX()) continue; - int nSector = pSprite->sectnum; + int nSector = pSprite->sectnum; viewBackupSpriteLoc(actor); - int nXSector = sector[nSector].extra; + int nXSector = sector[nSector].extra; XSECTOR* pXSector = NULL; - if (nXSector > 0) - { - assert(nXSector > 0 && nXSector < kMaxXSectors); - assert(xsector[nXSector].reference == nSector); - pXSector = &xsector[nXSector]; - } - if (pXSector) - { - int top, bottom; + if (nXSector > 0) + { + assert(nXSector > 0 && nXSector < kMaxXSectors); + assert(xsector[nXSector].reference == nSector); + pXSector = &xsector[nXSector]; + } + if (pXSector) + { + int top, bottom; GetActorExtents(actor, &top, &bottom); - if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= 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 = MulScale(speed, pXSector->busy, 16); - } + if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= 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 = MulScale(speed, pXSector->busy, 16); + } if (sector[nSector].floorstat & 64) angle = (angle + GetWallAngle(sector[nSector].wallptr) + 512) & 2047; - int dx = MulScale(speed, Cos(angle), 30); - int dy = MulScale(speed, Sin(angle), 30); + int dx = MulScale(speed, Cos(angle), 30); + int dy = MulScale(speed, Sin(angle), 30); actor->xvel() += dx; actor->yvel() += dy; - } - } + } + } if (pXSector && pXSector->Underwater) actAirDrag(actor, 5376); else actAirDrag(actor, 128); if ((pSprite->flags & 4) || actor->xvel() || actor->yvel() || actor->zvel() || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) MoveDude(actor); - } + } } //--------------------------------------------------------------------------- @@ -6324,7 +6324,7 @@ void actCheckFlares() { BloodStatIterator it(kStatFlare); while (auto actor = it.Next()) - { + { spritetype* pSprite = &actor->s(); if ((pSprite->flags & 32) || !actor->hasX()) continue; @@ -6335,28 +6335,28 @@ void actCheckFlares() viewBackupSpriteLoc(actor); spritetype* pTarget = &target->s(); auto pXTarget = target->hasX()? &target->x() : nullptr; - if (pTarget->statnum == kMaxStatus) - { - GibSprite(pSprite, GIBTYPE_17, NULL, NULL); + if (pTarget->statnum == kMaxStatus) + { + GibSprite(pSprite, GIBTYPE_17, NULL, NULL); actPostSprite(actor, kStatFree); - } + } if (pXTarget && pXTarget->health > 0) - { + { int x = pTarget->x + mulscale30r(Cos(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); int y = pTarget->y + mulscale30r(Sin(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2); int z = pTarget->z + pXSprite->targetZ; - vec3_t pos = { x, y, z }; + vec3_t pos = { x, y, z }; setsprite(pSprite->index, &pos); actor->xvel() = target->xvel(); actor->yvel() = target->yvel(); actor->zvel() = target->zvel(); - } - else - { - GibSprite(pSprite, GIBTYPE_17, NULL, NULL); + } + else + { + GibSprite(pSprite, GIBTYPE_17, NULL, NULL); actPostSprite(actor, kStatFree); - } - } + } + } } //--------------------------------------------------------------------------- From feb11a2f9a43491ae8e57787c2eb0ef8223f97c8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 23 Aug 2021 19:24:56 +0200 Subject: [PATCH 16/49] - fixed one merge conflict that managed to slip through. --- source/games/blood/src/actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 1084ce51f..5132e0e8d 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5961,7 +5961,7 @@ static void actCheckExplosion() // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions // so only allow this new checking method for dude spawned explosions short gAffectedXWalls[kMaxXWalls]; - const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic + const bool newSectCheckMethod = !cl_bloodvanillaexplosions && Owner && Owner->IsDudeActor() && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod); for (int i = 0; i < kMaxXWalls; i++) From 542f00556589ba1c55355f672a1f248b128f9ddf Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 07:25:52 +1000 Subject: [PATCH 17/49] - Blood: Fixed weapon switching while using Voodoo Doll playing its idle animation. * Fixes #517. --- source/games/blood/src/weapon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 424d69dde..6c15ac795 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -2029,7 +2029,8 @@ void WeaponProcess(PLAYER *pPlayer) { pPlayer->weaponTimer -= 4; bool bShoot = pPlayer->input.actions & SB_FIRE; bool bShoot2 = pPlayer->input.actions & SB_ALTFIRE; - if ((bShoot || bShoot2) && pPlayer->weaponQav == qavGetCorrectID(kQAVVDIDLE2)) pPlayer->weaponTimer = 0; + const int prevNewWeaponVal = pPlayer->input.getNewWeapon(); // used to fix scroll issue for banned weapons + if ((bShoot || bShoot2 || prevNewWeaponVal) && pPlayer->weaponQav == qavGetCorrectID(kQAVVDIDLE2)) pPlayer->weaponTimer = 0; if (pPlayer->qavLoop && pPlayer->pXSprite->health > 0) { if (bShoot && CheckAmmo(pPlayer, pPlayer->weaponAmmo, 1)) @@ -2084,7 +2085,6 @@ void WeaponProcess(PLAYER *pPlayer) { return; break; } - const int prevNewWeaponVal = pPlayer->input.getNewWeapon(); // used to fix scroll issue for banned weapons if (VanillaMode()) { if (pPlayer->nextWeapon) From b1fa923f020581e0af7599c7881ed70e71b3f4d7 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 10:06:54 +1000 Subject: [PATCH 18/49] - Blood: Re-organise `QAVInterpProps` struct so that when statically declaring `forcedinterpdata`, only the required value needs passing. --- source/games/blood/src/qav.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index fb67dbec5..21831b9ac 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -49,8 +49,8 @@ using QAVPrevTileFinder = TILE_FRAME* (*)(FRAMEINFO* const thisFrame, FRAMEINFO* struct QAVInterpProps { - int flags; QAVPrevTileFinder PrevTileFinder; + int flags; TMap> IgnoreData; bool CanInterpFrameTile(const int& nFrame, const int& i) @@ -108,7 +108,7 @@ bool GameInterface::IsQAVInterpTypeValid(const FString& type) void GameInterface::AddQAVInterpProps(const int& res_id, const FString& interptype, const bool& loopable, const TMap>& ignoredata) { - qavInterpProps.Insert(res_id, { loopable ? kQAVIsLoopable : 0, qavGetInterpType(interptype), ignoredata }); + qavInterpProps.Insert(res_id, { qavGetInterpType(interptype), loopable ? kQAVIsLoopable : 0, ignoredata }); } void GameInterface::RemoveQAVInterpProps(const int& res_id) @@ -156,7 +156,7 @@ void DrawFrame(double x, double y, double z, double a, TILE_FRAME *pTile, int st } -static QAVInterpProps forcedinterpdata{ 0, qavGetInterpType("picnum") }; +static QAVInterpProps forcedinterpdata{qavGetInterpType("picnum")}; void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio) { From 5a32000d1e232b5c90a7166d1b48f0e4394c5e36 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 10:07:58 +1000 Subject: [PATCH 19/49] - Blood: Interpolate the alpha and shade values when interpolating QAVs. --- source/games/blood/src/qav.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index 21831b9ac..f556740ab 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -117,25 +117,21 @@ void GameInterface::RemoveQAVInterpProps(const int& res_id) } -void DrawFrame(double x, double y, double z, double a, TILE_FRAME *pTile, int stat, int shade, int palnum, bool to3dview) +void DrawFrame(double x, double y, double z, double a, double alpha, int picnum, int stat, int shade, int palnum, bool to3dview) { - stat |= pTile->stat; - if (palnum <= 0) palnum = pTile->palnum; - if (!to3dview) { - auto tex = tileGetTexture(pTile->picnum); + auto tex = tileGetTexture(picnum); 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; auto translation = TRANSLATION(Translation_Remap, palnum); bool topleft = !!(stat & RS_TOPLEFT); bool xflip = !!(stat & 0x100); // repurposed flag bool yflip = !!(stat & RS_YFLIP); - auto color = shadeToLight(pTile->shade + shade); + auto color = shadeToLight(shade); DrawTexture(twod, tex, x, y, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_Rotate, angle, DTA_LegacyRenderStyle, renderstyle, DTA_Alpha, alpha, DTA_Pin, pin, DTA_TranslationIndex, translation, DTA_TopLeft, topleft, DTA_CenterOffsetRel, !topleft, DTA_FullscreenScale, FSMode_Fit320x200, DTA_FlipOffsets, true, DTA_Color, color, @@ -151,7 +147,7 @@ void DrawFrame(double x, double y, double z, double a, TILE_FRAME *pTile, int st if ((stat & kQavOrientationLeft)) stat |= RS_ALIGN_L; stat &= ~kQavOrientationLeft; - hud_drawsprite(x, y, z, a, pTile->picnum, pTile->shade + shade, palnum, stat); + hud_drawsprite(x, y, z, a, picnum, shade, palnum, stat, alpha); } } @@ -184,6 +180,9 @@ void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, b double tileY = y; double tileZ; double tileA; + double tileAlpha; + int tileShade; + auto const tileStat = stat | thisTile->stat; if (prevTile) { @@ -191,6 +190,10 @@ void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, b tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio); tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio); tileA = interpolatedangle(buildang(prevTile->angle), buildang(thisTile->angle), smoothratio).asbuildf(); + tileShade = interpolatedvalue(prevTile->shade, thisTile->shade, smoothratio) + shade; + auto prevAlpha = ((stat | prevTile->stat) & RS_TRANS1) ? glblend[0].def[!!((stat | prevTile->stat) & RS_TRANS2)].alpha : 1.; + auto thisAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.; + tileAlpha = interpolatedvaluef(prevAlpha, thisAlpha, smoothratio); } else { @@ -198,9 +201,11 @@ void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, b tileY += thisTile->y; tileZ = thisTile->z; tileA = thisTile->angle; + tileShade = thisTile->shade + shade; + tileAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.; } - DrawFrame(tileX, tileY, tileZ, tileA, thisTile, stat, shade, palnum, to3dview); + DrawFrame(tileX, tileY, tileZ, tileA, tileAlpha, thisTile->picnum, tileStat, tileShade, (palnum <= 0 ? thisTile->palnum : palnum), to3dview); } } } From 78b8f7785003b7a4ec21c7d7553246ab7e8d8466 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 11:22:44 +1000 Subject: [PATCH 20/49] - Remove duplicate `grpinfo` definition for "BLOOD: One Unit Whole Blood". --- wadsrc/static/engine/grpinfo.txt | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/wadsrc/static/engine/grpinfo.txt b/wadsrc/static/engine/grpinfo.txt index be490ee49..f6071933c 100644 --- a/wadsrc/static/engine/grpinfo.txt +++ b/wadsrc/static/engine/grpinfo.txt @@ -462,22 +462,6 @@ grpinfo GameID "Blood" } -grpinfo -{ - name "BLOOD: One Unit Whole Blood" - size 9570681 - crc BLOOD_CRC - defname "blood.def" - scriptname "BLOOD.INI" - flags GAMEFLAG_BLOOD - dependency 0 - loadgrp "SOUNDS.RFF", "GUI.RFF" - gamefilter "Blood.Blood" - FgColor 0 - BkColor 0x7f002f - GameID "Blood" -} - grpinfo { // This is for identifying older Blood versions. Since I have no information, all I can do is testing for a few known files. From 90b75247069fc058306ac345442cdc5ee1679b98 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Aug 2021 09:57:36 +0200 Subject: [PATCH 21/49] - SW: fixed episode indexing resulting in bad display on the automap. --- source/games/sw/src/scrip2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/games/sw/src/scrip2.cpp b/source/games/sw/src/scrip2.cpp index 5f316c9fa..e73d93dae 100644 --- a/source/games/sw/src/scrip2.cpp +++ b/source/games/sw/src/scrip2.cpp @@ -509,7 +509,7 @@ void LoadCustomInfoFromScript(const char *filename) curep = sc.Number; if (sc.ParseError) curep = -1; - else if ((unsigned)--curep >= 2u) + else if ((unsigned)curep > 2u) { sc.ScriptMessage("Episode number %d not in range 1-2\n", curep + 1); curep = -1; @@ -808,8 +808,8 @@ void LoadCustomInfoFromScript(const char *filename) break; } } - auto vol0 = MustFindVolume(0); - auto vol1 = MustFindVolume(1); + auto vol0 = MustFindVolume(1); + auto vol1 = MustFindVolume(2); auto map1 = FindMapByLevelNum(1); auto map5 = FindMapByLevelNum(5); if (vol0 && map1) vol0->startmap = map1->labelName; From 68387cd59e6848660d4153d24d170b0d9bccbd7d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 24 Aug 2021 10:08:25 +0200 Subject: [PATCH 22/49] - fixed: List menus still allowed to select unselectable items with the mouse. This was particularly noticable in SW's episode menu with the subtitles. --- wadsrc/static/zscript/engine/ui/menu/listmenu.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs index 14cd07569..cc4656d95 100644 --- a/wadsrc/static/zscript/engine/ui/menu/listmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/listmenu.zs @@ -260,7 +260,7 @@ class ListMenu : Menu { for(int i=0;i Date: Tue, 24 Aug 2021 20:54:33 +1000 Subject: [PATCH 23/49] - Duke: Correctly mark `Duke: Alien World Tour` as a Duke add-on. --- wadsrc/static/engine/grpinfo.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/engine/grpinfo.txt b/wadsrc/static/engine/grpinfo.txt index f6071933c..1806623ff 100644 --- a/wadsrc/static/engine/grpinfo.txt +++ b/wadsrc/static/engine/grpinfo.txt @@ -374,8 +374,9 @@ grpinfo grpinfo { - name "Duke: Alien World Order" - dependency DUKE15_CRC + name "Duke: Alien World Order" + dependency DUKE15_CRC + flags GAMEFLAG_DUKE|GAMEFLAG_ADDON mustcontain "FIREFLYTROOPER.CON", "FLAMETHROWER.CON", "music/E5L1_BulletDam.ogg", "sound/VO_E5L1_Duke_CreamAndSugar.ogg" gamefilter "Duke.Worldtour" GameID "DukeWorldTour" From fd149e50eef0734cd170738e02358fa92da01e63 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 20:56:28 +1000 Subject: [PATCH 24/49] - Remove early return from `GrpScan()` that was allowing addons to come through even if they weren't valid. * Raze configured to only search $PROGDIR with a single `worldtour.grp` file would attempt to autoload even if its dependency CRC wasn't present. Attempted to re-arrange function but had mixed results. Removing this early return is what worked under all test cases. --- source/core/searchpaths.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/core/searchpaths.cpp b/source/core/searchpaths.cpp index df4c6e51c..61d3f8565 100644 --- a/source/core/searchpaths.cpp +++ b/source/core/searchpaths.cpp @@ -840,9 +840,6 @@ TArray GrpScan() sortedFileList.Delete(0, findex + 1); sortedGroupList.Delete(0, gindex + 1); - if (sortedGroupList.Size() == 0 || sortedFileList.Size() == 0) - return foundGames; - for (auto entry : sortedFileList) { GetCRC(entry, cachedCRCs); From d5a4a17ced92fa79a93b8b08c4358a91a62f000e Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Tue, 24 Aug 2021 22:34:56 +1000 Subject: [PATCH 25/49] - Blood: Amend shade issues in QAVs for `KQAVFLARFIR2` (res_id: 43) and `kQAVFLAR2FIR` (res_id: 48) now that we're interpolating shade. --- wadsrc/static/filter/blood/qavs/FLAR2FIR.QAV | Bin 2076 -> 2076 bytes wadsrc/static/filter/blood/qavs/FLARFIR2.QAV | Bin 1668 -> 1668 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/filter/blood/qavs/FLAR2FIR.QAV b/wadsrc/static/filter/blood/qavs/FLAR2FIR.QAV index 770bd07737066ebf078672227d66573a18ef528e..2c7c17962bfc5cae2d7db86ea4fc2429676945ef 100644 GIT binary patch delta 100 zcmbOuFh^iQ#pDCb1`}6E@Tc-HFxWCMFr4`R|33o*-;rnS6!WVsZ&n27)UyS%tX; d!u6P3z{E0{hvf((!{m!Brx_VG&t9sd9T diff --git a/wadsrc/static/filter/blood/qavs/FLARFIR2.QAV b/wadsrc/static/filter/blood/qavs/FLARFIR2.QAV index d235c29ff1ed4405a9b8eb3589928fef5d61b2e0..275c4c5075f6046f2d62b0a67e38ababefda2982 100644 GIT binary patch delta 14 VcmZqSZQ-3zG1-MtWMj_{Rsbcz1yKM1 delta 14 VcmZqSZQ-3zF?j;B#Ks9 Date: Tue, 24 Aug 2021 18:39:54 +0200 Subject: [PATCH 26/49] - Blood: don't abort the INI scanner if it finds a file with resource file index 0. 0 is also used for on-the-fly addition of data to the file system, so this must run through the entire directory to be safe. --- source/games/blood/src/levels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index a4692c6fe..230008145 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -120,7 +120,7 @@ static const char* DefFile(void) for (int i = numlumps - 1; i >= 0; i--) { int fileno = fileSystem.GetFileContainer(i); - if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) break; + if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue; FString fn = fileSystem.GetFileFullName(i, false); FString ext = fn.Right(4); if (ext.CompareNoCase(".ini") == 0) From 0cad0b9258114ab8231bf1233503496350580c02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 25 Aug 2021 08:46:31 +0200 Subject: [PATCH 27/49] - reformatting the mess created by TortoiseMerge. --- source/games/blood/src/actor.cpp | 238 +++++++++++++++---------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 5132e0e8d..cad56fbb7 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -2408,7 +2408,7 @@ static void actInitThings() #endif pXSprite->state = 0; break; - case kThingBloodChunks: + case kThingBloodChunks: { SEQINST* pInst = GetInstance(3, pSprite->extra); if (pInst) @@ -2529,12 +2529,12 @@ static void actInitDudes() void actInit(bool bSaveLoad) { - - #ifdef NOONE_EXTENSIONS + +#ifdef NOONE_EXTENSIONS if (!gModernMap) nnExtResetGlobals(); else nnExtInitModernStuff(bSaveLoad); - #endif - +#endif + BloodStatIterator it(kStatItem); while (auto act = it.Next()) { @@ -2951,7 +2951,7 @@ static bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType) auto pXSprite = &actor->x(); GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); removeDudeStuff(pSprite); - if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == nullptr) + if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == nullptr) { if (pExtra->weaponType == kGenDudeWeaponKamikaze && Chance(0x4000) && damageType != kDamageSpirit && damageType != kDamageDrown) { @@ -3485,7 +3485,7 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag } auto Owner = actor->GetOwner(); - switch (pSprite->type) + switch (pSprite->type) { case kDudeZombieAxeNormal: zombieAxeNormalDeath(actor, nSeq); @@ -4197,10 +4197,10 @@ static void actTouchFloor(DBloodActor* actor, int nSector) bool doDamage = (pXSector && (pSector->type == kSectorDamage || pXSector->damageType > 0)); // don't allow damage for damage sectors if they are not enabled - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS if (gModernMap && doDamage && pSector->type == kSectorDamage && !pXSector->state) doDamage = false; - #endif +#endif if (doDamage) { DAMAGE_TYPE nDamageType; @@ -4665,14 +4665,14 @@ int MoveThing(DBloodActor* actor) actWallBounceVector(&actor->xvel(), &actor->yvel(), nHitWall, pThingInfo->elastic); switch (pSprite->type) { - case kThingZombieHead: - sfxPlay3DSound(pSprite, 607, 0, 0); + case kThingZombieHead: + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - break; + break; - case kThingKickablePail: - sfxPlay3DSound(pSprite, 374, 0, 0); - break; + case kThingKickablePail: + sfxPlay3DSound(pSprite, 374, 0, 0); + break; } } } @@ -4739,22 +4739,22 @@ int MoveThing(DBloodActor* actor) switch (pSprite->type) { - case kThingNapalmBall: + case kThingNapalmBall: if (actor->zvel() == 0 || Chance(0xA000)) actNapalmMove(actor); - break; + break; - case kThingZombieHead: + case kThingZombieHead: if (abs(actor->zvel()) > 0x80000) { - sfxPlay3DSound(pSprite, 607, 0, 0); + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - } - break; + } + break; - case kThingKickablePail: + case kThingKickablePail: if (abs(actor->zvel()) > 0x80000) - sfxPlay3DSound(pSprite, 374, 0, 0); - break; + sfxPlay3DSound(pSprite, 374, 0, 0); + break; } lhit = kHitSector | nSector; @@ -4783,18 +4783,18 @@ int MoveThing(DBloodActor* actor) switch (pSprite->type) { - case kThingZombieHead: + case kThingZombieHead: if (abs(actor->zvel()) > 0x80000) { - sfxPlay3DSound(pSprite, 607, 0, 0); + sfxPlay3DSound(pSprite, 607, 0, 0); actDamageSprite(nullptr, actor, kDamageFall, 80); - } - break; + } + break; - case kThingKickablePail: + case kThingKickablePail: if (abs(actor->zvel()) > 0x80000) - sfxPlay3DSound(pSprite, 374, 0, 0); - break; + sfxPlay3DSound(pSprite, 374, 0, 0); + break; } } } @@ -4911,8 +4911,8 @@ void MoveDude(DBloodActor* actor) if (!gModernMap && pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) trTriggerSprite(coll.actor, kCmdSpriteTouch); #else - if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) - trTriggerSprite(coll.actor, kCmdSpriteTouch); + if (pHitXSprite && pHitXSprite->Touch && !pHitXSprite->state && !pHitXSprite->isTriggered) + trTriggerSprite(coll.actor, kCmdSpriteTouch); #endif if (pDudeInfo->lockOut && pHitXSprite && pHitXSprite->Push && !pHitXSprite->key && !pHitXSprite->DudeLockout && !pHitXSprite->state && !pHitXSprite->busy && !pPlayer) @@ -5023,7 +5023,7 @@ void MoveDude(DBloodActor* actor) if (bUnderwater) vc = 0; else if (bottom >= floorZ) - vc = 0; + vc = 0; } if (vc) { @@ -5085,13 +5085,13 @@ void MoveDude(DBloodActor* actor) break; case kDudeBoneEel: actKillDude(pSprite->index, pSprite, kDamageFall, 1000 << 4); - break; + break; } - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS if (IsDudeSprite(pSprite) && pXSprite->health > 0 && aiInPatrolState(nAiStateType)) aiPatrolState(pSprite, kAiStatePatrolMoveL); // continue patrol when going from water - #endif +#endif } break; case kMarkerUpWater: @@ -5109,13 +5109,13 @@ void MoveDude(DBloodActor* actor) { #ifdef NOONE_EXTENSIONS // look for palette in data2 of marker. If value <= 0, use default ones. - if (gModernMap) + if (gModernMap) { pPlayer->nWaterPal = 0; - auto pUpper = getUpperLink(nSector); - if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; + auto pUpper = getUpperLink(nSector); + if (pUpper && pUpper->hasX()) pPlayer->nWaterPal = pUpper->x().data2; } - #endif +#endif pPlayer->posture = 1; pXSprite->burnTime = 0; @@ -5144,9 +5144,9 @@ void MoveDude(DBloodActor* actor) if (fixRandomCultist) // fix burning cultists randomly switching types underwater pSprite->type = pSprite->inittype; // restore back to spawned cultist type pXSprite->burnTime = 0; - evPost(actor, 0, kCallbackEnemeyBubble); + evPost(actor, 0, kCallbackEnemeyBubble); sfxPlay3DSound(pSprite, 720, -1, 0); - aiNewState(actor, &cultistSwimGoto); + aiNewState(actor, &cultistSwimGoto); break; } case kDudeZombieAxeNormal: @@ -5181,7 +5181,7 @@ void MoveDude(DBloodActor* actor) break; } - #ifdef NOONE_EXTENSIONS +#ifdef NOONE_EXTENSIONS if (gModernMap) { if (pSprite->type == kDudeModernCustom) { @@ -5196,13 +5196,13 @@ void MoveDude(DBloodActor* actor) aiPatrolState(pSprite, kAiStatePatrolMoveW); } - #endif +#endif } break; } - } - } + } + } GetActorExtents(actor, &top, &bottom); if (pPlayer && bottom >= floorZ) { @@ -5342,9 +5342,9 @@ int MoveMissile(DBloodActor* actor) if (Owner && Owner->IsDudeActor()) { pOwner = &Owner->s(); - bakCstat = pOwner->cstat; - pOwner->cstat &= ~257; - } + bakCstat = pOwner->cstat; + pOwner->cstat &= ~257; + } gHitInfo.hitsect = -1; gHitInfo.hitwall = -1; gHitInfo.hitsprite = -1; @@ -5408,19 +5408,19 @@ int MoveMissile(DBloodActor* actor) { gHitInfo.hitsprite = clipmoveresult.legacyVal; cliptype = 3; - } + } else if (clipmoveresult.type == kHitWall) - { + { gHitInfo.hitwall = clipmoveresult.index; if (wall[clipmoveresult.index].nextsector == -1) cliptype = 0; - else - { - int32_t fz, cz; + else + { + int32_t fz, cz; getzsofslope(wall[clipmoveresult.index].nextsector, x, y, &cz, &fz); if (z <= cz || z >= fz) cliptype = 0; else cliptype = 4; - } } + } if (cliptype == 4) { walltype* pWall = &wall[gHitInfo.hitwall]; @@ -5688,15 +5688,15 @@ static void actCheckProximity() if (pSprite->flags & 32) continue; if (actor->hasX()) - { + { XSPRITE* pXSprite = &actor->x(); switch (pSprite->type) { - case kThingBloodBits: - case kThingBloodChunks: - case kThingZombieHead: - if (pXSprite->locked && PlayClock >= pXSprite->targetX) pXSprite->locked = 0; - break; + case kThingBloodBits: + case kThingBloodChunks: + case kThingZombieHead: + if (pXSprite->locked && PlayClock >= pXSprite->targetX) pXSprite->locked = 0; + break; } if (pXSprite->burnTime > 0) @@ -5752,21 +5752,21 @@ static void actCheckProximity() { switch (pSprite->type) { - case kThingDroppedLifeLeech: + case kThingDroppedLifeLeech: if (!Chance(0x4000) && nextdude) continue; - if (pSprite2->cstat & CLIPMASK0) pXSprite->target = pSprite2->index; - else continue; - break; + if (pSprite2->cstat & CLIPMASK0) pXSprite->target = pSprite2->index; + else continue; + break; #ifdef NOONE_EXTENSIONS - case kModernThingTNTProx: + case kModernThingTNTProx: if (!dudeactor->IsPlayerActor()) continue; - pSprite->pal = 0; - break; + pSprite->pal = 0; + break; - case kModernThingEnemyLifeLeech: - if (pXSprite->target != pSprite2->index) continue; - break; + case kModernThingEnemyLifeLeech: + if (pXSprite->target != pSprite2->index) continue; + break; #endif default: @@ -5851,50 +5851,50 @@ static void actCheckThings() switch (pSprite->type) { - case kThingDripWater: - case kThingDripBlood: - MakeSplash(&bloodActors[pXSprite->reference]); - break; + case kThingDripWater: + case kThingDripBlood: + MakeSplash(&bloodActors[pXSprite->reference]); + break; #ifdef NOONE_EXTENSIONS - case kModernThingThrowableRock: + case kModernThingThrowableRock: seqSpawn(24, actor, -1); if (hit.type = kHitSprite) - { - pSprite->xrepeat = 32; - pSprite->yrepeat = 32; + { + pSprite->xrepeat = 32; + pSprite->yrepeat = 32; actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, pXSprite->data1); - } - break; + } + break; #endif - case kThingBone: + case kThingBone: seqSpawn(24, actor, -1); if (hit.type = kHitSprite) - { + { actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); - } - break; + } + break; - case kThingPodGreenBall: + case kThingPodGreenBall: if (hit.type == kHitSector) - { + { actRadiusDamage(actor->GetOwner(), pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, kDamageExplode, 6, 0); evPost(actor, 0, kCallbackFXPodBloodSplat); - } + } else if (hit.type == kHitSprite) - { + { actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); evPost(actor, 0, kCallbackFXPodBloodSplat); - } - break; + } + break; - case kThingPodFireBall: + case kThingPodFireBall: if (hit.type == kHitSprite) actExplodeSprite(actor); - break; - } - } + break; } } } + } + } } //--------------------------------------------------------------------------- @@ -5963,7 +5963,7 @@ static void actCheckExplosion() short gAffectedXWalls[kMaxXWalls]; const bool newSectCheckMethod = !cl_bloodvanillaexplosions && Owner && Owner->IsDudeActor() && !VanillaMode(); // use new sector checking logic GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod); - + for (int i = 0; i < kMaxXWalls; i++) { int nWall = gAffectedXWalls[i]; @@ -6043,20 +6043,20 @@ static void actCheckExplosion() #ifdef NOONE_EXTENSIONS if (pXSprite->data1 != 0) { - // add impulse for sprites from physics list + // add impulse for sprites from physics list if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0) { for (int i = 0; i < gPhysSpritesCount; i++) { - if (gPhysSpritesList[i] == -1) continue; + if (gPhysSpritesList[i] == -1) continue; auto physactor = &bloodActors[gPhysSpritesList[i]]; spritetype* pDebris = &physactor->s(); if (pDebris->sectnum < 0 || (pDebris->flags & kHitagFree) != 0) continue; if (!TestBitString(sectormap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; else debrisConcuss(Owner ? Owner->s().index : -1, i, x, y, z, pExplodeInfo->dmgType); + } } - } // trigger sprites from impact list if (gImpactSpritesCount > 0) { @@ -6075,7 +6075,7 @@ static void actCheckExplosion() continue; trTriggerSprite(impactsprite->index, pXImpact, kCmdSpriteImpact); - } + } } } @@ -6195,7 +6195,7 @@ static void actCheckDudes() { actor->xvel() = actor->yvel() = 0; if (seqGetStatus(actor) < 0) genDudeTransform(pSprite); - } + } #endif if (pSprite->type == kDudeCerberusTwoHead) { @@ -6334,7 +6334,7 @@ void actCheckFlares() viewBackupSpriteLoc(actor); spritetype* pTarget = &target->s(); - auto pXTarget = target->hasX()? &target->x() : nullptr; + auto pXTarget = target->hasX() ? &target->x() : nullptr; if (pTarget->statnum == kMaxStatus) { GibSprite(pSprite, GIBTYPE_17, NULL, NULL); @@ -6378,8 +6378,8 @@ void actProcessSprites(void) actCheckTraps(); actCheckDudes(); actCheckFlares(); - aiProcessDudes(); - gFX.fxProcess(); + aiProcessDudes(); + gFX.fxProcess(); } //--------------------------------------------------------------------------- @@ -6390,30 +6390,30 @@ void actProcessSprites(void) DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool setextra) { - int nSprite = InsertSprite(nSector, nStat); + int nSprite = InsertSprite(nSector, nStat); if (nSprite >= 0) sprite[nSprite].extra = -1; - else - { + else + { BloodStatIterator it(kStatPurge); - nSprite = it.NextIndex(); - assert(nSprite >= 0); - assert(nSector >= 0 && nSector < kMaxSectors); - ChangeSpriteSect(nSprite, nSector); - actPostSprite(nSprite, nStat); - } + nSprite = it.NextIndex(); + assert(nSprite >= 0); + assert(nSector >= 0 && nSector < kMaxSectors); + ChangeSpriteSect(nSprite, nSector); + actPostSprite(nSprite, nStat); + } DBloodActor* actor = &bloodActors[nSprite]; - vec3_t pos = { x, y, z }; - setsprite(nSprite, &pos); + vec3_t pos = { x, y, z }; + setsprite(nSprite, &pos); spritetype* pSprite = &actor->s(); - pSprite->type = kSpriteDecoration; + pSprite->type = kSpriteDecoration; if (setextra && !actor->hasX()) - { + { actor->addExtra(); actor->hit().florhit = 0; actor->hit().ceilhit = 0; if (!VanillaMode()) actor->SetTarget(nullptr); - } + } return actor; } From c80831555ca34bd84e6ca13fa3412726589a1452 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 25 Aug 2021 08:47:40 +0200 Subject: [PATCH 28/49] - Blood: fixed broken missile collision checks. Curse that stupid bit masking madness in clipmove. As long as this code isn't properly abstracted, we still need to handle it on the game side. --- source/games/blood/src/actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index cad56fbb7..c16cbd986 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5406,7 +5406,7 @@ int MoveMissile(DBloodActor* actor) } if (clipmoveresult.type == kHitSprite) { - gHitInfo.hitsprite = clipmoveresult.legacyVal; + gHitInfo.hitsprite = clipmoveresult.legacyVal & kHitIndexMask; cliptype = 3; } else if (clipmoveresult.type == kHitWall) From 957a23d2820d54f5e92ae6227104f35a7cdc4b1b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 25 Aug 2021 11:09:38 +0300 Subject: [PATCH 29/49] - updated continuous integration workflow * Switch from macOS 10.15 to 11, Xcode 12.4 to 12.5 * Switch from Clang 11 to 12 * Remove no longer needed workaround for Clang 6 with GCC 11 deinstallation --- .github/workflows/continuous_integration.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index a5d8495a0..8a8197a26 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -24,13 +24,13 @@ jobs: } - { name: "macOS", - os: macos-10.15, + os: macos-11, deps_cmdline: "brew install libvpx", build_type: "Release" } - { name: "macOS", - os: macos-10.15, + os: macos-11, extra_options: "-DDYN_FLUIDSYNTH=OFF -DDYN_OPENAL=OFF -DDYN_SNDFILE=OFF -DDYN_MPG123=OFF", deps_cmdline: "brew install libvpx fluidsynth mpg123 libsndfile", build_type: "Debug" @@ -54,14 +54,14 @@ jobs: os: ubuntu-20.04, extra_options: "-DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 \ -DDYN_FLUIDSYNTH=OFF -DDYN_OPENAL=OFF -DDYN_SNDFILE=OFF -DDYN_MPG123=OFF", - deps_cmdline: "sudo apt update && sudo apt remove gcc-11 libgcc-11-dev g++-11 libstdc++-11-dev && sudo apt install clang-6.0 libstdc++-9-dev libsdl2-dev libvpx-dev libopenal-dev libfluidsynth-dev libmpg123-dev libsndfile1-dev", + deps_cmdline: "sudo apt update && sudo apt install clang-6.0 libsdl2-dev libvpx-dev libopenal-dev libfluidsynth-dev libmpg123-dev libsndfile1-dev", build_type: "Debug" } - { - name: "Linux Clang 11", + name: "Linux Clang 12", os: ubuntu-20.04, - extra_options: "-DCMAKE_C_COMPILER=clang-11 -DCMAKE_CXX_COMPILER=clang++-11", - deps_cmdline: "sudo apt update && sudo apt install clang-11 libsdl2-dev libvpx-dev", + extra_options: "-DCMAKE_C_COMPILER=clang-12 -DCMAKE_CXX_COMPILER=clang++-12", + deps_cmdline: "sudo apt update && sudo apt install clang-12 libsdl2-dev libvpx-dev", build_type: "Release" } From f44d6952457b956df88ba9b5c4dbda0148f0cd8e Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Thu, 26 Aug 2021 10:33:24 +1000 Subject: [PATCH 30/49] - Fix some warning messages in the `defineqav` DEF parser. --- source/core/defparser.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/core/defparser.cpp b/source/core/defparser.cpp index da0cb5840..64a1080cc 100644 --- a/source/core/defparser.cpp +++ b/source/core/defparser.cpp @@ -2026,7 +2026,7 @@ static bool parseDefineQAVInterpolateIgnoreBlock(FScanner& sc, const int& res_id if (sc.StartBraces(&blockend)) { - pos.Message(MSG_ERROR, "defineqav (%d): interpolate: malformed syntax, unable to continue", res_id); + pos.Message(MSG_ERROR, "defineqav (%d): interpolate: ignore: malformed syntax, unable to continue", res_id); return false; } while (!sc.FoundEndBrace(blockend)) @@ -2039,7 +2039,7 @@ static bool parseDefineQAVInterpolateIgnoreBlock(FScanner& sc, const int& res_id // Confirm we received something for 'frames' and 'tiles'. if (scframes.IsEmpty() || sctiles.IsEmpty()) { - pos.Message(MSG_ERROR, "defineqav (%d): interpolate: unable to get any values for 'frames' or 'tiles', unable to continue", res_id); + pos.Message(MSG_ERROR, "defineqav (%d): interpolate: ignore: unable to get any values for 'frames' or 'tiles', unable to continue", res_id); return false; } @@ -2102,7 +2102,7 @@ static bool parseDefineQAVInterpolateBlock(FScanner& sc, const int& res_id, cons if (sc.StartBraces(&blockend)) { - pos.Message(MSG_ERROR, "defineqav (%d): interpolate (%s): malformed syntax, unable to continue", res_id, interptype.GetChars()); + pos.Message(MSG_ERROR, "defineqav (%d): interpolate: malformed syntax, unable to continue", res_id); return false; } while (!sc.FoundEndBrace(blockend)) @@ -2112,13 +2112,13 @@ static bool parseDefineQAVInterpolateBlock(FScanner& sc, const int& res_id, cons { if (interptype.IsNotEmpty()) { - pos.Message(MSG_ERROR, "defineqav (%d): interpolate (%s): more than one interpolation type defined, unable to continue", res_id, interptype.GetChars()); + pos.Message(MSG_ERROR, "defineqav (%d): interpolate: more than one interpolation type defined, unable to continue", res_id); return false; } sc.GetString(interptype); if (!gi->IsQAVInterpTypeValid(interptype)) { - pos.Message(MSG_ERROR, "defineqav (%d): interpolate (%s): interpolation type not found", res_id, interptype.GetChars()); + pos.Message(MSG_ERROR, "defineqav (%d): interpolate: interpolation type not found", res_id); return false; } } From 37f8fc8b0d92d1e2ca16770a44b2b43c39162f10 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Thu, 26 Aug 2021 10:34:00 +1000 Subject: [PATCH 31/49] - Allow disabling of load screens like how they were before the move of ScreenJob from native code to ZScript. --- source/core/gamecvars.cpp | 1 + source/core/gamecvars.h | 1 + source/core/screenjob.cpp | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/core/gamecvars.cpp b/source/core/gamecvars.cpp index 35982b9dd..87df2e201 100644 --- a/source/core/gamecvars.cpp +++ b/source/core/gamecvars.cpp @@ -90,6 +90,7 @@ CVARD(Bool, cl_bloodqavinterp, true, CVAR_ARCHIVE, "enable/disable Blood's QAV i CVARD(Bool, cl_bloodqavforcedinterp, false, CVAR_ARCHIVE, "enable/disable Blood's QAV interpolation forcefully for QAVs that aren't defined as interpolatable") CVARD(Bool, cl_bloodweapinterp, false, CVAR_ARCHIVE, "enable/disable Blood's weapon interpolation. Depends on 'cl_bloodqavinterp'") CVARD(Bool, cl_bloodoldweapbalance, false, CVAR_ARCHIVE, "enable/disable legacy 1.0 weapon handling for Blood") +CVARD(Bool, cl_loadingscreens, true, CVAR_ARCHIVE, "enable/disable loading screens for games") CUSTOM_CVARD(Int, cl_autoaim, 1, CVAR_ARCHIVE|CVAR_USERINFO, "enable/disable weapon autoaim") diff --git a/source/core/gamecvars.h b/source/core/gamecvars.h index 99dfc7798..acbe197eb 100644 --- a/source/core/gamecvars.h +++ b/source/core/gamecvars.h @@ -35,6 +35,7 @@ EXTERN_CVAR(Bool, cl_bloodqavinterp) EXTERN_CVAR(Bool, cl_bloodqavforcedinterp) EXTERN_CVAR(Bool, cl_bloodweapinterp) EXTERN_CVAR(Bool, cl_bloodoldweapbalance) +EXTERN_CVAR(Bool, cl_loadingscreens) EXTERN_CVAR(Bool, demorec_seeds_cvar) EXTERN_CVAR(Bool, demoplay_diffs) diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index c0ac0722f..871fddca5 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -222,10 +222,10 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C if (tocluster == nullptr || !CreateCutscene(&tocluster->intro, runner, toMap, !!fromMap)) CreateCutscene(&globalCutscenes.DefaultMapIntro, runner, toMap, !!fromMap); } - // Skip the load screen if the level is started from the console. + // Skip the load screen if the level is started from the console or loading screens are disabled. // In this case the load screen is not helpful as it blocks the actual level start, // requiring closing and reopening the console first before entering any commands that need the level. - if (ConsoleState == c_up || ConsoleState == c_rising) + if ((ConsoleState == c_up || ConsoleState == c_rising) && cl_loadingscreens) CreateCutscene(&globalCutscenes.LoadingScreen, runner, toMap, true); } else if (isShareware()) From 6d06f063f6c1c8e18c3ccc61c4b580866471afc2 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Thu, 26 Aug 2021 11:19:42 +1000 Subject: [PATCH 32/49] - Blood: Directly use the incoming `loopable` bool from `gi->AddQAVInterpProps()` in the `QAVInterpProps` struct. * During the initial implementation, there were more flags than this single one. I don't foresee any further flags coming so lets go for cleaner code. --- source/games/blood/src/qav.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index f556740ab..b4533c323 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -40,17 +40,12 @@ extern void (*qavClientCallback[])(int, void *); // //========================================================================== -enum -{ - kQAVIsLoopable = 1 << 0, -}; - using QAVPrevTileFinder = TILE_FRAME* (*)(FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int& i); struct QAVInterpProps { QAVPrevTileFinder PrevTileFinder; - int flags; + bool loopable; TMap> IgnoreData; bool CanInterpFrameTile(const int& nFrame, const int& i) @@ -108,7 +103,7 @@ bool GameInterface::IsQAVInterpTypeValid(const FString& type) void GameInterface::AddQAVInterpProps(const int& res_id, const FString& interptype, const bool& loopable, const TMap>& ignoredata) { - qavInterpProps.Insert(res_id, { qavGetInterpType(interptype), loopable ? kQAVIsLoopable : 0, ignoredata }); + qavInterpProps.Insert(res_id, { qavGetInterpType(interptype), loopable, ignoredata }); } void GameInterface::RemoveQAVInterpProps(const int& res_id) @@ -164,7 +159,7 @@ void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, b auto const nFrame = clamp(ticks / ticksPerFrame, 0, nFrames - 1); FRAMEINFO* const thisFrame = &frames[nFrame]; - auto const oFrame = clamp((nFrame == 0 && (interpdata && (interpdata->flags & kQAVIsLoopable)) ? nFrames : nFrame) - 1, 0, nFrames - 1); + auto const oFrame = clamp((nFrame == 0 && interpdata && interpdata->loopable ? nFrames : nFrame) - 1, 0, nFrames - 1); FRAMEINFO* const prevFrame = &frames[oFrame]; bool const interpolate = interpdata && cl_hudinterpolation && cl_bloodqavinterp && (nFrames > 1) && (nFrame != oFrame) && (smoothratio != MaxSmoothRatio); From 03e6bb36960659c29c33ba5980cbf8b017dc1f18 Mon Sep 17 00:00:00 2001 From: carnivoroussociety <38839485+carnivoroussociety@users.noreply.github.com> Date: Thu, 26 Aug 2021 09:16:09 +1000 Subject: [PATCH 33/49] Skip CheckProximityWall when newSectCheckMethod is set Fixes edge case where CheckProximityWall misses --- source/games/blood/src/gameutil.cpp | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source/games/blood/src/gameutil.cpp b/source/games/blood/src/gameutil.cpp index 2840c85f8..f9318e3ca 100644 --- a/source/games/blood/src/gameutil.cpp +++ b/source/games/blood/src/gameutil.cpp @@ -869,8 +869,12 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect if (TestBitString(sectbits, nNextSector)) // if we've already checked this sector, skip continue; bool setSectBit = true; - bool withinRange = CheckProximityWall(pWall->point2, x, y, nDist); - if (newSectCheckMethod && !withinRange) // if range check failed, try comparing midpoints/subdivides of wall span + bool withinRange = false; + if (!newSectCheckMethod) // original method + { + withinRange = CheckProximityWall(pWall->point2, x, y, nDist); + } + else // new method - first test edges and then wall span midpoints { for (int k = (j+1); k < nEndWall; k++) // scan through the rest of the sector's walls { @@ -884,27 +888,34 @@ int GetClosestSpriteSectors(int nSector, int x, int y, int nDist, uint8_t *pSect const int nWallB = wall[nWallA].point2; int x1 = wall[nWallA].x, y1 = wall[nWallA].y; int x2 = wall[nWallB].x, y2 = wall[nWallB].y; + int point1Dist = approxDist(x-x1, y-y1); // setup edge distance needed for below loop (determines which point to shift closer to center) + int point2Dist = approxDist(x-x2, y-y2); int nLength = approxDist(x1-x2, y1-y2); - const int nDist2 = (nDist+(nDist>>1))<<4; - nLength = ClipRange(nLength / nDist2, 1, 4); // never split more than 4 times - for (int k = 0; true; k++) // subdivide span into smaller chunks towards direction + const int nDist4 = nDist<<4; + nLength = ClipRange(nLength / (nDist4+(nDist4>>1)), 1, 4); // always test midpoint at least once, and never split more than 4 times + for (int k = 0; true; k++) // check both points of wall and subdivide span into smaller chunks towards target { - const int xcenter = (x1+x2)>>1, ycenter = (y1+y2)>>1; - withinRange = CheckProximityPoint(xcenter, ycenter, 0, x, y, 0, nDist); + withinRange = (point1Dist < nDist4) || (point2Dist < nDist4); // check if both points of span is within radius if (withinRange) break; - if (k == (nLength-1)) // reached end + if (k == nLength) // reached end break; - const bool bDir = approxDist(x-x1, y-y1) < approxDist(x-x2, y-y2); - if (bDir) // step closer and check again + const int xcenter = (x1+x2)>>1, ycenter = (y1+y2)>>1; + if (point1Dist < point2Dist) // shift closest side of wall towards target point, and refresh point distance values + { x2 = xcenter, y2 = ycenter; + point2Dist = approxDist(x-x2, y-y2); + } else + { x1 = xcenter, y1 = ycenter; + point1Dist = approxDist(x-x1, y-y1); + } } } if (withinRange) // if new sector is within range, set to current sector and test walls { - setSectBit = true; // sector is within range, set as checked + setSectBit = true; // sector is within range, set the sector as checked if (pSectBit) SetBitString(pSectBit, nNextSector); pSectors[n++] = nNextSector; From 1fbaeceadabb14dedadc0ce1624c0ff4d5bb531e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 26 Aug 2021 08:10:18 +0200 Subject: [PATCH 34/49] - Blood: avoid double free of sprites. This happened to me once in Death Wish. --- source/games/blood/src/actor.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index c16cbd986..6937f6fa4 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -7272,10 +7272,13 @@ void actPostProcess(void) int nStatus = pPost->status; if (nStatus == kStatFree) { - evKill(nSprite, 3); - if (sprite[nSprite].extra > 0) - seqKill(3, sprite[nSprite].extra); - DeleteSprite(nSprite); + if (pSprite->statnum != kStatFree) + { + evKill(nSprite, 3); + if (sprite[nSprite].extra > 0) + seqKill(3, pSprite->extra); + DeleteSprite(nSprite); + } } else ChangeSpriteStat(nSprite, nStatus); From 9b061f9829230d20c4e06cac60502facf0851f99 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 26 Aug 2021 08:16:43 +0200 Subject: [PATCH 35/49] - Blood: fixed crash with Gargoyle projectiles. Thanks, MSVC, for not warning about this... :( --- source/games/blood/src/actor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 6937f6fa4..786425833 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5858,7 +5858,7 @@ static void actCheckThings() #ifdef NOONE_EXTENSIONS case kModernThingThrowableRock: seqSpawn(24, actor, -1); - if (hit.type = kHitSprite) + if (hit.type == kHitSprite) { pSprite->xrepeat = 32; pSprite->yrepeat = 32; @@ -5868,7 +5868,7 @@ static void actCheckThings() #endif case kThingBone: seqSpawn(24, actor, -1); - if (hit.type = kHitSprite) + if (hit.type == kHitSprite) { actDamageSprite(actor->GetOwner(), hit.actor, kDamageFall, 12); } From e010dce8129f7dfbe090bb917127671172b09cdf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 26 Aug 2021 09:31:32 +0200 Subject: [PATCH 36/49] - Blood: fixed occasionally disappearing sprites when hitting something with the tesla gun. --- source/games/blood/src/actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 786425833..3d0228cdc 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -4904,7 +4904,7 @@ void MoveDude(DBloodActor* actor) { HITINFO hitInfo = gHitInfo; gHitInfo.hitsprite = pSprite->index; - actImpactMissile(actor, 3); + actImpactMissile(coll.actor, 3); gHitInfo = hitInfo; } #ifdef NOONE_EXTENSIONS From f3e10a595d13f132c268acb23d9a3a8b6e49cdb4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Aug 2021 13:25:01 +0200 Subject: [PATCH 37/49] - Blood: fixed pod fireballs not exploding. Looks like something went wrong with cleaning out the broken code that once was here. --- source/games/blood/src/actor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index 3d0228cdc..f6c6aa621 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -5888,7 +5888,7 @@ static void actCheckThings() break; case kThingPodFireBall: - if (hit.type == kHitSprite) actExplodeSprite(actor); + actExplodeSprite(actor); break; } } From 656ec8ef06611056514dcd9e50035944295d44de Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Fri, 27 Aug 2021 22:18:57 +1000 Subject: [PATCH 38/49] - Blood: Apply a slightly better fix for the akimbo shotgun animation `kQAV2SHOTF2` (res_id: 61). * The issue here is that `pPlayer->weaponTimer` reaches 0 before the animation plays out. This is because the QAV timer has its own ticrate independent of the game's timer. * A workaround like this is still the best approach for now as its not easily possible to remove `weaponTimer` within the game without messing up the trigger system that runs at ticrate. --- source/games/blood/src/qav.cpp | 4 ++-- source/games/blood/src/qav.h | 2 +- source/games/blood/src/weapon.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index b4533c323..1604f4d18 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -286,7 +286,7 @@ 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) +void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration, bool const ignoreWeaponTimer) { // Process if not paused. if (!paused) @@ -294,7 +294,7 @@ void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, doub // Process clock based on QAV's ticrate and last tick value. qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick); - if (pPlayer->weaponTimer == 0) + if (pPlayer->weaponTimer == 0 && !ignoreWeaponTimer) { // Check if we're playing an idle QAV as per the ticker's weapon timer. *duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration; diff --git a/source/games/blood/src/qav.h b/source/games/blood/src/qav.h index aca60789a..aa0e2bad5 100644 --- a/source/games/blood/src/qav.h +++ b/source/games/blood/src/qav.h @@ -240,7 +240,7 @@ 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); +void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration = false, bool const ignoreWeaponTimer = false); inline bool qavIsOriginal(const int& res_id) { diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 6c15ac795..5b4361b35 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -256,7 +256,7 @@ void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum int duration; double smoothratio; - qavProcessTimer(pPlayer, pQAV, &duration, &smoothratio, pPlayer->weaponState == -1 || (pPlayer->curWeapon == kWeapShotgun && pPlayer->weaponState == 7)); + qavProcessTimer(pPlayer, pQAV, &duration, &smoothratio, pPlayer->weaponState == -1, pPlayer->curWeapon == kWeapShotgun && pPlayer->weaponState == 7); pQAV->x = int(xpos); pQAV->y = int(ypos); From dc0d2012752ff1d4cae342ee46063be14bad1db0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Aug 2021 18:21:01 +0200 Subject: [PATCH 39/49] - Blood: added serialization for the tracking conditions array. --- source/games/blood/src/nnexts.cpp | 32 ++++++++++++++++++++++++++++++- source/games/blood/src/nnexts.h | 10 +++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index c8539a6ec..6fed49f2d 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -1919,7 +1919,7 @@ void trPlayerCtrlLink(XSPRITE* pXSource, PLAYER* pPlayer, bool checkCondition) { for (unsigned k = 0; k < pCond->length; k++) { if (pCond->obj[k].type != OBJ_SPRITE || pCond->obj[k].index != pXSource->reference) continue; pCond->obj[k].index = pPlayer->nSprite; - pCond->obj[k].cmd = pPlayer->pXSprite->command; + pCond->obj[k].cmd = (uint8_t)pPlayer->pXSprite->command; break; } @@ -7912,6 +7912,34 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, SPRITEMASS& w, SPR return arc; } +FSerializer& Serialize(FSerializer& arc, const char* keyname, OBJECTS_TO_TRACK& w, OBJECTS_TO_TRACK* def) +{ + static OBJECTS_TO_TRACK nul; + if (arc.isReading()) w = {}; + if (arc.BeginObject(keyname)) + { + arc("type", w.type, &nul.type) + ("index", w.index, &nul.index) + ("xrepeat", w.cmd, &nul.cmd) + .EndObject(); + } + return arc; +} + +FSerializer& Serialize(FSerializer& arc, const char* keyname, TRCONDITION& w, TRCONDITION* def) +{ + static TRCONDITION nul; + if (arc.isReading()) w = {}; + if (arc.BeginObject(keyname)) + { + arc("length", w.length, &nul.length) + ("xindex", w.xindex, &nul.xindex) + .Array("obj", w.obj, w.length) + .EndObject(); + } + return arc; +} + void SerializeNNExts(FSerializer& arc) { if (arc.BeginObject("nnexts")) @@ -7938,6 +7966,8 @@ void SerializeNNExts(FSerializer& arc) ("impactspritescount", gImpactSpritesCount) .Array("impactspriteslist", gImpactSpritesList, gImpactSpritesCount) ("eventredirects", gEventRedirectsUsed) + ("trconditioncount", gTrackingCondsCount) + .Array("trcondition", gCondition, gTrackingCondsCount) .EndObject(); } } diff --git a/source/games/blood/src/nnexts.h b/source/games/blood/src/nnexts.h index 044758c2a..9f7abfd70 100644 --- a/source/games/blood/src/nnexts.h +++ b/source/games/blood/src/nnexts.h @@ -235,14 +235,14 @@ struct TRPLAYERCTRL { // this one for controlling the player using triggers (mov }; struct OBJECTS_TO_TRACK { - signed int type: 3; - unsigned int index: 16; - unsigned int cmd: 8; + int8_t type; + uint8_t cmd; + int index; }; struct TRCONDITION { - signed int xindex: 16; - unsigned int length: 8; + signed int xindex; + unsigned int length; OBJECTS_TO_TRACK obj[kMaxTracedObjects]; }; From 3c09f41b436e86296542892c754d815bd7cad8ae Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 28 Aug 2021 11:53:26 +1000 Subject: [PATCH 40/49] - Blood: Use more precision for flicker, quake and tilt effects. --- source/games/blood/src/common_game.h | 5 +++ source/games/blood/src/view.cpp | 54 +++++++++------------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/source/games/blood/src/common_game.h b/source/games/blood/src/common_game.h index 30768ba05..4e5684c34 100644 --- a/source/games/blood/src/common_game.h +++ b/source/games/blood/src/common_game.h @@ -561,6 +561,11 @@ inline int QRandom2(int a1) return MulScale(qrand(), a1, 14)-a1; } +inline double QRandom2F(double a1) +{ + return MulScaleF(qrand(), a1, 14)-a1; +} + template inline void SetBitString(T *pArray, int nIndex) { diff --git a/source/games/blood/src/view.cpp b/source/games/blood/src/view.cpp index 23c6e3952..61036221b 100644 --- a/source/games/blood/src/view.cpp +++ b/source/games/blood/src/view.cpp @@ -359,43 +359,23 @@ void viewUpdateDelirium(void) void viewUpdateShake(int& cX, int& cY, int& cZ, binangle& cA, fixedhoriz& cH, double& pshakeX, double& pshakeY) { - int shakeHoriz = 0; - int shakeAngle = 0; - int shakeX = 0; - int shakeY = 0; - int shakeZ = 0; - int shakeBobX = 0; - int shakeBobY = 0; - if (gView->flickerEffect) + auto doEffect = [&](const int& effectType) { - int nValue = ClipHigh(gView->flickerEffect * 8, 2000); - shakeHoriz += QRandom2(nValue >> 8); - shakeAngle += QRandom2(nValue >> 8); - shakeX += QRandom2(nValue >> 4); - shakeY += QRandom2(nValue >> 4); - shakeZ += QRandom2(nValue); - shakeBobX += QRandom2(nValue); - shakeBobY += QRandom2(nValue); - } - if (gView->quakeEffect) - { - int nValue = ClipHigh(gView->quakeEffect * 8, 2000); - shakeHoriz += QRandom2(nValue >> 8); - shakeAngle += QRandom2(nValue >> 8); - shakeX += QRandom2(nValue >> 4); - shakeY += QRandom2(nValue >> 4); - shakeZ += QRandom2(nValue); - shakeBobX += QRandom2(nValue); - shakeBobY += QRandom2(nValue); - } - cH += buildhoriz(shakeHoriz); - cA += buildang(shakeAngle); - cX += shakeX; - cY += shakeY; - cZ += shakeZ; - pshakeX += shakeBobX; - pshakeY += shakeBobY; + if (effectType) + { + int nValue = ClipHigh(effectType * 8, 2000); + cH += buildfhoriz(QRandom2F(nValue * (1. / 256.))); + cA += buildfang(QRandom2F(nValue * (1. / 256.))); + cX += QRandom2(nValue >> 4); + cY += QRandom2(nValue >> 4); + cZ += QRandom2(nValue); + pshakeX += QRandom2F(nValue); + pshakeY += QRandom2F(nValue); + } + }; + doEffect(gView->flickerEffect); + doEffect(gView->quakeEffect); } @@ -483,7 +463,7 @@ void SetupView(int &cX, int& cY, int& cZ, binangle& cA, fixedhoriz& cH, int& nSe } viewUpdateShake(cX, cY, cZ, cA, cH, shakeX, shakeY); - cH += buildhoriz(MulScale(0x40000000 - Cos(gView->tiltEffect << 2), 30, 30)); + cH += q16horiz(xs_CRoundToInt(MulScaleF(double(0x40000000) - bcosf(gView->tiltEffect << 2, 16), 30, 14))); if (gViewPos == 0) { if (cl_viewhbob) @@ -495,7 +475,7 @@ void SetupView(int &cX, int& cY, int& cZ, binangle& cA, fixedhoriz& cH, int& nSe { cZ += bobHeight; } - cZ += xs_CRoundToInt(cH.asq16() / 6553.6); + cZ += xs_CRoundToInt(cH.asq16() * (1. / 6553.6)); cameradist = -1; cameraclock = PlayClock + MulScale(4, (int)gInterpolate, 16); } From 726edc199e2f776a495fd0e54a01987f1b6a0953 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 28 Aug 2021 16:36:27 +1000 Subject: [PATCH 41/49] - Blood: Add `SetQAV()` static function to abstract away from directly setting the player's `weaponQav` variable to allow us to properly reset the framerate QAV timer values to 0 as well. --- source/games/blood/src/qav.cpp | 2 +- source/games/blood/src/weapon.cpp | 68 +++++++++++++++++-------------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/source/games/blood/src/qav.cpp b/source/games/blood/src/qav.cpp index 1604f4d18..43f18258a 100644 --- a/source/games/blood/src/qav.cpp +++ b/source/games/blood/src/qav.cpp @@ -294,7 +294,7 @@ void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, doub // Process clock based on QAV's ticrate and last tick value. qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick); - if (pPlayer->weaponTimer == 0 && !ignoreWeaponTimer) + if (pPlayer->weaponTimer == 0 && pPlayer->qavTimer == 0 && !ignoreWeaponTimer) { // Check if we're playing an idle QAV as per the ticker's weapon timer. *duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration; diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 5b4361b35..2dfda4e0d 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -297,6 +297,14 @@ static void StartQAV(PLAYER *pPlayer, int nWeaponQAV, int callback = -1, bool lo pPlayer->weaponTimer -= 4; } +static void SetQAV(PLAYER *pPlayer, int nWeaponQAV) +{ + assert(nWeaponQAV < kQAVEnd); + pPlayer->weaponQav = qavGetCorrectID(nWeaponQAV); + pPlayer->qavTimer = 0; + pPlayer->qavLastTick = 0; +} + struct WEAPONTRACK { int aimSpeedHorz; @@ -833,7 +841,7 @@ void WeaponUpdateState(PLAYER *pPlayer) switch (lastWeapon) { case kWeapPitchFork: - pPlayer->weaponQav = qavGetCorrectID(kQAVFORKIDLE); + SetQAV(pPlayer, kQAVFORKIDLE); break; case kWeapSpraycan: switch (vb) @@ -849,15 +857,15 @@ void WeaponUpdateState(PLAYER *pPlayer) StartQAV(pPlayer, kQAVCANPREF); } else - pPlayer->weaponQav = qavGetCorrectID(kQAVLITEIDLE); + SetQAV(pPlayer, kQAVLITEIDLE); break; case 3: - pPlayer->weaponQav = qavGetCorrectID(kQAVCANIDLE); + SetQAV(pPlayer, kQAVCANIDLE); break; case 4: if (CheckAmmo(pPlayer, 6, 1)) { - pPlayer->weaponQav = qavGetCorrectID(kQAVCANIDLE); + SetQAV(pPlayer, kQAVCANIDLE); pPlayer->weaponState = 3; } else @@ -890,10 +898,10 @@ void WeaponUpdateState(PLAYER *pPlayer) StartQAV(pPlayer, kQAVBUNUP); } else - pPlayer->weaponQav = qavGetCorrectID(kQAVLITEIDLE); + SetQAV(pPlayer, kQAVLITEIDLE); break; case 3: - pPlayer->weaponQav = qavGetCorrectID(kQAVBUNIDLE); + SetQAV(pPlayer, kQAVBUNIDLE); break; } break; @@ -901,7 +909,7 @@ void WeaponUpdateState(PLAYER *pPlayer) switch (vb) { case 7: - pPlayer->weaponQav = qavGetCorrectID(kQAVPROXIDLE); + SetQAV(pPlayer, kQAVPROXIDLE); break; case 8: pPlayer->weaponState = 7; @@ -913,10 +921,10 @@ void WeaponUpdateState(PLAYER *pPlayer) switch (vb) { case 10: - pPlayer->weaponQav = qavGetCorrectID(kQAVREMIDLE1); + SetQAV(pPlayer, kQAVREMIDLE1); break; case 11: - pPlayer->weaponQav = qavGetCorrectID(kQAVREMIDLE2); + SetQAV(pPlayer, kQAVREMIDLE2); break; case 12: if (pPlayer->ammoCount[11] > 0) @@ -939,7 +947,7 @@ void WeaponUpdateState(PLAYER *pPlayer) pPlayer->weaponState = 1; break; case 7: - pPlayer->weaponQav = qavGetCorrectID(kQAV2SHOTI); + SetQAV(pPlayer, kQAV2SHOTI); break; case 1: if (CheckAmmo(pPlayer, 2, 1)) @@ -952,25 +960,25 @@ void WeaponUpdateState(PLAYER *pPlayer) pPlayer->weaponState = 2; } else - pPlayer->weaponQav = qavGetCorrectID(kQAVSHOTI3); + SetQAV(pPlayer, kQAVSHOTI3); break; case 2: - pPlayer->weaponQav = qavGetCorrectID(kQAVSHOTI2); + SetQAV(pPlayer, kQAVSHOTI2); break; case 3: - pPlayer->weaponQav = qavGetCorrectID(kQAVSHOTI1); + SetQAV(pPlayer, kQAVSHOTI1); break; } break; case kWeapTommyGun: if (powerupCheck(pPlayer, kPwUpTwoGuns) && checkAmmo2(pPlayer, 3, 2)) { - pPlayer->weaponQav = qavGetCorrectID(kQAV2TOMIDLE); + SetQAV(pPlayer, kQAV2TOMIDLE); pPlayer->weaponState = 1; } else { - pPlayer->weaponQav = qavGetCorrectID(kQAVTOMIDLE); + SetQAV(pPlayer, kQAVTOMIDLE); pPlayer->weaponState = 0; } break; @@ -978,33 +986,33 @@ void WeaponUpdateState(PLAYER *pPlayer) if (powerupCheck(pPlayer, kPwUpTwoGuns)) { if (vb == 3 && checkAmmo2(pPlayer, 1, 2)) - pPlayer->weaponQav = qavGetCorrectID(kQAVFLAR2I); + SetQAV(pPlayer, kQAVFLAR2I); else { - pPlayer->weaponQav = qavGetCorrectID(kQAVFLARIDLE); + SetQAV(pPlayer, kQAVFLARIDLE); pPlayer->weaponState = 2; } } else - pPlayer->weaponQav = qavGetCorrectID(kQAVFLARIDLE); + SetQAV(pPlayer, kQAVFLARIDLE); break; case kWeapVoodooDoll: if (pXSprite->height < 256 && pPlayer->swayHeight != 0) StartQAV(pPlayer, kQAVVDIDLE2); else - pPlayer->weaponQav = qavGetCorrectID(kQAVVDIDLE1); + SetQAV(pPlayer, kQAVVDIDLE1); break; case kWeapTeslaCannon: switch (vb) { case 2: if (checkAmmo2(pPlayer, 7, 10) && powerupCheck(pPlayer, kPwUpTwoGuns)) - pPlayer->weaponQav = qavGetCorrectID(kQAV2SGUNIDL); + SetQAV(pPlayer, kQAV2SGUNIDL); else - pPlayer->weaponQav = qavGetCorrectID(kQAVSGUNIDL1); + SetQAV(pPlayer, kQAVSGUNIDL1); break; case 3: - pPlayer->weaponQav = qavGetCorrectID(kQAVSGUNIDL2); + SetQAV(pPlayer, kQAVSGUNIDL2); break; } break; @@ -1013,12 +1021,12 @@ void WeaponUpdateState(PLAYER *pPlayer) { case 3: if (powerupCheck(pPlayer, kPwUpTwoGuns) && (gInfiniteAmmo || CheckAmmo(pPlayer,4, 4))) - pPlayer->weaponQav = qavGetCorrectID(kQAV2NAPIDLE); + SetQAV(pPlayer, kQAV2NAPIDLE); else - pPlayer->weaponQav = qavGetCorrectID(kQAVNAPIDLE); + SetQAV(pPlayer, kQAVNAPIDLE); break; case 2: - pPlayer->weaponQav = qavGetCorrectID(kQAVNAPIDLE); + SetQAV(pPlayer, kQAVNAPIDLE); break; } break; @@ -1026,12 +1034,12 @@ void WeaponUpdateState(PLAYER *pPlayer) switch (vb) { case 2: - pPlayer->weaponQav = qavGetCorrectID(kQAVSTAFIDL1); + SetQAV(pPlayer, kQAVSTAFIDL1); break; } break; case kWeapBeast: - pPlayer->weaponQav = qavGetCorrectID(kQAVBSTIDLE); + SetQAV(pPlayer, kQAVBSTIDLE); break; } } @@ -1586,7 +1594,7 @@ void FireTesla(int nTrigger, PLAYER *pPlayer) if (!checkAmmo2(pPlayer, 7, pMissile->ammouse)) { pPlayer->weaponState = -1; - pPlayer->weaponQav = qavGetCorrectID(kQAVSGUNIDL2); + SetQAV(pPlayer, kQAVSGUNIDL2); pPlayer->flashEffect = 0; return; } @@ -2355,7 +2363,7 @@ void WeaponProcess(PLAYER *pPlayer) { switch (pPlayer->weaponState) { case 7: - pPlayer->weaponQav = qavGetCorrectID(kQAVPROXIDLE); + SetQAV(pPlayer, kQAVPROXIDLE); pPlayer->weaponState = 9; pPlayer->throwTime = PlayClock; return; @@ -2365,7 +2373,7 @@ void WeaponProcess(PLAYER *pPlayer) { switch (pPlayer->weaponState) { case 10: - pPlayer->weaponQav = qavGetCorrectID(kQAVREMIDLE1); + SetQAV(pPlayer, kQAVREMIDLE1); pPlayer->weaponState = 13; pPlayer->throwTime = PlayClock; return; From 2fbfa82fe8329c1f3bb2badedaaf81025283d963 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 28 Aug 2021 16:41:51 +1000 Subject: [PATCH 42/49] - Blood: Add interpolated weapon QAVs to `WeaponInit()` and `WeaponPrecache()` functions. --- source/games/blood/src/weapon.cpp | 34 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 2dfda4e0d..8e07d2111 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -228,23 +228,35 @@ void SpawnShellEject(PLAYER *pPlayer, int a2, int a3) void WeaponInit(void) { - for (int i = 0; i < kQAVEnd; i++) + auto doInit = [](const int base) { - auto pQAV = getQAV(i); - if (!pQAV) - I_Error("Could not load QAV %d\n", i); - pQAV->nSprite = -1; - } + for (int i = base; i < (kQAVEnd + base); i++) + { + auto pQAV = getQAV(i); + if (!pQAV) + I_Error("Could not load QAV %d\n", i); + pQAV->nSprite = -1; + } + }; + + doInit(0); + doInit(10000); } void WeaponPrecache() { - for (int i = 0; i < kQAVEnd; i++) + auto doPrecache = [](const int base) { - auto pQAV = getQAV(i); - if (pQAV) - pQAV->Precache(); - } + for (int i = base; i < (kQAVEnd + base); i++) + { + auto pQAV = getQAV(i); + if (pQAV) + pQAV->Precache(); + } + }; + + doPrecache(0); + doPrecache(10000); } void WeaponDraw(PLAYER *pPlayer, int shade, double xpos, double ypos, int palnum) From 049665e03e23b9a59c228b434d2ea0d83fd0f89d Mon Sep 17 00:00:00 2001 From: carnivoroussociety <38839485+carnivoroussociety@users.noreply.github.com> Date: Sat, 28 Aug 2021 05:38:02 +1000 Subject: [PATCH 43/49] Fixed bug collecting lifeleech with ignited tnt/spray --- source/games/blood/src/misc.h | 1 + source/games/blood/src/triggers.cpp | 5 ++++- source/games/blood/src/weapon.cpp | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/games/blood/src/misc.h b/source/games/blood/src/misc.h index 96914d50f..f889ce817 100644 --- a/source/games/blood/src/misc.h +++ b/source/games/blood/src/misc.h @@ -43,6 +43,7 @@ void HookReplaceFunctions(); struct PLAYER; +bool checkFired6or7(PLAYER *pPlayer); void WeaponInit(void); void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5); void WeaponRaise(PLAYER *pPlayer); diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index ade5acbcf..28aa333de 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "blood.h" +#include "misc.h" #include "d_net.h" BEGIN_BLD_NS @@ -206,14 +207,16 @@ void LifeLeechOperate(spritetype *pSprite, XSPRITE *pXSprite, EVENT event) PLAYER *pPlayer = &gPlayer[nPlayer]; if (pPlayer->pXSprite->health > 0) { + evKill(pSprite->index, 3); pPlayer->ammoCount[8] = ClipHigh(pPlayer->ammoCount[8]+pXSprite->data3, gAmmoInfo[8].max); pPlayer->hasWeapon[9] = 1; if (pPlayer->curWeapon != kWeapLifeLeech) { + if (!VanillaMode() && checkFired6or7(pPlayer)) // if tnt/spray is actively used, do not switch weapon + break; pPlayer->weaponState = 0; pPlayer->nextWeapon = 9; } - evKill(pSprite->index, 3); } } break; diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 8e07d2111..714028243 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -140,7 +140,7 @@ enum nClientAltFireNapalm, }; -static bool checkFired6or7(PLAYER *pPlayer) +bool checkFired6or7(PLAYER *pPlayer) { switch (pPlayer->curWeapon) { From 2b44f8e79dce354103218d6f2b37fb3bafaa2a1e Mon Sep 17 00:00:00 2001 From: carnivoroussociety <38839485+carnivoroussociety@users.noreply.github.com> Date: Sat, 28 Aug 2021 06:30:34 +1000 Subject: [PATCH 44/49] Carry over team flag fix from nblood --- source/games/blood/src/player.cpp | 52 ++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index c524aa521..cc9e06b46 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -978,20 +978,56 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { } } return 0; - case kItemFlagA: + case kItemFlagA: { if (gGameOptions.nGameType != 3) return 0; - evKill(pItem->index, 3, kCallbackReturnFlag); - pPlayer->hasFlag |= 1; - pPlayer->used2[0] = pItem->index; gBlueFlagDropped = false; + const bool enemyTeam = (pPlayer->teamId&1) == 1; + if (!enemyTeam && (pItem->owner >= 0) && (pItem->owner < kMaxSprites)) { + pPlayer->hasFlag &= ~1; + pPlayer->used2[0] = -1; + spritetype* pOwner = &sprite[pItem->owner]; + XSPRITE* pXOwner = &xsprite[pOwner->extra]; + trTriggerSprite(pOwner->index, pXOwner, kCmdOn); + sprintf(buffer, "%s returned Blue Flag", gProfile[pPlayer->nPlayer].name); + sndStartSample(8003, 255, 2, 0); + viewSetMessage(buffer); + break; + } + pPlayer->hasFlag |= 1; + pPlayer->used2[0] = pItem->owner; + if (enemyTeam) + { + sprintf(buffer, "%s stole Blue Flag", gProfile[pPlayer->nPlayer].name); + sndStartSample(8007, 255, 2, 0); + viewSetMessage(buffer); + } break; - case kItemFlagB: + } + case kItemFlagB: { if (gGameOptions.nGameType != 3) return 0; - evKill(pItem->index, 3, kCallbackReturnFlag); - pPlayer->hasFlag |= 2; - pPlayer->used2[1] = pItem->index; gRedFlagDropped = false; + const bool enemyTeam = (pPlayer->teamId&1) == 0; + if (!enemyTeam && (pItem->owner >= 0) && (pItem->owner < kMaxSprites)) { + pPlayer->hasFlag &= ~2; + pPlayer->used2[1] = -1; + spritetype* pOwner = &sprite[pItem->owner]; + XSPRITE* pXOwner = &xsprite[pOwner->extra]; + trTriggerSprite(pOwner->index, pXOwner, kCmdOn); + sprintf(buffer, "%s returned Red Flag", gProfile[pPlayer->nPlayer].name); + sndStartSample(8002, 255, 2, 0); + viewSetMessage(buffer); + break; + } + pPlayer->hasFlag |= 2; + pPlayer->used2[1] = pItem->owner; + if (enemyTeam) + { + sprintf(buffer, "%s stole Red Flag", gProfile[pPlayer->nPlayer].name); + sndStartSample(8006, 255, 2, 0); + viewSetMessage(buffer); + } break; + } case kItemArmorBasic: case kItemArmorBody: case kItemArmorFire: From deefbcf431f1c3172bd4a53a1e402f9ac8e2e53e Mon Sep 17 00:00:00 2001 From: carnivoroussociety <38839485+carnivoroussociety@users.noreply.github.com> Date: Sat, 28 Aug 2021 06:37:45 +1000 Subject: [PATCH 45/49] Use PlayerName() --- source/games/blood/src/player.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index cc9e06b46..3233f6e71 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -988,7 +988,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { spritetype* pOwner = &sprite[pItem->owner]; XSPRITE* pXOwner = &xsprite[pOwner->extra]; trTriggerSprite(pOwner->index, pXOwner, kCmdOn); - sprintf(buffer, "%s returned Blue Flag", gProfile[pPlayer->nPlayer].name); + sprintf(buffer, "%s returned Blue Flag", PlayerName(pPlayer->nPlayer)); sndStartSample(8003, 255, 2, 0); viewSetMessage(buffer); break; @@ -997,7 +997,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { pPlayer->used2[0] = pItem->owner; if (enemyTeam) { - sprintf(buffer, "%s stole Blue Flag", gProfile[pPlayer->nPlayer].name); + sprintf(buffer, "%s stole Blue Flag", PlayerName(pPlayer->nPlayer)); sndStartSample(8007, 255, 2, 0); viewSetMessage(buffer); } @@ -1013,7 +1013,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { spritetype* pOwner = &sprite[pItem->owner]; XSPRITE* pXOwner = &xsprite[pOwner->extra]; trTriggerSprite(pOwner->index, pXOwner, kCmdOn); - sprintf(buffer, "%s returned Red Flag", gProfile[pPlayer->nPlayer].name); + sprintf(buffer, "%s returned Red Flag", PlayerName(pPlayer->nPlayer)); sndStartSample(8002, 255, 2, 0); viewSetMessage(buffer); break; @@ -1022,7 +1022,7 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { pPlayer->used2[1] = pItem->owner; if (enemyTeam) { - sprintf(buffer, "%s stole Red Flag", gProfile[pPlayer->nPlayer].name); + sprintf(buffer, "%s stole Red Flag", PlayerName(pPlayer->nPlayer)); sndStartSample(8006, 255, 2, 0); viewSetMessage(buffer); } From 44e0da1212e613d72797ab82df09669aad73c0f6 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sat, 28 Aug 2021 16:58:39 +1000 Subject: [PATCH 46/49] - Blood: Remove the `interpolate` statement from all unused beast QAVs. * These files are included so that all interpolated weapon QAVs from 0 - 124 can be easily init/load/precache using the same code the game uses to init/load/precache the original QAVs. * These QAVs have not been tested or patched for any QAV interpolation issues, so best to not declare them interpolated in case a modder uses them and they're messed up. --- wadsrc/static/filter/blood/engine/engine.def | 21 -------------------- 1 file changed, 21 deletions(-) diff --git a/wadsrc/static/filter/blood/engine/engine.def b/wadsrc/static/filter/blood/engine/engine.def index 3078a4d0c..a3d5be401 100644 --- a/wadsrc/static/filter/blood/engine/engine.def +++ b/wadsrc/static/filter/blood/engine/engine.def @@ -662,45 +662,24 @@ defineqav 10092 { } defineqav 10093 { file "qavs/BSTUP.QAV" - interpolate { - type "index" - } } defineqav 10094 { file "qavs/BSTIDLE.QAV" - interpolate { - type "index" - } } defineqav 10095 { file "qavs/BSTATAK1.QAV" - interpolate { - type "index" - } } defineqav 10096 { file "qavs/BSTATAK2.QAV" - interpolate { - type "index" - } } defineqav 10097 { file "qavs/BSTATAK3.QAV" - interpolate { - type "index" - } } defineqav 10098 { file "qavs/BSTATAK4.QAV" - interpolate { - type "index" - } } defineqav 10099 { file "qavs/BSTDOWN.QAV" - interpolate { - type "index" - } } defineqav 10100 { file "qavs/VDUP.QAV" From bac1480997a6871bf6471fafde8dca9c46408b94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 28 Aug 2021 17:59:33 +0200 Subject: [PATCH 47/49] - Blood: fixed use of bad index variable in condCheckSector --- source/games/blood/src/nnexts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 6fed49f2d..e419aadb5 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -3570,8 +3570,8 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH) { SectIterator it(objIndex); while ((nSprite = it.NextIndex()) >= 0) { - if (!condCmp(sprite[var].type, arg1, arg2, cmpOp)) continue; - else if (PUSH) condPush(pXCond, OBJ_SPRITE, var); + if (!condCmp(sprite[nSprite].type, arg1, arg2, cmpOp)) continue; + else if (PUSH) condPush(pXCond, OBJ_SPRITE, nSprite); return true; } return false; From 0a04f8d14e6e0d323bf6ac0cc505fc9f1bcfe5b1 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Sun, 29 Aug 2021 19:42:24 +1000 Subject: [PATCH 48/49] - Blood: Repair bad tile index swaps for frame 1 that were accidentally applied against frame 0. * Fixes #527. --- wadsrc/static/filter/blood/qavs/VDFIRE1.QAV | Bin 2484 -> 2484 bytes wadsrc/static/filter/blood/qavs/VDFIRE2.QAV | Bin 2484 -> 2484 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/filter/blood/qavs/VDFIRE1.QAV b/wadsrc/static/filter/blood/qavs/VDFIRE1.QAV index e156e5f5f1cdf4c11ff16b0de4cc4c11a9eeb1cc..90b179d4ad151a78f776581f51bb63988d34992b 100644 GIT binary patch delta 36 ucmV+<0Nekx6SNbMFq8BMz>z=z= Date: Sun, 29 Aug 2021 21:00:08 +1000 Subject: [PATCH 49/49] - Duke/RR: Fix clearing of weapons for RRRA E2L2 that should only be done for RR. * Fixes https://forum.zdoom.org/viewtopic.php?f=340&t=73173. --- wadsrc/static/filter/redneck.ridesagain/engine/rmapinfo.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/wadsrc/static/filter/redneck.ridesagain/engine/rmapinfo.txt b/wadsrc/static/filter/redneck.ridesagain/engine/rmapinfo.txt index e44fe042d..98f54fd46 100644 --- a/wadsrc/static/filter/redneck.ridesagain/engine/rmapinfo.txt +++ b/wadsrc/static/filter/redneck.ridesagain/engine/rmapinfo.txt @@ -63,7 +63,6 @@ map { 2, 2 } { interbackground = "LEVELMAP09" rr_startsound = 176 - clearweapons } map { 2, 3 }