From b7b0e644716858928a2f7812cbd3f2f51d7e4b7b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 14 Feb 2017 20:11:30 +0100 Subject: [PATCH] - separated splash detection from water level setting. This could cause problems if 3D floors with different properties for slashing and waterlevel were occupied at the same time. By keeping the slash code separate both parts can be handled without having to look out for the other. --- src/actor.h | 1 + src/p_mobj.cpp | 130 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/actor.h b/src/actor.h index 77c7f81a4..a973c101a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1230,6 +1230,7 @@ public: bool InStateSequence(FState * newstate, FState * basestate); int GetTics(FState * newstate); bool SetState (FState *newstate, bool nofunction=false); + virtual void SplashCheck(); virtual bool UpdateWaterLevel (bool splash=true); bool isFast(); bool isSlow(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d879d206d..81fab5733 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4540,23 +4540,22 @@ void AActor::CheckSectorTransition(sector_t *oldsec) //========================================================================== // -// AActor::UpdateWaterLevel +// AActor::SplashCheck // // Returns true if actor should splash // //========================================================================== -bool AActor::UpdateWaterLevel (bool dosplash) +void AActor::SplashCheck() { - BYTE lastwaterlevel = waterlevel; double fh = -FLT_MAX; - bool reset=false; + bool reset = false; waterlevel = 0; if (Sector == NULL) { - return false; + return; } if (Sector->MoreFlags & SECF_UNDERWATER) // intentionally not SECF_UNDERWATERMASK @@ -4568,7 +4567,7 @@ bool AActor::UpdateWaterLevel (bool dosplash) const sector_t *hsec = Sector->GetHeightSec(); if (hsec != NULL) { - fh = hsec->floorplane.ZatPoint (this); + fh = hsec->floorplane.ZatPoint(this); //if (hsec->MoreFlags & SECF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors { if (Z() < fh) @@ -4584,7 +4583,7 @@ bool AActor::UpdateWaterLevel (bool dosplash) } } } - else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint (this))) + else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this))) { waterlevel = 3; } @@ -4593,29 +4592,23 @@ bool AActor::UpdateWaterLevel (bool dosplash) waterlevel = 0; } } - // even non-swimmable deep water must be checked here to do the splashes correctly - // But the water level must be reset when this function returns - if (!(hsec->MoreFlags&SECF_UNDERWATERMASK)) - { - reset = true; - } } else { // Check 3D floors as well! - for(auto rover : Sector->e->XFloor.ffloors) + for (auto rover : Sector->e->XFloor.ffloors) { if (!(rover->flags & FF_EXISTS)) continue; if (rover->flags & FF_SOLID) continue; - reset = !(rover->flags & FF_SWIMMABLE); + bool reset = !(rover->flags & FF_SWIMMABLE); if (reset && rover->alpha == 0) continue; - double ff_bottom=rover->bottom.plane->ZatPoint(this); - double ff_top=rover->top.plane->ZatPoint(this); + double ff_bottom = rover->bottom.plane->ZatPoint(this); + double ff_top = rover->top.plane->ZatPoint(this); - if(ff_top <= Z() || ff_bottom > (Center())) continue; - - fh=ff_top; + if (ff_top <= Z() || ff_bottom > (Center())) continue; + + fh = ff_top; if (Z() < fh) { waterlevel = 1; @@ -4634,17 +4627,106 @@ bool AActor::UpdateWaterLevel (bool dosplash) } } } - + // some additional checks to make deep sectors like Boom's splash without setting // the water flags. - if (boomwaterlevel == 0 && waterlevel != 0 && dosplash) + if (boomwaterlevel == 0 && waterlevel != 0) { P_HitWater(this, Sector, PosAtZ(fh), true); } boomwaterlevel = waterlevel; - if (reset) + return; +} + +//========================================================================== +// +// AActor::UpdateWaterLevel +// +// Returns true if actor should splash +// +//========================================================================== + +bool AActor::UpdateWaterLevel(bool dosplash) +{ + if (dosplash) SplashCheck(); + + double fh = -FLT_MAX; + bool reset = false; + + waterlevel = 0; + + if (Sector == NULL) { - waterlevel = lastwaterlevel; + return false; + } + + if (Sector->MoreFlags & SECF_UNDERWATER) // intentionally not SECF_UNDERWATERMASK + { + waterlevel = 3; + } + else + { + const sector_t *hsec = Sector->GetHeightSec(); + if (hsec != NULL) + { + fh = hsec->floorplane.ZatPoint(this); + if (hsec->MoreFlags & SECF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors + { + if (Z() < fh) + { + waterlevel = 1; + if (Center() < fh) + { + waterlevel = 2; + if ((player && Z() + player->viewheight <= fh) || + (Top() <= fh)) + { + waterlevel = 3; + } + } + } + else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this))) + { + waterlevel = 3; + } + else + { + waterlevel = 0; + } + } + } + else + { + // Check 3D floors as well! + for (auto rover : Sector->e->XFloor.ffloors) + { + if (!(rover->flags & FF_EXISTS)) continue; + if (rover->flags & FF_SOLID) continue; + if (!(rover->flags & FF_SWIMMABLE)) continue; + + double ff_bottom = rover->bottom.plane->ZatPoint(this); + double ff_top = rover->top.plane->ZatPoint(this); + + if (ff_top <= Z() || ff_bottom > (Center())) continue; + + fh = ff_top; + if (Z() < fh) + { + waterlevel = 1; + if (Center() < fh) + { + waterlevel = 2; + if ((player && Z() + player->viewheight <= fh) || + (Top() <= fh)) + { + waterlevel = 3; + } + } + } + + break; + } + } } return false; // we did the splash ourselves }