From a360f6126eead86e3df243638cc32bbd4b947939 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Thu, 11 Nov 2021 20:06:38 +1100 Subject: [PATCH] Shuttle docking (#5169) Co-authored-by: metalgearsloth --- Content.Client/Doors/AirlockVisualizer.cs | 3 + Content.Client/Entry/IgnoredComponents.cs | 1 + .../Doors/Components/ServerDoorComponent.cs | 20 +- .../Physics/Controllers/MoverController.cs | 2 +- Content.Server/Shuttles/DockingSystem.cs | 494 ++++++++++++++++++ Content.Server/Shuttles/ShuttleComponent.cs | 5 +- Content.Server/Shuttles/ShuttleSystem.cs | 2 +- Content.Shared/Doors/SharedDoorComponent.cs | 12 +- .../Shuttles/SharedDockingComponent.cs | 18 + Resources/Audio/Effects/docking.ogg | Bin 0 -> 31515 bytes Resources/Locale/en-US/shuttles/docking.ftl | 2 + .../Structures/Doors/Airlocks/shuttle.yml | 88 ++++ .../Airlocks/Standard/shuttle.rsi/closed.png | Bin 0 -> 696 bytes .../Airlocks/Standard/shuttle.rsi/closing.png | Bin 0 -> 3391 bytes .../Airlocks/Standard/shuttle.rsi/meta.json | 47 ++ .../Airlocks/Standard/shuttle.rsi/open.png | Bin 0 -> 614 bytes .../Airlocks/Standard/shuttle.rsi/opening.png | Bin 0 -> 3428 bytes 17 files changed, 681 insertions(+), 13 deletions(-) create mode 100644 Content.Server/Shuttles/DockingSystem.cs create mode 100644 Content.Shared/Shuttles/SharedDockingComponent.cs create mode 100644 Resources/Audio/Effects/docking.ogg create mode 100644 Resources/Locale/en-US/shuttles/docking.ftl create mode 100644 Resources/Prototypes/Entities/Structures/Doors/Airlocks/shuttle.yml create mode 100644 Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/closed.png create mode 100644 Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/closing.png create mode 100644 Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/meta.json create mode 100644 Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/open.png create mode 100644 Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/opening.png diff --git a/Content.Client/Doors/AirlockVisualizer.cs b/Content.Client/Doors/AirlockVisualizer.cs index af40479a6c..60cb788e4a 100644 --- a/Content.Client/Doors/AirlockVisualizer.cs +++ b/Content.Client/Doors/AirlockVisualizer.cs @@ -30,6 +30,9 @@ namespace Content.Client.Doors [DataField("animatedPanel")] private bool _animatedPanel = true; + /// + /// Means the door is simply open / closed / opening / closing. No wires or access. + /// [DataField("simpleVisuals")] private bool _simpleVisuals = false; diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 3413c60249..8b938dbe07 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -120,6 +120,7 @@ namespace Content.Client.Entry "SurgeryTool", "EmitSoundOnThrow", "Flash", + "Docking", "Telecrystal", "TrashSpawner", "RCD", diff --git a/Content.Server/Doors/Components/ServerDoorComponent.cs b/Content.Server/Doors/Components/ServerDoorComponent.cs index ee9bdccf6f..a35b185885 100644 --- a/Content.Server/Doors/Components/ServerDoorComponent.cs +++ b/Content.Server/Doors/Components/ServerDoorComponent.cs @@ -11,22 +11,18 @@ using Content.Server.Construction; using Content.Server.Construction.Components; using Content.Server.Hands.Components; using Content.Server.Stunnable; -using Content.Server.Stunnable.Components; using Content.Server.Tools; using Content.Server.Tools.Components; using Content.Shared.Damage; using Content.Shared.Doors; using Content.Shared.Interaction; using Content.Shared.Sound; -using Content.Shared.Stunnable; using Content.Shared.Tools; -using Content.Shared.Tools.Components; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Log; using Robust.Shared.Maths; -using Robust.Shared.Physics; using Robust.Shared.Player; using Robust.Shared.Players; using Robust.Shared.Prototypes; @@ -276,6 +272,11 @@ namespace Content.Server.Doors.Components public void TryOpen(IEntity? user=null) { + var msg = new DoorOpenAttemptEvent(); + Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, msg); + + if (msg.Cancelled) return; + if (user == null) { // a machine opened it or something, idk @@ -412,6 +413,11 @@ namespace Content.Server.Doors.Components public void TryClose(IEntity? user=null) { + var msg = new DoorCloseAttemptEvent(); + Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, msg); + + if (msg.Cancelled) return; + if (user != null && !CanCloseByEntity(user)) { Deny(); @@ -495,7 +501,7 @@ namespace Content.Server.Doors.Components if (CloseSound != null) { SoundSystem.Play(Filter.Pvs(Owner), CloseSound.GetSound(), Owner, - AudioParams.Default.WithVolume(-10)); + AudioParams.Default.WithVolume(-5)); } Owner.SpawnTimer(CloseTimeOne, async () => @@ -673,8 +679,10 @@ namespace Content.Server.Doors.Components var canEv = new BeforeDoorPryEvent(eventArgs); Owner.EntityManager.EventBus.RaiseLocalEvent(Owner.Uid, canEv, false); + if (canEv.Cancelled) return false; + var successfulPry = await toolSystem.UseTool(eventArgs.Using.Uid, eventArgs.User.Uid, Owner.Uid, - 0f, ev.PryTimeModifier * PryTime, _pryingQuality, () => !canEv.Cancelled); + 0f, ev.PryTimeModifier * PryTime, _pryingQuality); if (successfulPry && !IsWeldedShut) { diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index 5c06695e26..0734b30371 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -99,7 +99,7 @@ namespace Content.Server.Physics.Controllers // inputs will do different things. // TODO: Do that float speedCap; - var angularSpeed = 0.75f; + var angularSpeed = 0.075f; // ShuttleSystem has already worked out the ratio so we'll just multiply it back by the mass. var movement = (mover.VelocityDir.walking + mover.VelocityDir.sprinting); diff --git a/Content.Server/Shuttles/DockingSystem.cs b/Content.Server/Shuttles/DockingSystem.cs new file mode 100644 index 0000000000..952f7a7a7e --- /dev/null +++ b/Content.Server/Shuttles/DockingSystem.cs @@ -0,0 +1,494 @@ +using System; +using Content.Server.Doors.Components; +using Content.Server.Power.Components; +using Content.Shared.Doors; +using Content.Shared.Shuttles; +using Content.Shared.Verbs; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Log; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Collision.Shapes; +using Robust.Shared.Physics.Dynamics; +using Robust.Shared.Physics.Dynamics.Joints; +using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; + +namespace Content.Server.Shuttles +{ + [RegisterComponent] + public sealed class DockingComponent : SharedDockingComponent + { + [ViewVariables] + public DockingComponent? DockedWith; + + [ViewVariables] + public Joint? DockJoint; + + [ViewVariables] + public override bool Docked => DockedWith != null; + } + + public sealed class DockingSystem : EntitySystem + { + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphaseSystem = default!; + [Dependency] private readonly SharedJointSystem _jointSystem = default!; + + private const string DockingFixture = "docking"; + private const string DockingJoint = "docking"; + private const float DockingRadius = 0.20f; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnPowerChange); + SubscribeLocalEvent(OnAnchorChange); + + SubscribeLocalEvent(OnVerb); + SubscribeLocalEvent(OnAutoClose); + SubscribeLocalEvent(OnDoorOpenAttempt); + SubscribeLocalEvent(OnDoorCloseAttempt); + } + + // Won't allow users to override door controls + private void OnDoorOpenAttempt(EntityUid uid, DockingComponent component, DoorOpenAttemptEvent args) + { + args.Cancel(); + } + + private void OnDoorCloseAttempt(EntityUid uid, DockingComponent component, DoorCloseAttemptEvent args) + { + args.Cancel(); + } + + private void OnAutoClose(EntityUid uid, DockingComponent component, BeforeDoorAutoCloseEvent args) + { + // We'll just pin the door open when docked. + if (component.Docked) + args.Cancel(); + } + + private void OnVerb(EntityUid uid, DockingComponent component, GetInteractionVerbsEvent args) + { + if (!args.CanInteract || + !args.CanAccess) return; + + Verb? verb; + + // TODO: Have it open the UI and have the UI do this. + if (!component.Docked && + EntityManager.TryGetComponent(uid, out PhysicsComponent? body) && + EntityManager.TryGetComponent(uid, out TransformComponent? xform)) + { + DockingComponent? otherDock = null; + + if (component.Enabled) + otherDock = GetDockable(body, xform); + + verb = new Verb + { + Disabled = otherDock == null, + Text = Loc.GetString("docking-component-dock"), + Act = () => + { + if (otherDock == null) return; + TryDock(component, otherDock); + } + }; + } + else if (component.Docked) + { + verb = new Verb + { + Disabled = !component.Docked, + Text = Loc.GetString("docking-component-undock"), + Act = () => + { + if (component.DockedWith == null || !component.Enabled) return; + + Undock(component); + } + }; + } + else + { + return; + } + + args.Verbs.Add(verb); + } + + private DockingComponent? GetDockable(PhysicsComponent body, TransformComponent dockingXform) + { + // Did you know Saltern is the most dockable station? + + // Assume the docking port itself (and its body) is valid + + if (!_mapManager.TryGetGrid(dockingXform.GridID, out var grid) || + !EntityManager.HasComponent(grid.GridEntityId)) return null; + + var transform = body.GetTransform(); + var dockingFixture = body.GetFixture(DockingFixture); + + if (dockingFixture == null) + { + DebugTools.Assert(false); + Logger.ErrorS("docking", $"Found null fixture on {EntityManager.GetEntity(body.OwnerUid)}"); + return null; + } + + Box2? aabb = null; + + for (var i = 0; i < dockingFixture.Shape.ChildCount; i++) + { + aabb = aabb?.Union(dockingFixture.Shape.ComputeAABB(transform, i)) ?? dockingFixture.Shape.ComputeAABB(transform, i); + } + + if (aabb == null) return null; + + var enlargedAABB = aabb.Value.Enlarged(DockingRadius * 1.5f); + + // Get any docking ports in range on other grids. + _mapManager.FindGridsIntersectingEnumerator(dockingXform.MapID, enlargedAABB, out var enumerator); + + while (enumerator.MoveNext(out var otherGrid)) + { + if (otherGrid.Index == dockingXform.GridID) continue; + + foreach (var ent in otherGrid.GetAnchoredEntities(enlargedAABB)) + { + if (!EntityManager.TryGetComponent(ent, out DockingComponent? otherDocking) || + !otherDocking.Enabled || + !EntityManager.TryGetComponent(ent, out PhysicsComponent? otherBody)) continue; + + var otherTransform = otherBody.GetTransform(); + var otherDockingFixture = otherBody.GetFixture(DockingFixture); + + if (otherDockingFixture == null) + { + DebugTools.Assert(false); + Logger.ErrorS("docking", $"Found null docking fixture on {EntityManager.GetEntity(ent)}"); + continue; + } + + for (var i = 0; i < otherDockingFixture.Shape.ChildCount; i++) + { + var otherAABB = otherDockingFixture.Shape.ComputeAABB(otherTransform, i); + + if (!aabb.Value.Intersects(otherAABB)) continue; + + // TODO: Need CollisionManager's GJK for accurate bounds + // Realistically I want 2 fixtures anyway but I'll deal with that later. + return otherDocking; + } + } + } + + return null; + } + + private void OnShutdown(EntityUid uid, DockingComponent component, ComponentShutdown args) + { + if (component.DockedWith == null || + EntityManager.GetComponent(uid).EntityLifeStage > EntityLifeStage.MapInitialized) return; + + Cleanup(component); + } + + private void Cleanup(DockingComponent dockA) + { + _jointSystem.RemoveJoint(dockA.DockJoint!); + + var dockB = dockA.DockedWith; + + if (dockB == null || dockA.DockJoint == null) + { + DebugTools.Assert(false); + Logger.Error("docking", $"Tried to cleanup {dockA.OwnerUid} but not docked?"); + + dockA.DockedWith = null; + if (dockA.DockJoint != null) + { + // We'll still cleanup the dock joint on release at least + _jointSystem.RemoveJoint(dockA.DockJoint); + } + + return; + } + + dockB.DockedWith = null; + dockB.DockJoint = null; + + dockA.DockJoint = null; + dockA.DockedWith = null; + + // If these grids are ever invalid then need to look at fixing ordering for unanchored events elsewhere. + var gridAUid = _mapManager.GetGrid(EntityManager.GetComponent(dockA.OwnerUid).GridID).GridEntityId; + var gridBUid = _mapManager.GetGrid(EntityManager.GetComponent(dockB.OwnerUid).GridID).GridEntityId; + + var msg = new UndockEvent + { + DockA = dockA, + DockB = dockB, + GridAUid = gridAUid, + GridBUid = gridBUid, + }; + + EntityManager.EventBus.RaiseLocalEvent(dockA.OwnerUid, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockB.OwnerUid, msg, false); + EntityManager.EventBus.RaiseEvent(EventSource.Local, msg); + } + + private void OnStartup(EntityUid uid, DockingComponent component, ComponentStartup args) + { + // Use startup so transform already initialized + if (!EntityManager.GetComponent(uid).Anchored) return; + + EnableDocking(uid, component); + } + + private void OnAnchorChange(EntityUid uid, DockingComponent component, ref AnchorStateChangedEvent args) + { + if (args.Anchored) + { + EnableDocking(uid, component); + } + else + { + DisableDocking(uid, component); + } + } + + private void OnPowerChange(EntityUid uid, DockingComponent component, PowerChangedEvent args) + { + if (args.Powered) + { + EnableDocking(uid, component); + } + else + { + DisableDocking(uid, component); + } + } + + private void DisableDocking(EntityUid uid, DockingComponent component) + { + if (!component.Enabled) return; + + component.Enabled = false; + + if (component.DockedWith != null) + { + Undock(component); + } + + if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) + { + return; + } + + _broadphaseSystem.DestroyFixture(physicsComponent, DockingFixture); + } + + private void EnableDocking(EntityUid uid, DockingComponent component) + { + if (component.Enabled) + return; + + if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) + return; + + component.Enabled = true; + + // TODO: WTF IS THIS GARBAGE + var shape = new PhysShapeCircle + { + // Want half of the unit vector + Position = new Vector2(0f, -0.5f), + Radius = DockingRadius + }; + + // Listen it makes intersection tests easier; you can probably dump this but it requires a bunch more boilerplate + var fixture = new Fixture(physicsComponent, shape) + { + ID = DockingFixture, + Hard = false, + }; + + // TODO: I want this to ideally be 2 fixtures to force them to have some level of alignment buuuttt + // I also need collisionmanager for that yet again so they get dis. + _broadphaseSystem.CreateFixture(physicsComponent, fixture); + } + + /// + /// Docks 2 ports together and assumes it is valid. + /// + private void Dock(DockingComponent dockA, DockingComponent dockB) + { + Logger.DebugS("docking", $"Docking between {dockA.Owner} and {dockB.Owner}"); + + // https://gamedev.stackexchange.com/questions/98772/b2distancejoint-with-frequency-equal-to-0-vs-b2weldjoint + + // We could also potentially use a prismatic joint? Depending if we want clamps that can extend or whatever + + var dockAXform = EntityManager.GetComponent(dockA.OwnerUid); + var dockBXform = EntityManager.GetComponent(dockB.OwnerUid); + + var gridA = _mapManager.GetGrid(dockAXform.GridID).GridEntityId; + var gridB = _mapManager.GetGrid(dockBXform.GridID).GridEntityId; + + SharedJointSystem.LinearStiffness( + 2f, + 0.7f, + EntityManager.GetComponent(gridA).Mass, + EntityManager.GetComponent(gridB).Mass, + out var stiffness, + out var damping); + + // These need playing around with + // Could also potentially have collideconnected false and stiffness 0 but it was a bit more suss??? + var joint = _jointSystem.CreateWeldJoint(gridA, gridB, DockingJoint + dockA.OwnerUid); + + var gridAXform = EntityManager.GetComponent(gridA); + var gridBXform = EntityManager.GetComponent(gridB); + + var anchorA = dockAXform.LocalPosition + dockAXform.LocalRotation.ToWorldVec() / 2f; + var anchorB = dockBXform.LocalPosition + dockBXform.LocalRotation.ToWorldVec() / 2f; + + joint.LocalAnchorA = anchorA; + joint.LocalAnchorB = anchorB; + joint.ReferenceAngle = (float) (gridBXform.WorldRotation - gridAXform.WorldRotation); + joint.CollideConnected = true; + joint.Stiffness = stiffness; + joint.Damping = damping; + + dockA.DockedWith = dockB; + dockB.DockedWith = dockA; + dockA.DockJoint = joint; + dockB.DockJoint = joint; + + if (EntityManager.TryGetComponent(dockA.OwnerUid, out ServerDoorComponent? doorA)) + { + doorA.Open(); + } + + if (EntityManager.TryGetComponent(dockB.OwnerUid, out ServerDoorComponent? doorB)) + { + doorB.Open(); + } + + var msg = new DockEvent + { + DockA = dockA, + DockB = dockB, + GridAUid = gridA, + GridBUid = gridB, + }; + + EntityManager.EventBus.RaiseLocalEvent(dockA.OwnerUid, msg, false); + EntityManager.EventBus.RaiseLocalEvent(dockB.OwnerUid, msg, false); + EntityManager.EventBus.RaiseEvent(EventSource.Local, msg); + } + + /// + /// Attempts to dock 2 ports together and will return early if it's not possible. + /// + private void TryDock(DockingComponent dockA, DockingComponent dockB) + { + if (!EntityManager.TryGetComponent(dockA.OwnerUid, out PhysicsComponent? bodyA) || + !EntityManager.TryGetComponent(dockB.OwnerUid, out PhysicsComponent? bodyB) || + !dockA.Enabled || + !dockB.Enabled) + { + return; + } + + var fixtureA = bodyA.GetFixture(DockingFixture); + var fixtureB = bodyB.GetFixture(DockingFixture); + + if (fixtureA == null || fixtureB == null) + { + return; + } + + var transformA = bodyA.GetTransform(); + var transformB = bodyB.GetTransform(); + var intersect = false; + + for (var i = 0; i < fixtureA.Shape.ChildCount; i++) + { + var aabb = fixtureA.Shape.ComputeAABB(transformA, i); + + for (var j = 0; j < fixtureB.Shape.ChildCount; j++) + { + var otherAABB = fixtureB.Shape.ComputeAABB(transformB, j); + if (!aabb.Intersects(otherAABB)) continue; + + // TODO: Need collisionmanager's GJK for accurate checks don't @ me son + intersect = true; + break; + } + + if (intersect) break; + } + + if (!intersect) return; + + Dock(dockA, dockB); + } + + private void Undock(DockingComponent dock) + { + if (dock.DockedWith == null) + { + DebugTools.Assert(false); + Logger.ErrorS("docking", $"Tried to undock {dock.OwnerUid} but not docked with anything?"); + return; + } + + if (EntityManager.TryGetComponent(dock.OwnerUid, out ServerDoorComponent? doorA)) + { + doorA.Close(); + } + + if (EntityManager.TryGetComponent(dock.DockedWith.OwnerUid, out ServerDoorComponent? doorB)) + { + doorB.Close(); + } + + // Could maybe give the shuttle a light push away, or at least if there's no other docks left? + + Cleanup(dock); + } + + /// + /// Raised whenever 2 airlocks dock. + /// + public sealed class DockEvent : EntityEventArgs + { + public DockingComponent DockA = default!; + public DockingComponent DockB = default!; + + public EntityUid GridAUid = default!; + public EntityUid GridBUid = default!; + } + + /// + /// Raised whenever 2 grids undock. + /// + public sealed class UndockEvent : EntityEventArgs + { + public DockingComponent DockA = default!; + public DockingComponent DockB = default!; + + public EntityUid GridAUid = default!; + public EntityUid GridBUid = default!; + } + } +} diff --git a/Content.Server/Shuttles/ShuttleComponent.cs b/Content.Server/Shuttles/ShuttleComponent.cs index 5cbf09536d..952b3bda19 100644 --- a/Content.Server/Shuttles/ShuttleComponent.cs +++ b/Content.Server/Shuttles/ShuttleComponent.cs @@ -4,8 +4,5 @@ using Robust.Shared.GameObjects; namespace Content.Server.Shuttles { [RegisterComponent] - public class ShuttleComponent : SharedShuttleComponent - { - - } + public sealed class ShuttleComponent : SharedShuttleComponent {} } diff --git a/Content.Server/Shuttles/ShuttleSystem.cs b/Content.Server/Shuttles/ShuttleSystem.cs index e8cb2977f6..45d3e1c4c9 100644 --- a/Content.Server/Shuttles/ShuttleSystem.cs +++ b/Content.Server/Shuttles/ShuttleSystem.cs @@ -126,7 +126,7 @@ namespace Content.Server.Shuttles //component.FixedRotation = false; TODO WHEN ROTATING SHUTTLES FIXED. component.FixedRotation = false; component.LinearDamping = 0.2f; - component.AngularDamping = 0.1f; + component.AngularDamping = 0.3f; } private void Disable(PhysicsComponent component) diff --git a/Content.Shared/Doors/SharedDoorComponent.cs b/Content.Shared/Doors/SharedDoorComponent.cs index e85da53ff9..812043d6ea 100644 --- a/Content.Shared/Doors/SharedDoorComponent.cs +++ b/Content.Shared/Doors/SharedDoorComponent.cs @@ -11,7 +11,7 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.Doors { - [NetworkedComponent()] + [NetworkedComponent] public abstract class SharedDoorComponent : Component { public override string Name => "Door"; @@ -177,4 +177,14 @@ namespace Content.Shared.Doors CurTime = curTime; } } + + public sealed class DoorOpenAttemptEvent : CancellableEntityEventArgs + { + + } + + public sealed class DoorCloseAttemptEvent : CancellableEntityEventArgs + { + + } } diff --git a/Content.Shared/Shuttles/SharedDockingComponent.cs b/Content.Shared/Shuttles/SharedDockingComponent.cs new file mode 100644 index 0000000000..30baf5be43 --- /dev/null +++ b/Content.Shared/Shuttles/SharedDockingComponent.cs @@ -0,0 +1,18 @@ +using Robust.Shared.GameObjects; +using Robust.Shared.GameStates; +using Robust.Shared.ViewVariables; + +namespace Content.Shared.Shuttles +{ + public abstract class SharedDockingComponent : Component + { + // Yes I left this in for now because there's no overhead and we'll need a client one later anyway + // and I was too lazy to delete it. + public override string Name => "Docking"; + + [ViewVariables] + public bool Enabled = false; + + public abstract bool Docked { get; } + } +} diff --git a/Resources/Audio/Effects/docking.ogg b/Resources/Audio/Effects/docking.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5f94a19b883814248ca408de67e6c5042a102ea4 GIT binary patch literal 31515 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 e^v*usGx`UW8!3IEdSR^q0000U zr*XxK70s%S($I*1X3w6jS^^=y=;FnTYUa$D-eWH8-Md$vKYw1eb^as(M1J7F0r3s4 zUcD+hX2bI3%M(sYfVRxvNC!cF?AS5Y-28uy)V+ImHDJI1b@Jp%b^ZGF1{Hv&rl#h@ zhYza@7cQvNr%$Va0|!>V0~bW-z_Fu8k0zX7zI-XHBM(2G9{_hz9a8>A{UVdBfB*iu z5+68nBQCgg+I4o;`c2zkmNmNqm=xAwz~(&&9*P zdGkiKYu7HCju3vJp`jtF4j+Fi04O5J1t(6Nh?4j=5wm8^VjH`T9XlpljA_qufHQYt^Hoo?N_MdhV>-{f!g07x))?AYk{bT#}Y zI(P1zRL5w1tIb=J0q}KG^8j_Z6t`~ON~(#cPoGBNMU{qULfc}ZCIf&0P?@0qzupzC z7LovL+_*7m{aXt+Z{AdE)~u=g-{g<21vyV|SbhA!+qZ8E>mXjVY5Jf}=T8E#Y15|U z;I3V}RJE~o?OL^R6^)jsNG*pVs191avfL;}tApXY2_)Qb>O8C(Q zMU@dl2lzU4=#aE)J$m%W@K+d61Vg%Nd4aASrfsK9o0d9WZGOsFQvM%5ex!145#HXt zdsqH%@+SdUw{BfRxO3;uWF%Nk?AWm*;rsUOTjiL^AG->|{V>fSKC|ZW-$$U69f+jzTe(WHi8j$j%!9)VZ&;j1Qefy@4>HIZ04yXoV zPc2A6qiJp+Sd#(J`^>R0bm&lZ<;oS&xmYxbr2`{s4Cuy>AFuA*xs&<6CIf)pNNn7_ zd$$w~#QXjGckB150Bqj8S(S-u@=F?2;*XgDh?nc$rviYf(tl{)x^-*RH37_xW2Fgm z;)@n7vYtcyG1nx(3qDjQs9L1_NVqd+&JmjbUtlotH+~!-fqL@fXPiHr{^y`Xvpq$)8!0gkh)}iSYXMYwzr0On#0RpQlfs zUNwFfFKPf2sQ^&xU+qNT5R0GVMVHW}qbR?R7jBC&W5%SeNd@51qesc_SUF+g!iDP9 zt5+#8u7!~p{CRj|@Jo2{`TqU;YRZ%;m1C6vU}UC`2GM_o2?@aL-TwXiqjkZui=Gw68s7Z@MSSuuUp#*x&7gOS9fKma#@)<~r`s6uZ zJV35v8(zG4k$U)09X{SZeflK#;R4XBS1)z;>{&Hu&YWN!W)N(=xW5UjI~t@#eezsl zV5G=FAARQ4;o`*)d44z`vGVA!l|YjhfgCkzREjSZ06hm5^~u|O@xY-&hn&}$4Q zjXyIG(?!Ja$?Lv&dLV9t1g%Kn+@d;cyaXRVA&(9huZ`cjBuN(+@yXkYIqq-v0(8)K zMRerhHTm`Hq&o8QW~v~x1B4XJUZNfY5x5ANka+uLZ}W2 zFCEw28P2(&*7V8Of)02$Irl;g9i~AGNbL_8H*Q>}$mH?KbG~@od(fak>fE_=R)7Aa zNs|&+GMyW$!^ey6B;0P?{(xuCo+TDVR52ksq`U|m&SUonzy$y=JE4eA-t@%-D9$%- z++h9r;GZyILgm~%IyhbcRl&i72c7(wjzB3O9;pr=FMx5w_U+r<`vY_*FHpoMZ*v#> z{P`3B6CpZWu4W%UOtfUE4b|auQzNk6{Q)|P_~cDryndVmXNU^X!SPD@U8T&W!^cZb z>EQhVd42MxFP@Nhe}Gg6$1CMWSJMSfhmRM5MecX*4>0{Qd42LWUp#8)g-#0ZivHYu7uTHv{dN)&|L&A$6l(1E+R;fLE_Sp9a-~_$VDdLm2 z`QmYJh~oVD=rN#|LFeYt;o?OuMK0v{(Tl+kI6`$uc;N{`32T-80X|=RE%H*LSBn>o zu-S!m2B3&fp7X^cS8#JNmoHx~ti#1i;M$r?mo7Q)?b0FPeemExhCeeMZO#bhwQAdZ z@pNx)Hc}UxSBHz2=61LYp!0|7knj@N$vE?ZB0hPWFCO=`P5GMq`uU+cT)e&vz-g1{ zknj@N>1Zq-VE(#@Pu}H=r_~}3SOlTz-cTJ9URpTkO2F~s$CDK=)YDQOA-n{(1i-^i z(az(O_xa*|K|oIe=K~=+it-YsPMw<6(^&hJ=m_P7ZwTMh;y;iI0G8XR@0!OQ?DNHw zC~k)e&cl>67R{wPLU<`L^aRj>ffObr0iO=MVl$K%jWY$7km&_cOD}nNUm}>kc+{b; z9V+M@kYhojBb1jCg9`wFbz7m1WcDnAsm-_K~aMlXv;^$+YFuVVlvE0CO;s{Qg2!0T_H>B!~qG2-Lmux<@{b zCm#K3EXZT9$NBToZ>E>F+H}AoUW6BT{`|R>zbs^?BCyj5!o%Y` zmqVIHikyxjyZ}De5>f$xH5*HUG+H&i@}@^V#1oH|Abh5TaKWb|FE0jIwT4sx$TCMW zdp57U>5;c3hRqX?hsQ7x7z91`1uRIbTka*&Cgf57FA;sXt$$ zBZSw-Uj{PvbPlFhUVq2GK4B&G;@cp(&eRcuw@jo0fCd%~9?VC`;V!Sd{*Hf}6~pwz zlj95xq-(&0>u^7*ju2k>I?0((E6B_Rp}U6lP%IC+yz-<;_#3~a?qEtr+FO6SJ{xXr-A3&=` zD7tU}a9(-cMXXyfY@T=|E~*h!C%bp=cKY*i9k@~bNOVYf(JjTO*tS2ROl0;4=ni3* zS6=EBMZ!@cpgNH34*E3w#9NiPIyB3x#S;G4Bu|EMW1nSmGbVzwons9Ht*2d&76RG_H z=zC*Y0f1naS6=tX>p7J3#N&Rb3Xl^ye?Cp1!5}5o5yFcG8bL7m%S2`zK(mG+eQ($H zee%R3$LTvTeaNFD25)O46#&kkZ-Z_|HQ&u|^Tg|L?FB0`QuXoHA~O2}T+ruV^d5`; zZhpzcScpI0rz3>d$6p45rlSGd1L_SL=ZV)*bUNCmL&EFhF9VtBXzER1Snu=71LnK= zIZr%5F9VTGM~CQ;@)Byc1kg*Ru@;M=yw58SVD3hLH$Ufz2XH?mD7Pq&gwofHr8>+Y zaJ(2_)Y`gmDgbaHkgFG6ONm!rcL=kB29(JbB~IMRRPz#@K;-V__^EMR?0VCIIl`V6g>*vOHdS-5YQ7@c8~( zHs#PFI`Z(A1@`X;=*a7p*FEvn@S#3-`SV?-tq>hHUb?ncTya2se?ZBo?++*${{foY VTo-Xamg@ij002ovPDHLkV1gAomXrVh literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/meta.json b/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/meta.json new file mode 100644 index 0000000000..fb51d45117 --- /dev/null +++ b/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/meta.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from CEV-Eris at commit https://github.com/discordia-space/CEV-Eris/commit/14517938186858388656a6aee14bf47af9e9649f", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "closed" + }, + { + "name": "open" + }, + { + "name": "closing", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "opening", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/open.png b/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/open.png new file mode 100644 index 0000000000000000000000000000000000000000..4a4e534504f92a186655ae93a9255b2ef9a1c7a3 GIT binary patch literal 614 zcmV-s0-61ZP)(oiGo%n5($lefSy`HuMrW2LLn$b zq4iPI3gQoFs3fA6Xi%b%u-BP;ckQq~@2qXS37gEAeII8|X3pVbv6uiFipMX%-w!8{ zrx%UKWAJ*t56AAQR;$5qIQ#_=&6~~U(=V7zCQpqiDH@FuPYFOY?{qpK2jVt^Lr3Bn@t%2Lv%PCpxf;-F;{}{ z`FvEeQviiR0n+I-Q}as*kH>R60-sPOlerxME%XH-0NHF7_WS+EOlPwhBoc`;KrWXf zgVkzPb@OC03GsLwoK7csN?U*f^?Dt2I-RNj+wGQkiK21<40JlJXMyn;f zXYkr~yWMAiR4PT1uu`dzlTb~S%VpxX+wIN(rBdmoV&uPaxm=_kppsB4eE}$dd_J!& z0A7`U5{ktl)0*Ivc!I;>fKyEXp-@N}03(3qG8QH*A<#S!2*7f=1cSjq&0Upb*f6k! z5Y5-?HEcGUt9c3lOJ)=+h)3pE0Q32rJXu5n&4a-ptX3<^oa5-%NC0>;$xlNp9I+`u z;qBFEG?+E9Vpk*qi2qhTaZjw8Qwac@MEq!>AC$csvNGyOO8@`>07*qoM6N<$f{Zx? AYybcN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/opening.png b/Resources/Textures/Structures/Doors/Airlocks/Standard/shuttle.rsi/opening.png new file mode 100644 index 0000000000000000000000000000000000000000..2e19084260b7bc02ecbdf420cb04bc254d847a8b GIT binary patch literal 3428 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 literal 0 HcmV?d00001