diff --git a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs index dce60bf811..0f4bd50457 100644 --- a/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using System; using Content.Server.GameObjects.EntitySystems; using Content.Shared.Atmos; using Robust.Server.Interfaces.GameObjects; @@ -10,6 +11,7 @@ using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -30,6 +32,12 @@ namespace Content.Server.GameObjects.Components.Atmos private bool _airBlocked = true; private bool _fixVacuum = false; + [ViewVariables] + private bool _rotateAirBlocked = true; + + [ViewVariables] + private bool _fixAirBlockedDirectionInitialize = true; + [ViewVariables(VVAccess.ReadWrite)] public bool AirBlocked { @@ -63,6 +71,8 @@ namespace Content.Server.GameObjects.Components.Atmos serializer.DataField(ref _airBlocked, "airBlocked", true); serializer.DataField(ref _fixVacuum, "fixVacuum", true); serializer.DataField(ref _airBlockedDirection, "airBlockedDirection", (int)AtmosDirection.All, WithFormat.Flags()); + serializer.DataField(ref _rotateAirBlocked, "rotateAirBlocked", true); + serializer.DataField(ref _fixAirBlockedDirectionInitialize, "fixAirBlockedDirectionInitialize", true); } public override void Initialize() @@ -75,9 +85,36 @@ namespace Content.Server.GameObjects.Components.Atmos if (!Owner.EnsureComponent(out SnapGridComponent _)) Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition.ToString()} didn't have a {nameof(SnapGridComponent)}"); + Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, RotateEvent); + + if(_fixAirBlockedDirectionInitialize) + RotateEvent(new RotateEvent(Owner, Angle.Zero, Owner.Transform.LocalRotation)); + UpdatePosition(); } + private void RotateEvent(RotateEvent ev) + { + if (!_rotateAirBlocked || ev.Sender != Owner || ev.NewRotation == ev.OldRotation) + return; + + var diff = ev.NewRotation - ev.OldRotation; + + var newAirBlockedDirs = AtmosDirection.Invalid; + + // When we make multiZ atmos, special case this. + for (int i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection) i; + if (!AirBlockedDirection.HasFlag(direction)) continue; + var angle = direction.ToAngle(); + angle += diff; + newAirBlockedDirs |= angle.ToAtmosDirectionCardinal(); + } + + AirBlockedDirection = newAirBlockedDirs; + } + public void MapInit() { if (Owner.TryGetComponent(out SnapGridComponent? snapGrid)) diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs index 03ec350359..b6c416ca97 100644 --- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -35,12 +35,17 @@ namespace Content.Server.GameObjects.Components.Atmos { base.Startup(); - var airtightComponent = Owner.EnsureComponent(); - var collidableComponent = Owner.GetComponent(); + if (Owner.TryGetComponent(out AirtightComponent airtightComponent)) + { + airtightComponent.AirBlocked = false; + } + + if (Owner.TryGetComponent(out ICollidableComponent collidableComponent)) + { + collidableComponent.Hard = false; + } Safety = false; - airtightComponent.AirBlocked = false; - collidableComponent.Hard = false; if (Occludes && Owner.TryGetComponent(out OccluderComponent occluder)) { diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index c3991df998..aab6f1b7ad 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -77,6 +77,49 @@ namespace Content.Shared.Atmos }; } + /// + /// Converts a direction to an angle, where angle is -PI to +PI. + /// + /// + /// + public static Angle ToAngle(this AtmosDirection direction) + { + return direction switch + { + AtmosDirection.East => Angle.FromDegrees(0), + AtmosDirection.North => Angle.FromDegrees(90), + AtmosDirection.West => Angle.FromDegrees(180), + AtmosDirection.South => Angle.FromDegrees(270), + + AtmosDirection.NorthEast => Angle.FromDegrees(45), + AtmosDirection.NorthWest => Angle.FromDegrees(135), + AtmosDirection.SouthWest => Angle.FromDegrees(225), + AtmosDirection.SouthEast => Angle.FromDegrees(315), + + _ => throw new ArgumentOutOfRangeException(nameof(direction)), + }; + } + + /// + /// Converts an angle to a cardinal AtmosDirection + /// + /// + /// + public static AtmosDirection ToAtmosDirectionCardinal(this Angle angle) + { + return angle.GetCardinalDir().ToAtmosDirection(); + } + + /// + /// Converts an angle to an AtmosDirection + /// + /// + /// + public static AtmosDirection ToAtmosDirection(this Angle angle) + { + return angle.GetDir().ToAtmosDirection(); + } + public static int ToIndex(this AtmosDirection direction) { // This will throw if you pass an invalid direction. Not this method's fault, but yours!