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 }