diff --git a/Core/World/Physics/PhysicsManager.cs b/Core/World/Physics/PhysicsManager.cs index a7ec4c826..e07d4652c 100644 --- a/Core/World/Physics/PhysicsManager.cs +++ b/Core/World/Physics/PhysicsManager.cs @@ -182,7 +182,7 @@ public SectorMoveStatus MoveSectorZ(double speed, double destZ, SectorMoveSpecia var moveType = moveSpecial.MoveData.SectorMoveType; var startZ = sectorPlane.Z; if (!m_world.Config.Compatibility.VanillaSectorPhysics && IsSectorMovementBlocked(sector, startZ, destZ, moveSpecial)) - return SectorMoveStatus.BlockedAndStop; + return SectorMoveStatus.Blocked | SectorMoveStatus.Stop; // Move lower entities first to handle stacked entities // Ordering by Id is only required for EntityRenderer nudging to prevent z-fighting @@ -204,7 +204,7 @@ public SectorMoveStatus MoveSectorZ(double speed, double destZ, SectorMoveSpecia if (!moveSpecial.IsDoor && !m_world.Config.Compatibility.VanillaSectorPhysics && IsSectorMovementBlocked(sector, startZ, destZ, moveSpecial)) { FixPlaneClip(sector, sectorPlane, moveType); - status = SectorMoveStatus.BlockedAndStop; + status = SectorMoveStatus.Blocked | SectorMoveStatus.Stop; } if (solid) @@ -310,14 +310,16 @@ public SectorMoveStatus MoveSectorZ(double speed, double destZ, SectorMoveSpecia if (moveData.Crush != null) { + status |= SectorMoveStatus.Crushed; + if (moveData.Crush.Value.CrushMode == ZDoomCrushMode.Hexen || moveData.Crush.Value.Damage == 0) { highestBlockEntity = entity; highestBlockHeight = entity.Height; highestBlockEntityWasCrushing = entityMoveData.WasCrushing; + status |= SectorMoveStatus.Blocked; } - - status = SectorMoveStatus.Crush; + m_crushEntities.Add(entity); } else if (CheckSectorMoveBlock(entity, moveType, entityMoveData.SaveZ)) @@ -383,16 +385,16 @@ public SectorMoveStatus MoveSectorZ(double speed, double destZ, SectorMoveSpecia // If an entity is blocking this and the destination is blocked then we need to stop to match vanilla behavior. if (isCompleted && status == SectorMoveStatus.Blocked) - return SectorMoveStatus.BlockedAndStop; + return SectorMoveStatus.Blocked | SectorMoveStatus.Stop; - if (status == SectorMoveStatus.BlockedAndStop) + if (status == (SectorMoveStatus.Blocked | SectorMoveStatus.Stop)) return status; if (WorldStatic.Sector3D && checkSector3D && sector.TaggedSectors3D.Length > 0) { status = TestMoveSector3D(speed, destZ, startZ, moveSpecial, sector, sectorPlane, moveType); - if (status == SectorMoveStatus.Blocked || status == SectorMoveStatus.BlockedAndStop) + if ((status & (SectorMoveStatus.Blocked | SectorMoveStatus.Stop)) != 0) sectorPlane.SetZ(startZ); } @@ -455,9 +457,9 @@ private SectorMoveStatus TestMoveSector3D(double speed, double destZ, double sta moveSpecial.MoveData.SectorMoveType = face; moveSpecial.MoveData.Sector3D = null; - if (status != SectorMoveStatus.Success) + if ((status & SectorMoveStatus.Blocked) != 0) return status; - } + } return SectorMoveStatus.Success; } diff --git a/Core/World/Physics/SectorMoveStatus.cs b/Core/World/Physics/SectorMoveStatus.cs index 9e6823a6c..a9c9d6a33 100644 --- a/Core/World/Physics/SectorMoveStatus.cs +++ b/Core/World/Physics/SectorMoveStatus.cs @@ -1,9 +1,13 @@ +using System; + namespace Helion.World.Physics; +[Flags] public enum SectorMoveStatus { - Blocked, - Success, - Crush, - BlockedAndStop -} + None = 0, + Success = 1, + Blocked = 2, + Crushed = 4, + Stop = 8 +} \ No newline at end of file diff --git a/Core/World/Special/Specials/ElevatorSpecial.cs b/Core/World/Special/Specials/ElevatorSpecial.cs index b7d4187be..3cb06509e 100644 --- a/Core/World/Special/Specials/ElevatorSpecial.cs +++ b/Core/World/Special/Specials/ElevatorSpecial.cs @@ -26,12 +26,13 @@ public override void GetSectors(List<(Sector, SectorPlane)> data) public ElevatorSpecial(IWorld world, Sector sector, double floorDestZ, double speed, MoveDirection moveDirection, SectorSoundData soundData) { + var crush = new CrushData(Maps.Specials.ZDoom.ZDoomCrushMode.Hexen, 5); Sector = sector; var floor = world.DataCache.GetSectorMoveSpecial(world, sector, Sector.Floor.Z, floorDestZ, - new SectorMoveData(SectorPlaneFace.Floor, moveDirection, MoveRepetition.None, speed, 0), soundData); + new SectorMoveData(SectorPlaneFace.Floor, moveDirection, MoveRepetition.None, speed, 0, crush: crush), soundData); var ceiling = world.DataCache.GetSectorMoveSpecial(world, sector, Sector.Ceiling.Z, floorDestZ + sector.Ceiling.Z - sector.Floor.Z, - new SectorMoveData(SectorPlaneFace.Ceiling, moveDirection, MoveRepetition.None, speed, 0), soundData); + new SectorMoveData(SectorPlaneFace.Ceiling, moveDirection, MoveRepetition.None, speed, 0, crush: crush), soundData); // Sector plane that can potentially be blocked needs to moved first // Reverse when sector controls 3D sectors @@ -60,7 +61,7 @@ public ElevatorSpecial(Sector sector, SectorMoveSpecial firstMove, SectorMoveSpe public override SpecialTickStatus Tick() { m_firstMove.Tick(); - if (m_firstMove.MoveStatus == SectorMoveStatus.Blocked) + if ((m_firstMove.MoveStatus & SectorMoveStatus.Blocked) != 0) m_secondMove.ResetInterpolation(); else return m_secondMove.Tick(); diff --git a/Core/World/Special/Specials/SectorMoveSpecial.cs b/Core/World/Special/Specials/SectorMoveSpecial.cs index 8448a078a..93618243f 100644 --- a/Core/World/Special/Specials/SectorMoveSpecial.cs +++ b/Core/World/Special/Specials/SectorMoveSpecial.cs @@ -239,7 +239,7 @@ public virtual SpecialTickStatus Tick() IsInitialMove = false; - if (MoveStatus == SectorMoveStatus.BlockedAndStop) + if ((MoveStatus & SectorMoveStatus.Stop) != 0) DestZ = SectorPlane.Z; if (MoveData.LightTag > 0) @@ -247,7 +247,7 @@ public virtual SpecialTickStatus Tick() CheckPlaySound(); - if ((IsNonRepeat && SectorPlane.Z == DestZ) || MoveStatus == SectorMoveStatus.BlockedAndStop) + if ((IsNonRepeat && SectorPlane.Z == DestZ) || (MoveStatus & SectorMoveStatus.Stop) != 0) { if (CheckInstantMove(destZ)) ResetInterpolation(); @@ -474,27 +474,33 @@ private void PerformAndHandleMoveZ(double destZ) { MoveStatus = m_world.MoveSectorZ(MoveSpeed, destZ, this); - switch (MoveStatus) + // Never flip crushers on blocked + if ((MoveStatus & SectorMoveStatus.Blocked) != 0 && (MoveStatus & SectorMoveStatus.Crushed) == 0) { - case SectorMoveStatus.Blocked: - if (MoveData.MoveRepetition != MoveRepetition.None) - FlipMovementDirection(true); - break; + if (MoveData.MoveRepetition != MoveRepetition.None) + FlipMovementDirection(true); + } - case SectorMoveStatus.Crush when IsInitCrush: - SetSectorDataChange(); + if ((MoveStatus & SectorMoveStatus.Crushed) != 0) + { + if (IsInitCrush) + { IsCrushing = true; if (MoveData.Crush != null && MoveData.Crush.Value.CrushMode == ZDoomCrushMode.DoomWithSlowDown) MoveSpeed = MoveSpeed < 0 ? -Constants.DoomSlowCrushSpeed : Constants.DoomSlowCrushSpeed; - break; + } - case SectorMoveStatus.Success: + if ((MoveStatus & SectorMoveStatus.Blocked) == 0) SetSectorDataChange(); - break; - } + } - if (IsCrushing && MoveStatus == SectorMoveStatus.Success) - IsCrushing = false; + if ((MoveStatus & SectorMoveStatus.Success) != 0) + { + SetSectorDataChange(); + + if (IsCrushing) + IsCrushing = false; + } } private void SetSectorDataChange()