From b5d48e4db0ce9d986745f4428d6c189a515889fa Mon Sep 17 00:00:00 2001 From: Markek1 <51086796+Markek1@users.noreply.github.com> Date: Mon, 2 Nov 2020 11:31:27 +0100 Subject: [PATCH 01/41] Fixed crematorium creating ash out of nothing and being allowed to cremate while open (#2473) --- .../CrematoriumEntityStorageComponent.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs index 761c64561c..879fd4d5b5 100644 --- a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs @@ -55,6 +55,7 @@ namespace Content.Server.GameObjects.Components.Morgue public void Cremate() { if (Cooking) return; + if (Open) return; Appearance?.SetData(CrematoriumVisuals.Burning, true); Cooking = true; @@ -64,16 +65,19 @@ namespace Content.Server.GameObjects.Components.Morgue Appearance?.SetData(CrematoriumVisuals.Burning, false); Cooking = false; - for (var i = Contents.ContainedEntities.Count - 1; i >= 0; i--) + if (Contents.ContainedEntities.Count > 0) { - var item = Contents.ContainedEntities[i]; - Contents.Remove(item); - item.Delete(); + for (var i = Contents.ContainedEntities.Count - 1; i >= 0; i--) + { + var item = Contents.ContainedEntities[i]; + Contents.Remove(item); + item.Delete(); + } + + var ash = Owner.EntityManager.SpawnEntity("Ash", Owner.Transform.Coordinates); + Contents.Insert(ash); } - - var ash = Owner.EntityManager.SpawnEntity("Ash", Owner.Transform.Coordinates); - Contents.Insert(ash); - + TryOpenStorage(Owner); EntitySystem.Get().PlayFromEntity("/Audio/Machines/ding.ogg", Owner); From 015539dcdc07ae1231c23df29f91f57c37c0e847 Mon Sep 17 00:00:00 2001 From: Tomeno Date: Mon, 2 Nov 2020 11:32:03 +0100 Subject: [PATCH 02/41] Revert to old cooldown and unify with DoAfter (#2469) Co-authored-by: Tomeno --- .../EntitySystems/DoAfter/DoAfterBar.cs | 26 +++++++------------ .../UserInterface/CooldownGraphic.cs | 14 +++------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterBar.cs b/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterBar.cs index 982b5b9d12..b6a1af64da 100644 --- a/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterBar.cs +++ b/Content.Client/GameObjects/EntitySystems/DoAfter/DoAfterBar.cs @@ -56,23 +56,20 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter /// Is the cancellation bar red? /// private bool _flash = true; - + /// /// Last time we swapped the flash. /// private TimeSpan _lastFlash; - + /// /// How long each cancellation bar flash lasts in seconds. /// private const float FlashTime = 0.125f; - + private const int XPixelDiff = 20 * DoAfterBarScale; public const byte DoAfterBarScale = 2; - private static readonly Color StartColor = new Color(0.8f, 0.0f, 0.2f); // red - private static readonly Color EndColor = new Color(0.92f, 0.77f, 0.34f); // yellow - private static readonly Color CompletedColor = new Color(0.0f, 0.8f, 0.27f); // green public DoAfterBar() { @@ -108,28 +105,25 @@ namespace Content.Client.GameObjects.EntitySystems.DoAfter } color = new Color(1.0f, 0.0f, 0.0f, _flash ? 1.0f : 0.0f); - } + } else if (Ratio >= 1.0f) { - color = CompletedColor; + color = new Color(0f, 1f, 0f); } else { // lerp - color = new Color( - StartColor.R + (EndColor.R - StartColor.R) * Ratio, - StartColor.G + (EndColor.G - StartColor.G) * Ratio, - StartColor.B + (EndColor.B - StartColor.B) * Ratio, - StartColor.A); + var hue = (5f / 18f) * Ratio; + color = Color.FromHsv((hue, 1f, 0.75f, 1f)); } - + handle.UseShader(_shader); // If you want to make this less hard-coded be my guest var leftOffset = 2 * DoAfterBarScale; var box = new UIBox2i( - leftOffset, + leftOffset, -2 + 2 * DoAfterBarScale, - leftOffset + (int) (XPixelDiff * Ratio), + leftOffset + (int) (XPixelDiff * Ratio), -2); handle.DrawRect(box, color); } diff --git a/Content.Client/UserInterface/CooldownGraphic.cs b/Content.Client/UserInterface/CooldownGraphic.cs index a77972ab81..d281c73e99 100644 --- a/Content.Client/UserInterface/CooldownGraphic.cs +++ b/Content.Client/UserInterface/CooldownGraphic.cs @@ -27,29 +27,23 @@ namespace Content.Client.UserInterface /// Possible values range from 1 to -1, where 1 to 0 is a depleting circle animation and 0 to -1 is a blink animation. /// public float Progress { get; set; } - private static readonly Color StartColor = new Color(0.8f, 0.0f, 0.2f); // red - private static readonly Color EndColor = new Color(0.92f, 0.77f, 0.34f); // yellow - private static readonly Color CompletedColor = new Color(0.0f, 0.8f, 0.27f); // green protected override void Draw(DrawingHandleScreen handle) { - Span x = stackalloc float[10]; + Span x = new float[10]; Color color; var lerp = 1f - MathF.Abs(Progress); // for future bikeshedding purposes if (Progress >= 0f) { - color = new Color( - EndColor.R + (StartColor.R - EndColor.R) * Progress, - EndColor.G + (StartColor.G - EndColor.G) * Progress, - EndColor.B + (StartColor.B - EndColor.B) * Progress, - EndColor.A); + var hue = (5f / 18f) * lerp; + color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f)); } else { var alpha = MathHelper.Clamp(0.5f * lerp, 0f, 0.5f); - color = CompletedColor.WithAlpha(alpha); + color = new Color(1f, 1f, 1f, alpha); } _shader.SetParameter("progress", Progress); From 6b4a39006eabd434c4cc0e602a62710e4a91f1b8 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Mon, 2 Nov 2020 11:37:37 +0100 Subject: [PATCH 03/41] Make mechanism behaviors properly update, fix eating and drinking (#2472) * Make mechanisms properly update and fix eating and drinking * Remove outdated component ignores * Fix nullable error * Fix mechanism behavior events * Remove unnecessary code --- .../Body/Mechanism/HeartBehaviorComponent.cs | 12 -- Content.Client/IgnoredComponents.cs | 3 - .../Tests/Body/LungTest.cs | 6 +- .../Tests/Body/MechanismBehaviorEventsTest.cs | 93 ++++++------- Content.Server/Commands/Hungry.cs | 39 ++++++ ...nBehaviorComponent.cs => BrainBehavior.cs} | 14 +- ...tBehaviorComponent.cs => HeartBehavior.cs} | 9 +- ...ngBehaviorComponent.cs => LungBehavior.cs} | 29 ++-- .../Body/Behavior/MechanismBehavior.cs | 28 ++-- .../Body/Behavior}/MechanismExtensions.cs | 21 ++- .../Body/Behavior/StomachBehavior.cs | 26 +++- .../Body/Behavior/StomachBehaviorComponent.cs | 24 ---- .../Components/Chemistry/PillComponent.cs | 2 +- .../Metabolism/MetabolismComponent.cs | 2 +- .../Components/Nutrition/DrinkComponent.cs | 2 +- .../Components/Nutrition/FoodComponent.cs | 3 +- .../GameObjects/EntitySystems/HeartSystem.cs | 28 ---- .../GameObjects/EntitySystems/LungSystem.cs | 28 ---- .../Body/Behavior/IMechanismBehavior.cs | 18 ++- .../Behavior/SharedHeartBehaviorComponent.cs | 8 -- .../Behavior/SharedLungBehaviorComponent.cs | 39 ------ .../Components/Body/Mechanism/IMechanism.cs | 20 +++ .../Mechanism/SharedMechanismComponent.cs | 126 ++++++++++++++---- .../Nutrition/SharedStomachComponent.cs | 12 -- .../EntitySystems/MechanismSystem.cs | 21 +++ Resources/Groups/groups.yml | 2 + .../Body/Mechanisms/basic_human_organs.yml | 14 +- .../Entities/Mobs/Species/human.yml | 3 - 28 files changed, 326 insertions(+), 306 deletions(-) delete mode 100644 Content.Client/GameObjects/Components/Body/Mechanism/HeartBehaviorComponent.cs create mode 100644 Content.Server/Commands/Hungry.cs rename Content.Server/GameObjects/Components/Body/Behavior/{BrainBehaviorComponent.cs => BrainBehavior.cs} (80%) rename Content.Server/GameObjects/Components/Body/Behavior/{HeartBehaviorComponent.cs => HeartBehavior.cs} (71%) rename Content.Server/GameObjects/Components/Body/Behavior/{LungBehaviorComponent.cs => LungBehavior.cs} (91%) rename Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs => Content.Server/GameObjects/Components/Body/Behavior/MechanismBehavior.cs (75%) rename {Content.Shared/GameObjects/Components/Body/Mechanism => Content.Server/GameObjects/Components/Body/Behavior}/MechanismExtensions.cs (79%) rename Content.Shared/GameObjects/Components/Body/Behavior/SharedStomachBehaviorComponent.cs => Content.Server/GameObjects/Components/Body/Behavior/StomachBehavior.cs (88%) delete mode 100644 Content.Server/GameObjects/Components/Body/Behavior/StomachBehaviorComponent.cs delete mode 100644 Content.Server/GameObjects/EntitySystems/HeartSystem.cs delete mode 100644 Content.Server/GameObjects/EntitySystems/LungSystem.cs delete mode 100644 Content.Shared/GameObjects/Components/Body/Behavior/SharedHeartBehaviorComponent.cs delete mode 100644 Content.Shared/GameObjects/Components/Body/Behavior/SharedLungBehaviorComponent.cs delete mode 100644 Content.Shared/GameObjects/Components/Nutrition/SharedStomachComponent.cs create mode 100644 Content.Shared/GameObjects/EntitySystems/MechanismSystem.cs diff --git a/Content.Client/GameObjects/Components/Body/Mechanism/HeartBehaviorComponent.cs b/Content.Client/GameObjects/Components/Body/Mechanism/HeartBehaviorComponent.cs deleted file mode 100644 index 0131117d81..0000000000 --- a/Content.Client/GameObjects/Components/Body/Mechanism/HeartBehaviorComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Content.Shared.GameObjects.Components.Body.Behavior; -using Robust.Shared.GameObjects; - -namespace Content.Client.GameObjects.Components.Body.Mechanism -{ - [RegisterComponent] - [ComponentReference(typeof(SharedHeartBehaviorComponent))] - public class HeartBehaviorComponent : SharedHeartBehaviorComponent - { - public override void Update(float frameTime) { } - } -} diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index b54be45138..38483522c7 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -58,7 +58,6 @@ "Drink", "Food", "FoodContainer", - "Stomach", "Rotatable", "MagicMirror", "FloorTile", @@ -180,10 +179,8 @@ "BreakableConstruction", "GasCanister", "GasCanisterPort", - "Lung", "Cleanable", "Configuration", - "Brain", "PlantHolder", "SeedExtractor", "Produce", diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs index 30c181e189..6722ea41a0 100644 --- a/Content.IntegrationTests/Tests/Body/LungTest.cs +++ b/Content.IntegrationTests/Tests/Body/LungTest.cs @@ -20,7 +20,7 @@ using Robust.Shared.Maths; namespace Content.IntegrationTests.Tests.Body { [TestFixture] - [TestOf(typeof(LungBehaviorComponent))] + [TestOf(typeof(LungBehavior))] public class LungTest : ContentIntegrationTest { [Test] @@ -39,7 +39,7 @@ namespace Content.IntegrationTests.Tests.Body var human = entityManager.SpawnEntity("HumanMob_Content", MapCoordinates.Nullspace); Assert.That(human.TryGetComponent(out IBody body)); - Assert.That(body.TryGetMechanismBehaviors(out List lungs)); + Assert.That(body.TryGetMechanismBehaviors(out List lungs)); Assert.That(lungs.Count, Is.EqualTo(1)); Assert.That(human.TryGetComponent(out BloodstreamComponent bloodstream)); @@ -141,7 +141,7 @@ namespace Content.IntegrationTests.Tests.Body human = entityManager.SpawnEntity("HumanMob_Content", coordinates); Assert.True(human.TryGetComponent(out IBody body)); - Assert.True(body.HasMechanismBehavior()); + Assert.True(body.HasMechanismBehavior()); Assert.True(human.TryGetComponent(out metabolism)); Assert.False(metabolism.Suffocating); }); diff --git a/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs b/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs index e3c571496e..08afb1ae91 100644 --- a/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs +++ b/Content.IntegrationTests/Tests/Body/MechanismBehaviorEventsTest.cs @@ -1,12 +1,12 @@ #nullable enable using System.Linq; using System.Threading.Tasks; +using Content.Server.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Body.Part; using NUnit.Framework; -using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; @@ -18,14 +18,11 @@ namespace Content.IntegrationTests.Tests.Body [TestOf(typeof(SharedBodyComponent))] [TestOf(typeof(SharedBodyPartComponent))] [TestOf(typeof(SharedMechanismComponent))] - [TestOf(typeof(MechanismBehaviorComponent))] + [TestOf(typeof(MechanismBehavior))] public class MechanismBehaviorEventsTest : ContentIntegrationTest { - [RegisterComponent] - private class TestBehaviorComponent : MechanismBehaviorComponent + private class TestMechanismBehavior : MechanismBehavior { - public override string Name => nameof(MechanismBehaviorEventsTest) + "TestBehavior"; - public bool WasAddedToBody; public bool WasAddedToPart; public bool WasAddedToPartInBody; @@ -33,8 +30,6 @@ namespace Content.IntegrationTests.Tests.Body public bool WasRemovedFromPart; public bool WasRemovedFromPartInBody; - public override void Update(float frameTime) { } - public bool NoAdded() { return !WasAddedToBody && !WasAddedToPart && !WasAddedToPartInBody; @@ -111,13 +106,7 @@ namespace Content.IntegrationTests.Tests.Body [Test] public async Task EventsTest() { - var server = StartServerDummyTicker(new ServerContentIntegrationOption - { - ContentBeforeIoC = () => - { - IoCManager.Resolve().Register(); - } - }); + var server = StartServerDummyTicker(); await server.WaitAssertion(() => { @@ -141,68 +130,68 @@ namespace Content.IntegrationTests.Tests.Body var mechanism = centerPart!.Mechanisms.First(); Assert.NotNull(mechanism); - var component = mechanism.Owner.AddComponent(); - Assert.False(component.WasAddedToBody); - Assert.False(component.WasAddedToPart); - Assert.That(component.WasAddedToPartInBody); - Assert.That(component.NoRemoved); + mechanism.EnsureBehavior(out var behavior); + Assert.False(behavior.WasAddedToBody); + Assert.False(behavior.WasAddedToPart); + Assert.That(behavior.WasAddedToPartInBody); + Assert.That(behavior.NoRemoved); - component.ResetAll(); + behavior.ResetAll(); - Assert.That(component.NoAdded); - Assert.That(component.NoRemoved); + Assert.That(behavior.NoAdded); + Assert.That(behavior.NoRemoved); centerPart.RemoveMechanism(mechanism); - Assert.That(component.NoAdded); - Assert.False(component.WasRemovedFromBody); - Assert.False(component.WasRemovedFromPart); - Assert.That(component.WasRemovedFromPartInBody); + Assert.That(behavior.NoAdded); + Assert.False(behavior.WasRemovedFromBody); + Assert.False(behavior.WasRemovedFromPart); + Assert.That(behavior.WasRemovedFromPartInBody); - component.ResetAll(); + behavior.ResetAll(); centerPart.TryAddMechanism(mechanism, true); - Assert.False(component.WasAddedToBody); - Assert.False(component.WasAddedToPart); - Assert.That(component.WasAddedToPartInBody); - Assert.That(component.NoRemoved()); + Assert.False(behavior.WasAddedToBody); + Assert.False(behavior.WasAddedToPart); + Assert.That(behavior.WasAddedToPartInBody); + Assert.That(behavior.NoRemoved()); - component.ResetAll(); + behavior.ResetAll(); body.RemovePart(centerPart); - Assert.That(component.NoAdded); - Assert.That(component.WasRemovedFromBody); - Assert.False(component.WasRemovedFromPart); - Assert.False(component.WasRemovedFromPartInBody); + Assert.That(behavior.NoAdded); + Assert.That(behavior.WasRemovedFromBody); + Assert.False(behavior.WasRemovedFromPart); + Assert.False(behavior.WasRemovedFromPartInBody); - component.ResetAll(); + behavior.ResetAll(); centerPart.RemoveMechanism(mechanism); - Assert.That(component.NoAdded); - Assert.False(component.WasRemovedFromBody); - Assert.That(component.WasRemovedFromPart); - Assert.False(component.WasRemovedFromPartInBody); + Assert.That(behavior.NoAdded); + Assert.False(behavior.WasRemovedFromBody); + Assert.That(behavior.WasRemovedFromPart); + Assert.False(behavior.WasRemovedFromPartInBody); - component.ResetAll(); + behavior.ResetAll(); centerPart.TryAddMechanism(mechanism, true); - Assert.False(component.WasAddedToBody); - Assert.That(component.WasAddedToPart); - Assert.False(component.WasAddedToPartInBody); - Assert.That(component.NoRemoved); + Assert.False(behavior.WasAddedToBody); + Assert.That(behavior.WasAddedToPart); + Assert.False(behavior.WasAddedToPartInBody); + Assert.That(behavior.NoRemoved); - component.ResetAll(); + behavior.ResetAll(); body.TryAddPart(centerSlot!, centerPart, true); - Assert.That(component.WasAddedToBody); - Assert.False(component.WasAddedToPart); - Assert.False(component.WasAddedToPartInBody); - Assert.That(component.NoRemoved); + Assert.That(behavior.WasAddedToBody); + Assert.False(behavior.WasAddedToPart); + Assert.False(behavior.WasAddedToPartInBody); + Assert.That(behavior.NoRemoved); }); } } diff --git a/Content.Server/Commands/Hungry.cs b/Content.Server/Commands/Hungry.cs new file mode 100644 index 0000000000..b3a56c0171 --- /dev/null +++ b/Content.Server/Commands/Hungry.cs @@ -0,0 +1,39 @@ +#nullable enable +using Content.Server.GameObjects.Components.Nutrition; +using Content.Shared.GameObjects.Components.Nutrition; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; + +namespace Content.Server.Commands +{ + public class Hungry : IClientCommand + { + public string Command => "hungry"; + public string Description => "Makes you hungry."; + public string Help => $"{Command}"; + + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + if (player == null) + { + shell.SendText(player, "You cannot use this command unless you are a player."); + return; + } + + if (player.AttachedEntity == null) + { + shell.SendText(player, "You cannot use this command without an entity."); + return; + } + + if (!player.AttachedEntity.TryGetComponent(out HungerComponent? hunger)) + { + shell.SendText(player, $"Your entity does not have a {nameof(HungerComponent)} component."); + return; + } + + var hungryThreshold = hunger.HungerThresholds[HungerThreshold.Starving]; + hunger.CurrentHunger = hungryThreshold; + } + } +} diff --git a/Content.Server/GameObjects/Components/Body/Behavior/BrainBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/BrainBehavior.cs similarity index 80% rename from Content.Server/GameObjects/Components/Body/Behavior/BrainBehaviorComponent.cs rename to Content.Server/GameObjects/Components/Body/Behavior/BrainBehavior.cs index 0dff9e5a98..d5533a961d 100644 --- a/Content.Server/GameObjects/Components/Body/Behavior/BrainBehaviorComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/BrainBehavior.cs @@ -1,22 +1,14 @@ #nullable enable using Content.Server.GameObjects.Components.Mobs; -using Content.Server.Mobs; using Content.Shared.GameObjects.Components.Body; -using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Part; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.ComponentDependencies; using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Log; -using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Body.Behavior { - [RegisterComponent] - public class BrainBehaviorComponent : MechanismBehaviorComponent + public class BrainBehavior : MechanismBehavior { - public override string Name => "Brain"; - protected override void OnAddedToBody(IBody body) { base.OnAddedToBody(body); @@ -66,9 +58,5 @@ namespace Content.Server.GameObjects.Components.Body.Behavior oldMind.Mind?.TransferTo(newEntity); } - - public override void Update(float frameTime) - { - } } } diff --git a/Content.Server/GameObjects/Components/Body/Behavior/HeartBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/HeartBehavior.cs similarity index 71% rename from Content.Server/GameObjects/Components/Body/Behavior/HeartBehaviorComponent.cs rename to Content.Server/GameObjects/Components/Body/Behavior/HeartBehavior.cs index 9b0c9bc5fb..855c5831ef 100644 --- a/Content.Server/GameObjects/Components/Body/Behavior/HeartBehaviorComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/HeartBehavior.cs @@ -1,20 +1,17 @@ using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Networks; -using Robust.Shared.GameObjects; namespace Content.Server.GameObjects.Components.Body.Behavior { - [RegisterComponent] - [ComponentReference(typeof(SharedHeartBehaviorComponent))] - public class HeartBehaviorComponent : SharedHeartBehaviorComponent + public class HeartBehavior : MechanismBehavior { private float _accumulatedFrameTime; public override void Update(float frameTime) { // TODO BODY do between pre and metabolism - if (Mechanism?.Body == null || - !Mechanism.Body.Owner.HasComponent()) + if (Parent.Body == null || + !Parent.Body.Owner.HasComponent()) { return; } diff --git a/Content.Server/GameObjects/Components/Body/Behavior/LungBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/LungBehavior.cs similarity index 91% rename from Content.Server/GameObjects/Components/Body/Behavior/LungBehaviorComponent.cs rename to Content.Server/GameObjects/Components/Body/Behavior/LungBehavior.cs index 195733fe71..6755c4d6b2 100644 --- a/Content.Server/GameObjects/Components/Body/Behavior/LungBehaviorComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/LungBehavior.cs @@ -8,19 +8,15 @@ using Content.Server.GameObjects.Components.Body.Respiratory; using Content.Server.Utility; using Content.Shared.Atmos; using Content.Shared.GameObjects.Components.Body.Behavior; -using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; -using Robust.Shared.Log; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Body.Behavior { - [RegisterComponent] - [ComponentReference(typeof(SharedLungBehaviorComponent))] - public class LungBehaviorComponent : SharedLungBehaviorComponent + public class LungBehavior : MechanismBehavior { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -30,18 +26,24 @@ namespace Content.Server.GameObjects.Components.Body.Behavior [ViewVariables] public GasMixture Air { get; set; } = default!; - [ViewVariables] public override float Temperature => Air.Temperature; + [ViewVariables] public float Temperature => Air.Temperature; - [ViewVariables] public override float Volume => Air.Volume; + [ViewVariables] public float Volume => Air.Volume; [ViewVariables] public TimeSpan GaspPopupCooldown { get; private set; } + [ViewVariables] public LungStatus Status { get; set; } + + [ViewVariables] public float CycleDelay { get; set; } + public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); Air = new GasMixture {Temperature = Atmospherics.NormalBodyTemperature}; + serializer.DataField(this, l => l.CycleDelay, "cycleDelay", 2); + serializer.DataReadWriteFunction( "volume", 6, @@ -61,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior () => GaspPopupCooldown.TotalSeconds); } - public override void Gasp() + public void Gasp() { if (_gameTiming.CurTime >= _lastGaspPopupTime + GaspPopupCooldown) { @@ -148,7 +150,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior _accumulatedFrameTime = absoluteTime - delay; } - public override void Inhale(float frameTime) + public void Inhale(float frameTime) { if (Body != null && Body.Owner.TryGetComponent(out InternalsComponent? internals) && internals.BreathToolEntity != null && internals.GasTankEntity != null @@ -176,7 +178,7 @@ namespace Content.Server.GameObjects.Components.Body.Behavior ToBloodstream(Air); } - public override void Exhale(float frameTime) + public void Exhale(float frameTime) { if (!Owner.Transform.Coordinates.TryGetTileAir(out var tileAir)) { @@ -218,4 +220,11 @@ namespace Content.Server.GameObjects.Components.Body.Behavior Air.Merge(lungRemoved); } } + + public enum LungStatus + { + None = 0, + Inhaling, + Exhaling + } } diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/MechanismBehavior.cs similarity index 75% rename from Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs rename to Content.Server/GameObjects/Components/Body/Behavior/MechanismBehavior.cs index f4a0683eca..ca571ab0ac 100644 --- a/Content.Shared/GameObjects/Components/Body/Behavior/MechanismBehaviorComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/MechanismBehavior.cs @@ -1,23 +1,33 @@ #nullable enable +using Content.Shared.GameObjects.Components.Body; +using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Body.Part; -using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Serialization; using Robust.Shared.Utility; -namespace Content.Shared.GameObjects.Components.Body.Behavior +namespace Content.Server.GameObjects.Components.Body.Behavior { - public abstract class MechanismBehaviorComponent : Component, IMechanismBehavior + public abstract class MechanismBehavior : IMechanismBehavior { public IBody? Body => Part?.Body; - public IBodyPart? Part => Mechanism?.Part; + public IBodyPart? Part => Parent.Part; - public IMechanism? Mechanism => Owner.GetComponentOrNull(); + public IMechanism Parent { get; private set; } = default!; - protected override void Startup() + public IEntity Owner => Parent.Owner; + + public virtual void ExposeData(ObjectSerializer serializer) { } + + public virtual void Initialize(IMechanism parent) { - base.Startup(); + Parent = parent; + } + public virtual void Startup() + { if (Part == null) { return; @@ -33,8 +43,6 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior } } - public abstract void Update(float frameTime); - public void AddedToBody(IBody body) { DebugTools.AssertNotNull(Body); @@ -98,5 +106,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior protected virtual void OnRemovedFromPart(IBodyPart old) { } protected virtual void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart) { } + + public virtual void Update(float frameTime) { } } } diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs b/Content.Server/GameObjects/Components/Body/Behavior/MechanismExtensions.cs similarity index 79% rename from Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs rename to Content.Server/GameObjects/Components/Body/Behavior/MechanismExtensions.cs index 8dfb8750de..453b089c94 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/MechanismExtensions.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/MechanismExtensions.cs @@ -2,33 +2,29 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Part; -namespace Content.Shared.GameObjects.Components.Body.Mechanism +namespace Content.Server.GameObjects.Components.Body.Behavior { public static class MechanismExtensions { - public static bool HasMechanismBehavior(this IBody body) + public static bool HasMechanismBehavior(this IBody body) where T : IMechanismBehavior { return body.Parts.Values.Any(p => p.HasMechanismBehavior()); } - public static bool HasMechanismBehavior(this IBodyPart part) + public static bool HasMechanismBehavior(this IBodyPart part) where T : IMechanismBehavior { - return part.Mechanisms.Any(m => m.Owner.HasComponent()); - } - - public static bool HasMechanismBehavior(this IMechanism mechanism) - { - return mechanism.Owner.HasComponent(); + return part.Mechanisms.Any(m => m.HasBehavior()); } public static IEnumerable GetMechanismBehaviors(this IBody body) { foreach (var part in body.Parts.Values) foreach (var mechanism in part.Mechanisms) - foreach (var behavior in mechanism.Owner.GetAllComponents()) + foreach (var behavior in mechanism.Behaviors.Values) { yield return behavior; } @@ -52,10 +48,11 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism { foreach (var part in body.Parts.Values) foreach (var mechanism in part.Mechanisms) + foreach (var behavior in mechanism.Behaviors.Values) { - if (mechanism.Owner.TryGetComponent(out T? behavior)) + if (behavior is T tBehavior) { - yield return behavior; + yield return tBehavior; } } } diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/SharedStomachBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/StomachBehavior.cs similarity index 88% rename from Content.Shared/GameObjects/Components/Body/Behavior/SharedStomachBehaviorComponent.cs rename to Content.Server/GameObjects/Components/Body/Behavior/StomachBehavior.cs index 2045a1f0fa..6bb18a8a89 100644 --- a/Content.Shared/GameObjects/Components/Body/Behavior/SharedStomachBehaviorComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Behavior/StomachBehavior.cs @@ -1,23 +1,23 @@ -#nullable enable +#nullable enable using System.Collections.Generic; using System.Linq; +using Content.Server.GameObjects.Components.Chemistry; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Body.Networks; using Content.Shared.GameObjects.Components.Chemistry; using Robust.Shared.GameObjects; +using Robust.Shared.Log; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -namespace Content.Shared.GameObjects.Components.Body.Behavior +namespace Content.Server.GameObjects.Components.Body.Behavior { /// /// Where reagents go when ingested. Tracks ingested reagents over time, and /// eventually transfers them to once digested. /// - public abstract class SharedStomachBehaviorComponent : MechanismBehaviorComponent + public class StomachBehavior : MechanismBehavior { - public override string Name => "Stomach"; - private float _accumulatedFrameTime; /// @@ -45,7 +45,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior _accumulatedFrameTime -= 1; - if (!Body.Owner.TryGetComponent(out SharedSolutionContainerComponent? solution) || + if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solution) || !Body.Owner.TryGetComponent(out SharedBloodstreamComponent? bloodstream)) { return; @@ -58,7 +58,7 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior foreach (var delta in _reagentDeltas.ToList()) { //Increment lifetime of reagents - delta.Increment(frameTime); + delta.Increment(1); if (delta.Lifetime > _digestionDelay) { solution.TryRemoveReagent(delta.ReagentId, delta.Quantity); @@ -112,6 +112,18 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior serializer.DataField(ref _digestionDelay, "digestionDelay", 20); } + public override void Startup() + { + base.Startup(); + + if (!Owner.EnsureComponent(out SolutionContainerComponent solution)) + { + Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}"); + } + + solution.MaxVolume = InitialMaxVolume; + } + public bool CanTransferSolution(Solution solution) { if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solutionComponent)) diff --git a/Content.Server/GameObjects/Components/Body/Behavior/StomachBehaviorComponent.cs b/Content.Server/GameObjects/Components/Body/Behavior/StomachBehaviorComponent.cs deleted file mode 100644 index 10476d09c6..0000000000 --- a/Content.Server/GameObjects/Components/Body/Behavior/StomachBehaviorComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Server.GameObjects.Components.Chemistry; -using Content.Shared.GameObjects.Components.Body.Behavior; -using Robust.Shared.GameObjects; -using Robust.Shared.Log; - -namespace Content.Server.GameObjects.Components.Body.Behavior -{ - [RegisterComponent] - [ComponentReference(typeof(SharedStomachBehaviorComponent))] - public class StomachBehaviorComponent : SharedStomachBehaviorComponent - { - protected override void Startup() - { - base.Startup(); - - if (!Owner.EnsureComponent(out SolutionContainerComponent solution)) - { - Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}"); - } - - solution.MaxVolume = InitialMaxVolume; - } - } -} diff --git a/Content.Server/GameObjects/Components/Chemistry/PillComponent.cs b/Content.Server/GameObjects/Components/Chemistry/PillComponent.cs index a507974bea..b6b7f1ea26 100644 --- a/Content.Server/GameObjects/Components/Chemistry/PillComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/PillComponent.cs @@ -84,7 +84,7 @@ namespace Content.Server.GameObjects.Components.Chemistry var trueTarget = target ?? user; if (!trueTarget.TryGetComponent(out IBody body) || - !body.TryGetMechanismBehaviors(out var stomachs)) + !body.TryGetMechanismBehaviors(out var stomachs)) { return false; } diff --git a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs index a93e3dec88..05ed21f0e2 100644 --- a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs +++ b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs @@ -192,7 +192,7 @@ namespace Content.Server.GameObjects.Components.Metabolism return; } - var lungs = _body.GetMechanismBehaviors().ToArray(); + var lungs = _body.GetMechanismBehaviors().ToArray(); var needs = NeedsAndDeficit(frameTime); var used = 0f; diff --git a/Content.Server/GameObjects/Components/Nutrition/DrinkComponent.cs b/Content.Server/GameObjects/Components/Nutrition/DrinkComponent.cs index 29625d59cb..709bc3bf32 100644 --- a/Content.Server/GameObjects/Components/Nutrition/DrinkComponent.cs +++ b/Content.Server/GameObjects/Components/Nutrition/DrinkComponent.cs @@ -153,7 +153,7 @@ namespace Content.Server.GameObjects.Components.Nutrition } if (!target.TryGetComponent(out IBody body) || - !body.TryGetMechanismBehaviors(out var stomachs)) + !body.TryGetMechanismBehaviors(out var stomachs)) { return false; } diff --git a/Content.Server/GameObjects/Components/Nutrition/FoodComponent.cs b/Content.Server/GameObjects/Components/Nutrition/FoodComponent.cs index 0dbfc3f292..a71ff53d02 100644 --- a/Content.Server/GameObjects/Components/Nutrition/FoodComponent.cs +++ b/Content.Server/GameObjects/Components/Nutrition/FoodComponent.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Content.Server.GameObjects.Components.Body.Behavior; using Content.Server.GameObjects.Components.Chemistry; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; @@ -133,7 +134,7 @@ namespace Content.Server.GameObjects.Components.Nutrition var trueTarget = target ?? user; if (!trueTarget.TryGetComponent(out IBody? body) || - !body.TryGetMechanismBehaviors(out var stomachs)) + !body.TryGetMechanismBehaviors(out var stomachs)) { return false; } diff --git a/Content.Server/GameObjects/EntitySystems/HeartSystem.cs b/Content.Server/GameObjects/EntitySystems/HeartSystem.cs deleted file mode 100644 index e1da130db4..0000000000 --- a/Content.Server/GameObjects/EntitySystems/HeartSystem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Shared.GameObjects.Components.Body.Behavior; -using Content.Shared.GameObjects.EntitySystems; -using JetBrains.Annotations; -using Robust.Shared.GameObjects.Systems; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - public class HeartSystem : EntitySystem - { - public override void Initialize() - { - base.Initialize(); - - UpdatesBefore.Add(typeof(MetabolismSystem)); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var heart in ComponentManager.EntityQuery()) - { - heart.Update(frameTime); - } - } - } -} diff --git a/Content.Server/GameObjects/EntitySystems/LungSystem.cs b/Content.Server/GameObjects/EntitySystems/LungSystem.cs deleted file mode 100644 index 6b04f5f0d1..0000000000 --- a/Content.Server/GameObjects/EntitySystems/LungSystem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Shared.GameObjects.Components.Body.Behavior; -using Content.Shared.GameObjects.EntitySystems; -using JetBrains.Annotations; -using Robust.Shared.GameObjects.Systems; - -namespace Content.Server.GameObjects.EntitySystems -{ - [UsedImplicitly] - public class LungSystem : EntitySystem - { - public override void Initialize() - { - base.Initialize(); - - UpdatesBefore.Add(typeof(MetabolismSystem)); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var lung in ComponentManager.EntityQuery()) - { - lung.Update(frameTime); - } - } - } -} diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs b/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs index 2e38200f58..e1ddcb17b8 100644 --- a/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs +++ b/Content.Shared/GameObjects/Components/Body/Behavior/IMechanismBehavior.cs @@ -2,10 +2,11 @@ using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Body.Part; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Serialization; namespace Content.Shared.GameObjects.Components.Body.Behavior { - public interface IMechanismBehavior : IComponent + public interface IMechanismBehavior : IExposeData { IBody? Body { get; } @@ -15,7 +16,20 @@ namespace Content.Shared.GameObjects.Components.Body.Behavior /// Upward reference to the parent that this /// behavior is attached to. /// - IMechanism? Mechanism { get; } + IMechanism Parent { get; } + + /// + /// The entity that owns . + /// For the entity owning the body that this mechanism may be in, + /// see + /// + IEntity Owner { get; } + + void Initialize(IMechanism parent); + + void Startup(); + + void Update(float frameTime); /// /// Called when the containing is attached to a diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/SharedHeartBehaviorComponent.cs b/Content.Shared/GameObjects/Components/Body/Behavior/SharedHeartBehaviorComponent.cs deleted file mode 100644 index 6d4f6c0f3d..0000000000 --- a/Content.Shared/GameObjects/Components/Body/Behavior/SharedHeartBehaviorComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -#nullable enable -namespace Content.Shared.GameObjects.Components.Body.Behavior -{ - public abstract class SharedHeartBehaviorComponent : MechanismBehaviorComponent - { - public override string Name => "Heart"; - } -} diff --git a/Content.Shared/GameObjects/Components/Body/Behavior/SharedLungBehaviorComponent.cs b/Content.Shared/GameObjects/Components/Body/Behavior/SharedLungBehaviorComponent.cs deleted file mode 100644 index dbbff4e9d9..0000000000 --- a/Content.Shared/GameObjects/Components/Body/Behavior/SharedLungBehaviorComponent.cs +++ /dev/null @@ -1,39 +0,0 @@ -#nullable enable -using Robust.Shared.Serialization; -using Robust.Shared.ViewVariables; - -namespace Content.Shared.GameObjects.Components.Body.Behavior -{ - public abstract class SharedLungBehaviorComponent : MechanismBehaviorComponent - { - public override string Name => "Lung"; - - [ViewVariables] public abstract float Temperature { get; } - - [ViewVariables] public abstract float Volume { get; } - - [ViewVariables] public LungStatus Status { get; set; } - - [ViewVariables] public float CycleDelay { get; set; } - - public override void ExposeData(ObjectSerializer serializer) - { - base.ExposeData(serializer); - - serializer.DataField(this, l => l.CycleDelay, "cycleDelay", 2); - } - - public abstract void Inhale(float frameTime); - - public abstract void Exhale(float frameTime); - - public abstract void Gasp(); - } - - public enum LungStatus - { - None = 0, - Inhaling, - Exhaling - } -} diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs b/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs index 092b838819..f6f82627cb 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs +++ b/Content.Shared/GameObjects/Components/Body/Mechanism/IMechanism.cs @@ -1,4 +1,7 @@ #nullable enable +using System; +using System.Collections.Generic; +using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Part; using Robust.Shared.Interfaces.GameObjects; @@ -10,6 +13,8 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism IBodyPart? Part { get; set; } + IReadOnlyDictionary Behaviors { get; } + /// /// Professional description of the . /// @@ -55,6 +60,21 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism /// BodyPartCompatibility Compatibility { get; set; } + /// + /// Adds a behavior if it does not exist already. + /// + /// The behavior type to add. + /// + /// True if the behavior already existed, false if it had to be created. + /// + bool EnsureBehavior(out T behavior) where T : IMechanismBehavior, new(); + + bool HasBehavior() where T : IMechanismBehavior; + + bool TryRemoveBehavior() where T : IMechanismBehavior; + + void Update(float frameTime); + // TODO BODY Turn these into event listeners so they dont need to be exposed /// /// Called when the containing is attached to a diff --git a/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs b/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs index cfd6d8e2f9..7ac3c76ce2 100644 --- a/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs +++ b/Content.Shared/GameObjects/Components/Body/Mechanism/SharedMechanismComponent.cs @@ -1,10 +1,14 @@ #nullable enable +using System; using System.Collections.Generic; using System.Linq; using Content.Shared.GameObjects.Components.Body.Behavior; using Content.Shared.GameObjects.Components.Body.Part; +using Content.Shared.Interfaces; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Log; using Robust.Shared.Serialization; using Robust.Shared.Utility; @@ -14,11 +18,12 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism { public override string Name => "Mechanism"; - private IBodyPart? _part; protected readonly Dictionary OptionsCache = new Dictionary(); protected IBody? BodyCache; protected int IdHash; protected IEntity? PerformerCache; + private IBodyPart? _part; + private readonly Dictionary _behaviors = new Dictionary(); public IBody? Body => Part?.Body; @@ -61,6 +66,8 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism } } + public IReadOnlyDictionary Behaviors => _behaviors; + public string Description { get; set; } = string.Empty; public string ExamineMessage { get; set; } = string.Empty; @@ -98,6 +105,91 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism serializer.DataField(this, m => m.Size, "size", 1); serializer.DataField(this, m => m.Compatibility, "compatibility", BodyPartCompatibility.Universal); + + var moduleManager = IoCManager.Resolve(); + + if (moduleManager.IsServerModule) + { + serializer.DataReadWriteFunction( + "behaviors", + null!, + behaviors => + { + if (behaviors == null) + { + return; + } + + foreach (var behavior in behaviors) + { + var type = behavior.GetType(); + + if (!_behaviors.TryAdd(type, behavior)) + { + Logger.Warning($"Duplicate behavior in {nameof(SharedMechanismComponent)} for entity {Owner.Name}: {type}."); + continue; + } + + IoCManager.InjectDependencies(behavior); + } + }, + () => _behaviors.Values.ToList()); + } + } + + public override void Initialize() + { + base.Initialize(); + + foreach (var behavior in _behaviors.Values) + { + behavior.Initialize(this); + } + } + + protected override void Startup() + { + base.Startup(); + + foreach (var behavior in _behaviors.Values) + { + behavior.Startup(); + } + } + + public bool EnsureBehavior(out T behavior) where T : IMechanismBehavior, new() + { + if (_behaviors.TryGetValue(typeof(T), out var rawBehavior)) + { + behavior = (T) rawBehavior; + return true; + } + + behavior = new T(); + IoCManager.InjectDependencies(behavior); + _behaviors.Add(typeof(T), behavior); + behavior.Initialize(this); + behavior.Startup(); + + return false; + } + + public bool HasBehavior() where T : IMechanismBehavior + { + return _behaviors.ContainsKey(typeof(T)); + } + + public bool TryRemoveBehavior() where T : IMechanismBehavior + { + return _behaviors.Remove(typeof(T)); + } + + public void Update(float frameTime) + { + foreach (var behavior in _behaviors.Values) + { + behavior.Update(frameTime); + } } public void AddedToBody(IBody body) @@ -105,9 +197,7 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNotNull(Body); DebugTools.AssertNotNull(body); - OnAddedToBody(body); - - foreach (var behavior in Owner.GetAllComponents()) + foreach (var behavior in _behaviors.Values) { behavior.AddedToBody(body); } @@ -119,9 +209,8 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNotNull(part); Owner.Transform.AttachParent(part.Owner); - OnAddedToPart(part); - foreach (var behavior in Owner.GetAllComponents().ToArray()) + foreach (var behavior in _behaviors.Values) { behavior.AddedToPart(part); } @@ -135,9 +224,8 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNotNull(part); Owner.Transform.AttachParent(part.Owner); - OnAddedToPartInBody(body, part); - foreach (var behavior in Owner.GetAllComponents()) + foreach (var behavior in _behaviors.Values) { behavior.AddedToPartInBody(body, part); } @@ -148,9 +236,7 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNull(Body); DebugTools.AssertNotNull(old); - OnRemovedFromBody(old); - - foreach (var behavior in Owner.GetAllComponents()) + foreach (var behavior in _behaviors.Values) { behavior.RemovedFromBody(old); } @@ -162,9 +248,8 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNotNull(old); Owner.Transform.AttachToGridOrMap(); - OnRemovedFromPart(old); - foreach (var behavior in Owner.GetAllComponents()) + foreach (var behavior in _behaviors.Values) { behavior.RemovedFromPart(old); } @@ -178,24 +263,11 @@ namespace Content.Shared.GameObjects.Components.Body.Mechanism DebugTools.AssertNotNull(oldPart); Owner.Transform.AttachToGridOrMap(); - OnRemovedFromPartInBody(oldBody, oldPart); - foreach (var behavior in Owner.GetAllComponents()) + foreach (var behavior in _behaviors.Values) { behavior.RemovedFromPartInBody(oldBody, oldPart); } } - - protected virtual void OnAddedToBody(IBody body) { } - - protected virtual void OnAddedToPart(IBodyPart part) { } - - protected virtual void OnAddedToPartInBody(IBody body, IBodyPart part) { } - - protected virtual void OnRemovedFromBody(IBody old) { } - - protected virtual void OnRemovedFromPart(IBodyPart old) { } - - protected virtual void OnRemovedFromPartInBody(IBody oldBody, IBodyPart oldPart) { } } } diff --git a/Content.Shared/GameObjects/Components/Nutrition/SharedStomachComponent.cs b/Content.Shared/GameObjects/Components/Nutrition/SharedStomachComponent.cs deleted file mode 100644 index 030b1eae50..0000000000 --- a/Content.Shared/GameObjects/Components/Nutrition/SharedStomachComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Robust.Shared.GameObjects; - -namespace Content.Shared.GameObjects.Components.Nutrition -{ - /// - /// Shared class for stomach components - /// - public class SharedStomachComponent : Component - { - public override string Name => "Stomach"; - } -} diff --git a/Content.Shared/GameObjects/EntitySystems/MechanismSystem.cs b/Content.Shared/GameObjects/EntitySystems/MechanismSystem.cs new file mode 100644 index 0000000000..d3e9dd0daa --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/MechanismSystem.cs @@ -0,0 +1,21 @@ +using Content.Shared.GameObjects.Components.Body.Behavior; +using Content.Shared.GameObjects.Components.Body.Mechanism; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Shared.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class MechanismSystem : EntitySystem + { + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var mechanism in ComponentManager.EntityQuery()) + { + mechanism.Update(frameTime); + } + } + } +} diff --git a/Resources/Groups/groups.yml b/Resources/Groups/groups.yml index dbcc86b674..b9f90c5639 100644 --- a/Resources/Groups/groups.yml +++ b/Resources/Groups/groups.yml @@ -119,6 +119,7 @@ - attachtogrid - attachtograndparent - inrangeunoccluded + - hungry CanViewVar: true CanAdminPlace: true CanAdminMenu: true @@ -231,6 +232,7 @@ - attachtogrid - attachtograndparent - inrangeunoccluded + - hungry CanViewVar: true CanAdminPlace: true CanScript: true diff --git a/Resources/Prototypes/Body/Mechanisms/basic_human_organs.yml b/Resources/Prototypes/Body/Mechanisms/basic_human_organs.yml index e85f15d2f1..c4a85d1a40 100644 --- a/Resources/Prototypes/Body/Mechanisms/basic_human_organs.yml +++ b/Resources/Prototypes/Body/Mechanisms/basic_human_organs.yml @@ -11,7 +11,8 @@ durability: 10 size: 1 compatibility: Biological - - type: Brain + behaviors: + - !type:BrainBehavior {} - type: entity id: EyesHuman @@ -40,7 +41,8 @@ durability: 10 size: 1 compatibility: Biological - - type: Heart + behaviors: + - !type:HeartBehavior {} - type: entity id: LungsHuman @@ -55,7 +57,8 @@ durability: 13 size: 1 compatibility: Biological - - type: Lung + behaviors: + - !type:LungBehavior {} - type: entity id: StomachHuman @@ -70,7 +73,10 @@ durability: 13 size: 1 compatibility: Biological - - type: Stomach + behaviors: + - !type:StomachBehavior + max_volume: 250 + digestionDelay: 20 - type: entity id: LiverHuman diff --git a/Resources/Prototypes/Entities/Mobs/Species/human.yml b/Resources/Prototypes/Entities/Mobs/Species/human.yml index 3fd79f3b08..c5b20bba9a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/human.yml @@ -23,9 +23,6 @@ caps: AddTo, RemoveFrom, NoExamine - type: Bloodstream max_volume: 100 - - type: Stomach - max_volume: 250 - digestionDelay: 20 # StatusEffects - type: Stunnable # Other From 1817a4a81663d9eeaa4ee5d4c7aaeb6095e7b6cc Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Mon, 2 Nov 2020 11:41:07 +0100 Subject: [PATCH 04/41] Change events command to give better instructions on how to use it (#2456) --- .../StationEvents/StationEventCommand.cs | 160 ++++++++++-------- 1 file changed, 89 insertions(+), 71 deletions(-) diff --git a/Content.Server/StationEvents/StationEventCommand.cs b/Content.Server/StationEvents/StationEventCommand.cs index 108baba460..1c6f1f6928 100644 --- a/Content.Server/StationEvents/StationEventCommand.cs +++ b/Content.Server/StationEvents/StationEventCommand.cs @@ -13,88 +13,106 @@ namespace Content.Server.StationEvents { public string Command => "events"; public string Description => "Provides admin control to station events"; - public string Help => "events >\n" + - "list: return all event names that can be run\n " + - "pause: stop all random events from running\n" + - "resume: allow random events to run again\n" + - "run: start a particular event now; is case-insensitive and not localized"; + public string Help => $"events >\n{ListHelp}\n{PauseHelp}\n{ResumeHelp}\n{RunHelp}"; + + private const string ListHelp = "list: return all event names that can be run"; + + private const string PauseHelp = "pause: stop all random events from running and any one currently running"; + + private const string ResumeHelp = "resume: allow random events to run again"; + + private const string RunHelp = + "run : start a particular event now; is case-insensitive and not localized"; + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) { if (args.Length == 0) { - shell.SendText(player, "Need more args"); - return; - } - - if (args[0] == "list") - { - var resultText = "Random\n" + EntitySystem.Get().GetEventNames(); - shell.SendText(player, resultText); - return; - } - - // Didn't use a "toggle" so it's explicit - if (args[0] == "pause") - { - var stationEventSystem = EntitySystem.Get(); - - if (!stationEventSystem.Enabled) - { - shell.SendText(player, Loc.GetString("Station events are already paused")); - return; - } - else - { - stationEventSystem.Enabled = false; - shell.SendText(player, Loc.GetString("Station events paused")); - return; - } - } - - if (args[0] == "resume") - { - var stationEventSystem = EntitySystem.Get(); - - if (stationEventSystem.Enabled) - { - shell.SendText(player, Loc.GetString("Station events are already running")); - return; - } - else - { - stationEventSystem.Enabled = true; - shell.SendText(player, Loc.GetString("Station events resumed")); - return; - } - } - - if (args[0] == "stop") - { - var resultText = EntitySystem.Get().StopEvent(); - shell.SendText(player, resultText); + shell.SendText(player, $"Invalid amount of arguments.\n{Help}"); return; } - if (args[0] == "run" && args.Length == 2) + switch (args[0]) { - var eventName = args[1]; - string resultText; + case "list": + List(shell, player); + break; + // Didn't use a "toggle" so it's explicit + case "pause": + Pause(shell, player); + break; + case "resume": + Resume(shell, player); + break; + case "stop": + Stop(shell, player); + break; + case "run": + if (args.Length != 2) + { + shell.SendText(player, $"Need 2 arguments, there were {args.Length}.\n{RunHelp}"); + break; + } - if (eventName == "random") - { - resultText = EntitySystem.Get().RunRandomEvent(); - } - else - { - resultText = EntitySystem.Get().RunEvent(eventName); - } - - shell.SendText(player, resultText); - return; + Run(shell, player, args[1]); + break; + default: + shell.SendText(player, Loc.GetString($"Invalid events command.\n{Help}")); + break; } + } - shell.SendText(player, Loc.GetString("Invalid events command")); - return; + private void Run(IConsoleShell shell, IPlayerSession? player, string eventName) + { + var stationSystem = EntitySystem.Get(); + + var resultText = eventName == "random" + ? stationSystem.RunRandomEvent() + : stationSystem.RunEvent(eventName); + + shell.SendText(player, resultText); + } + + private void List(IConsoleShell shell, IPlayerSession? player) + { + var resultText = "Random\n" + EntitySystem.Get().GetEventNames(); + shell.SendText(player, resultText); + } + + private void Pause(IConsoleShell shell, IPlayerSession? player) + { + var stationEventSystem = EntitySystem.Get(); + + if (!stationEventSystem.Enabled) + { + shell.SendText(player, Loc.GetString("Station events are already paused")); + } + else + { + stationEventSystem.Enabled = false; + shell.SendText(player, Loc.GetString("Station events paused")); + } + } + + private void Resume(IConsoleShell shell, IPlayerSession? player) + { + var stationEventSystem = EntitySystem.Get(); + + if (stationEventSystem.Enabled) + { + shell.SendText(player, Loc.GetString("Station events are already running")); + } + else + { + stationEventSystem.Enabled = true; + shell.SendText(player, Loc.GetString("Station events resumed")); + } + } + + private void Stop(IConsoleShell shell, IPlayerSession? player) + { + var resultText = EntitySystem.Get().StopEvent(); + shell.SendText(player, resultText); } } } From 981fed8b27ae8043ae3be23c7b4cecc62d331dd0 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Mon, 2 Nov 2020 11:58:47 +0100 Subject: [PATCH 05/41] Fix being able to start pulls on anchored entities (#2457) * Fix being able to start pulls on anchored entities * Replace tryget with component dependency --- .../Pulling/SharedPullableComponent.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs index 5683665358..1a76e085e3 100644 --- a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs +++ b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs @@ -19,7 +19,7 @@ namespace Content.Shared.GameObjects.Components.Pulling public override string Name => "Pullable"; public override uint? NetID => ContentNetIDs.PULLABLE; - [ComponentDependency] private IPhysicsComponent? _physics = default!; + [ComponentDependency] private readonly IPhysicsComponent? _physics = default!; private IEntity? _puller; @@ -36,7 +36,7 @@ namespace Content.Shared.GameObjects.Components.Pulling _puller = value; Dirty(); - if (!Owner.TryGetComponent(out IPhysicsComponent? physics)) + if (_physics == null) { return; } @@ -45,7 +45,7 @@ namespace Content.Shared.GameObjects.Components.Pulling if (value == null) { - if (physics.TryGetController(out controller)) + if (_physics.TryGetController(out controller)) { controller.StopPull(); } @@ -53,7 +53,7 @@ namespace Content.Shared.GameObjects.Components.Pulling return; } - controller = physics.EnsureController(); + controller = _physics.EnsureController(); controller.StartPull(value); } } @@ -67,12 +67,12 @@ namespace Content.Shared.GameObjects.Components.Pulling return false; } - if (!puller.TryGetComponent(out IPhysicsComponent? physics)) + if (_physics == null) { return false; } - if (physics.Anchored) + if (_physics.Anchored) { return false; } @@ -145,12 +145,12 @@ namespace Content.Shared.GameObjects.Components.Pulling return false; } - if (!Owner.TryGetComponent(out IPhysicsComponent? physics)) + if (_physics == null) { return false; } - if (!physics.TryGetController(out PullController controller)) + if (!_physics.TryGetController(out PullController controller)) { return false; } From 9f03fc88804aebe0f6a11c24195bea20e0674bbf Mon Sep 17 00:00:00 2001 From: zionnBE Date: Mon, 2 Nov 2020 12:33:12 +0100 Subject: [PATCH 06/41] Add access restrictions to vending machines (#2471) * Add vending machine access restrictions * oops * Handle null * Flick deny upon access denied Co-authored-by: zionnBE --- .../VendingMachines/VendingMachineComponent.cs | 17 ++++++++++++++++- .../Constructible/Power/vending_machines.yml | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs b/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs index 138d88d667..ee233271d4 100644 --- a/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs +++ b/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.Utility; using Content.Shared.GameObjects.Components.VendingMachines; @@ -16,6 +17,7 @@ using Robust.Shared.Audio; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Timers; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Prototypes; @@ -146,7 +148,7 @@ namespace Content.Server.GameObjects.Components.VendingMachines switch (message) { case VendingMachineEjectMessage msg: - TryEject(msg.ID); + TryEject(msg.ID, serverMsg.Session.AttachedEntity); break; case InventorySyncRequestMessage _: UserInterface?.SendMessage(new VendingMachineInventoryMessage(Inventory)); @@ -195,6 +197,19 @@ namespace Content.Server.GameObjects.Components.VendingMachines EntitySystem.Get().PlayFromEntity(_soundVend, Owner, AudioParams.Default.WithVolume(-2f)); } + private void TryEject(string id, IEntity? sender) + { + if (Owner.TryGetComponent(out var accessReader)) + { + if (sender == null || !accessReader.IsAllowed(sender)) + { + FlickDenyAnimation(); + return; + } + } + TryEject(id); + } + private void FlickDenyAnimation() { TrySetVisualState(VendingMachineVisualState.Deny); diff --git a/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml b/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml index 590f0b0923..5f4ccee31f 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/vending_machines.yml @@ -68,6 +68,8 @@ normalUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Bar"]] - type: entity parent: VendingMachine @@ -227,6 +229,8 @@ ejectUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Kitchen"]] - type: entity parent: VendingMachine @@ -277,6 +281,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Engineering"]] - type: entity parent: VendingMachine @@ -352,6 +358,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Medical"]] - type: entity parent: VendingMachine @@ -403,6 +411,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Hydroponics"]] - type: entity parent: VendingMachine @@ -428,6 +438,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Research"]] - type: entity parent: VendingMachine @@ -479,6 +491,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Security"]] - type: entity parent: VendingMachine @@ -505,6 +519,8 @@ ejectUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Hydroponics"]] - type: entity parent: VendingMachine @@ -749,6 +765,8 @@ denyUnshaded: true broken: true - type: WiresVisualizer + - type: AccessReader + access: [["Medical"]] - type: entity parent: VendingMachine From 1e9968f2e1d3f91b6b61503a85fc8b87c89b961b Mon Sep 17 00:00:00 2001 From: moonheart08 Date: Tue, 3 Nov 2020 04:14:43 -0600 Subject: [PATCH 07/41] add machine linking button to sandbox panel. (#2484) * add machine linking button to sandbox panel. * Update Content.Client/Sandbox/SandboxManager.cs Co-authored-by: Paul Ritter Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Paul Ritter --- Content.Client/Sandbox/SandboxManager.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Content.Client/Sandbox/SandboxManager.cs b/Content.Client/Sandbox/SandboxManager.cs index bc36ba957c..5faff03d31 100644 --- a/Content.Client/Sandbox/SandboxManager.cs +++ b/Content.Client/Sandbox/SandboxManager.cs @@ -32,6 +32,7 @@ namespace Content.Client.Sandbox public Button ToggleSubfloorButton; public Button ShowMarkersButton; //Shows spawn points public Button ShowBbButton; //Shows bounding boxes + public Button MachineLinkingButton; // Enables/disables machine linking mode. public SandboxWindow() { @@ -77,6 +78,9 @@ namespace Content.Client.Sandbox ShowBbButton = new Button { Text = Loc.GetString("Show Bb"), ToggleMode = true }; vBox.AddChild(ShowBbButton); + + MachineLinkingButton = new Button { Text = Loc.GetString("Link machines"), ToggleMode = true }; + vBox.AddChild(MachineLinkingButton); } } @@ -186,6 +190,7 @@ namespace Content.Client.Sandbox _window.ToggleSubfloorButton.OnPressed += OnToggleSubfloorButtonClicked; _window.ShowMarkersButton.OnPressed += OnShowMarkersButtonClicked; _window.ShowBbButton.OnPressed += OnShowBbButtonClicked; + _window.MachineLinkingButton.OnPressed += OnMachineLinkingButtonClicked; _window.OpenCentered(); } @@ -241,6 +246,10 @@ namespace Content.Client.Sandbox { ShowBb(); } + private void OnMachineLinkingButtonClicked(BaseButton.ButtonEventArgs args) + { + LinkMachines(); + } private void OnGiveAdminAccessButtonClicked(BaseButton.ButtonEventArgs args) { @@ -318,5 +327,10 @@ namespace Content.Client.Sandbox { _console.ProcessCommand("showbb"); } + + private void LinkMachines() + { + _console.ProcessCommand("signallink"); + } } } From 3970e8b179f16ea53a8c765c9061533905d187d8 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Tue, 3 Nov 2020 11:25:31 +0100 Subject: [PATCH 08/41] Add unoccluded check for pointing arrows (#2253) * Make pointing check for occlusions * Make pointing ignore the pointer in case you are hella occluding * Merge branch 'master' of https://github.com/space-wizards/space-station-14 into unoccluded-pointing --- Content.Server/GameObjects/EntitySystems/PointingSystem.cs | 7 ++++--- Content.Server/GlobalVerbs/PointingVerb.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs index 50bfd070d2..b7d1e8e8cf 100644 --- a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Players; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Input; using Content.Shared.Interfaces; +using Content.Shared.Utility; using JetBrains.Annotations; using Robust.Server.GameObjects.Components; using Robust.Server.Interfaces.Player; @@ -75,9 +76,9 @@ namespace Content.Server.GameObjects.EntitySystems } } - public bool InRange(EntityCoordinates from, EntityCoordinates to) + public bool InRange(IEntity pointer, EntityCoordinates coordinates) { - return from.InRange(EntityManager, to, 15); + return pointer.InRangeUnOccluded(coordinates, 15, e => e == pointer); } public bool TryPoint(ICommonSession? session, EntityCoordinates coords, EntityUid uid) @@ -100,7 +101,7 @@ namespace Content.Server.GameObjects.EntitySystems return false; } - if (!InRange(coords, player.Transform.Coordinates)) + if (!InRange(player, coords)) { player.PopupMessage(Loc.GetString("You can't reach there!")); return false; diff --git a/Content.Server/GlobalVerbs/PointingVerb.cs b/Content.Server/GlobalVerbs/PointingVerb.cs index c3cdef56f4..3dd52e6941 100644 --- a/Content.Server/GlobalVerbs/PointingVerb.cs +++ b/Content.Server/GlobalVerbs/PointingVerb.cs @@ -25,7 +25,7 @@ namespace Content.Server.GlobalVerbs return; } - if (!EntitySystem.Get().InRange(user.Transform.Coordinates, target.Transform.Coordinates)) + if (!EntitySystem.Get().InRange(user, target.Transform.Coordinates)) { return; } From 246b2fe6db5eee9e57de50e93dff47a1c8fb638e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Tue, 3 Nov 2020 19:36:54 +0100 Subject: [PATCH 09/41] Update submodule. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 3c428a17a8..245c0f578d 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 3c428a17a87709b9527c930f97e327c1c0e29940 +Subproject commit 245c0f578d09f0664d85a6e356441e5fe1dfe634 From 6a72a0365dc9132bacb4034e6b913186e3b73bdd Mon Sep 17 00:00:00 2001 From: Swept Date: Tue, 3 Nov 2020 21:30:36 +0000 Subject: [PATCH 10/41] Camera doesn't move on melee attack (#2107) --- .../Components/Mobs/MeleeLungeComponent.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Content.Client/GameObjects/Components/Mobs/MeleeLungeComponent.cs b/Content.Client/GameObjects/Components/Mobs/MeleeLungeComponent.cs index 4dc93ac708..88fe6e7eb2 100644 --- a/Content.Client/GameObjects/Components/Mobs/MeleeLungeComponent.cs +++ b/Content.Client/GameObjects/Components/Mobs/MeleeLungeComponent.cs @@ -1,4 +1,4 @@ -using Robust.Client.GameObjects; +using Robust.Client.GameObjects; using Robust.Client.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.Maths; @@ -39,15 +39,6 @@ namespace Content.Client.GameObjects.Components.Mobs offset *= (ResetTime - _time) / ResetTime; } - if (Owner.TryGetComponent(out CameraRecoilComponent recoilComponent)) - { - recoilComponent.BaseOffset = offset; - } - else if (Owner.TryGetComponent(out EyeComponent eyeComponent)) - { - eyeComponent.Offset = offset; - } - if (Owner.TryGetComponent(out ISpriteComponent spriteComponent)) { // We have to account for rotation so the offset still checks out. From 1444074b24678d71f8b5bed072a8adfa8bb098fe Mon Sep 17 00:00:00 2001 From: Swept Date: Tue, 3 Nov 2020 22:14:46 +0000 Subject: [PATCH 11/41] Initial (#2450) --- Resources/Maps/saltern.yml | 8 +- .../Constructible/Doors/airlock_access.yml | 16 +- .../Constructible/Doors/airlock_base.yml | 1 - .../Constructible/Doors/airlock_types.yml | 65 ----- .../Doors/airlock_maint.rsi/closed.png | Bin 406 -> 1171 bytes .../Doors/airlock_maint.rsi/closing.png | Bin 1050 -> 1244 bytes .../Doors/airlock_maint.rsi/locked.png | Bin 415 -> 1140 bytes .../Doors/airlock_maint.rsi/opening.png | Bin 1007 -> 1220 bytes .../Doors/airlock_maint.rsi/spark.png | Bin 817 -> 926 bytes .../Doors/airlock_maint_cargo.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/closed.png | Bin 392 -> 0 bytes .../airlock_maint_cargo.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/closing.png | Bin 824 -> 0 bytes .../airlock_maint_cargo.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/locked.png | Bin 494 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_cargo.rsi/open.png | Bin 219 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/opening.png | Bin 817 -> 0 bytes .../airlock_maint_cargo.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_cargo.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_cargo.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_cargo.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/spark.png | Bin 1171 -> 0 bytes .../airlock_maint_cargo.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_cargo.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_cargo.rsi/welded.png | Bin 186 -> 0 bytes .../airlock_maint_command.rsi/bolted.png | Bin 146 -> 0 bytes .../airlock_maint_command.rsi/closed.png | Bin 408 -> 0 bytes .../closed_unlit.png | Bin 83 -> 0 bytes .../airlock_maint_command.rsi/closing.png | Bin 850 -> 0 bytes .../closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_command.rsi/deny.png | Bin 287 -> 0 bytes .../airlock_maint_command.rsi/locked.png | Bin 508 -> 0 bytes .../Doors/airlock_maint_command.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_command.rsi/open.png | Bin 219 -> 0 bytes .../airlock_maint_command.rsi/opening.png | Bin 853 -> 0 bytes .../opening_unlit.png | Bin 449 -> 0 bytes .../panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_command.rsi/panel_open.png | Bin 166 -> 0 bytes .../panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_command.rsi/spark.png | Bin 1184 -> 0 bytes .../sparks_broken.png | Bin 182 -> 0 bytes .../sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_command.rsi/sparks_open.png | Bin 183 -> 0 bytes .../airlock_maint_command.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_common.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_common.rsi/closed.png | Bin 397 -> 0 bytes .../airlock_maint_common.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../airlock_maint_common.rsi/closing.png | Bin 831 -> 0 bytes .../closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_common.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_common.rsi/locked.png | Bin 511 -> 0 bytes .../Doors/airlock_maint_common.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_common.rsi/open.png | Bin 216 -> 0 bytes .../airlock_maint_common.rsi/opening.png | Bin 824 -> 0 bytes .../opening_unlit.png | Bin 449 -> 0 bytes .../panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_common.rsi/panel_open.png | Bin 166 -> 0 bytes .../panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_common.rsi/spark.png | Bin 1196 -> 0 bytes .../sparks_broken.png | Bin 182 -> 0 bytes .../sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_common.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_common.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_engi.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_engi.rsi/closed.png | Bin 410 -> 0 bytes .../airlock_maint_engi.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_engi.rsi/closing.png | Bin 847 -> 0 bytes .../airlock_maint_engi.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_engi.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_engi.rsi/locked.png | Bin 509 -> 0 bytes .../Doors/airlock_maint_engi.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_engi.rsi/open.png | Bin 216 -> 0 bytes .../Doors/airlock_maint_engi.rsi/opening.png | Bin 841 -> 0 bytes .../airlock_maint_engi.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_engi.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_engi.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_engi.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_engi.rsi/spark.png | Bin 1184 -> 0 bytes .../airlock_maint_engi.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../airlock_maint_engi.rsi/sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_engi.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_engi.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_int.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_int.rsi/closed.png | Bin 393 -> 0 bytes .../airlock_maint_int.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_int.rsi/closing.png | Bin 892 -> 0 bytes .../airlock_maint_int.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_int.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_int.rsi/locked.png | Bin 492 -> 0 bytes .../Doors/airlock_maint_int.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_int.rsi/open.png | Bin 216 -> 0 bytes .../Doors/airlock_maint_int.rsi/opening.png | Bin 873 -> 0 bytes .../airlock_maint_int.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_int.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_int.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_int.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_int.rsi/spark.png | Bin 1184 -> 0 bytes .../airlock_maint_int.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../airlock_maint_int.rsi/sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_int.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_int.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_med.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_med.rsi/closed.png | Bin 412 -> 0 bytes .../airlock_maint_med.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_med.rsi/closing.png | Bin 850 -> 0 bytes .../airlock_maint_med.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_med.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_med.rsi/locked.png | Bin 877 -> 0 bytes .../Doors/airlock_maint_med.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_med.rsi/open.png | Bin 219 -> 0 bytes .../Doors/airlock_maint_med.rsi/opening.png | Bin 839 -> 0 bytes .../airlock_maint_med.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_med.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_med.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_med.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_med.rsi/spark.png | Bin 1916 -> 0 bytes .../airlock_maint_med.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../airlock_maint_med.rsi/sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_med.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_med.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/closed.png | Bin 404 -> 0 bytes .../airlock_maint_rnd.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/closing.png | Bin 850 -> 0 bytes .../airlock_maint_rnd.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/locked.png | Bin 504 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_rnd.rsi/open.png | Bin 221 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/opening.png | Bin 842 -> 0 bytes .../airlock_maint_rnd.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_rnd.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_rnd.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_rnd.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/spark.png | Bin 1180 -> 0 bytes .../airlock_maint_rnd.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../airlock_maint_rnd.rsi/sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_rnd.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_rnd.rsi/welded.png | Bin 186 -> 0 bytes .../Doors/airlock_maint_sec.rsi/bolted.png | Bin 146 -> 0 bytes .../Doors/airlock_maint_sec.rsi/closed.png | Bin 411 -> 0 bytes .../airlock_maint_sec.rsi/closed_unlit.png | Bin 83 -> 0 bytes .../Doors/airlock_maint_sec.rsi/closing.png | Bin 824 -> 0 bytes .../airlock_maint_sec.rsi/closing_unlit.png | Bin 552 -> 0 bytes .../Doors/airlock_maint_sec.rsi/deny.png | Bin 287 -> 0 bytes .../Doors/airlock_maint_sec.rsi/locked.png | Bin 454 -> 0 bytes .../Doors/airlock_maint_sec.rsi/meta.json | 226 ------------------ .../Doors/airlock_maint_sec.rsi/open.png | Bin 221 -> 0 bytes .../Doors/airlock_maint_sec.rsi/opening.png | Bin 835 -> 0 bytes .../airlock_maint_sec.rsi/opening_unlit.png | Bin 449 -> 0 bytes .../airlock_maint_sec.rsi/panel_closing.png | Bin 205 -> 0 bytes .../airlock_maint_sec.rsi/panel_open.png | Bin 166 -> 0 bytes .../airlock_maint_sec.rsi/panel_opening.png | Bin 204 -> 0 bytes .../Doors/airlock_maint_sec.rsi/spark.png | Bin 1011 -> 0 bytes .../airlock_maint_sec.rsi/sparks_broken.png | Bin 182 -> 0 bytes .../airlock_maint_sec.rsi/sparks_damaged.png | Bin 184 -> 0 bytes .../airlock_maint_sec.rsi/sparks_open.png | Bin 183 -> 0 bytes .../Doors/airlock_maint_sec.rsi/welded.png | Bin 186 -> 0 bytes 161 files changed, 12 insertions(+), 1886 deletions(-) delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/welded.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/bolted.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/closed.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/closed_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/closing_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/deny.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/locked.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening_unlit.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_closing.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_opening.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/spark.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/sparks_broken.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/sparks_damaged.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/sparks_open.png delete mode 100644 Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/welded.png diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index b4b93a9b6d..54d139ef00 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -1325,7 +1325,7 @@ entities: - deadThreshold: 100 type: Destructible - uid: 156 - type: AirlockMaintCargo + type: AirlockMaint components: - parent: 855 pos: -24.5,-12.5 @@ -4532,7 +4532,7 @@ entities: type: Robust.Server.GameObjects.Components.Container.Container type: ContainerContainer - uid: 407 - type: AirlockMaintCommon + type: AirlockMaint components: - parent: 855 pos: -24.5,-12.5 @@ -46793,7 +46793,7 @@ entities: rot: -1.5707963267948966 rad type: Transform - uid: 4088 - type: AirlockMaintCommon + type: AirlockMaint components: - parent: 855 pos: -8.5,-6.5 @@ -46947,7 +46947,7 @@ entities: rot: -1.5707963267948966 rad type: Transform - uid: 4110 - type: AirlockMaintCommon + type: AirlockMaint components: - parent: 855 pos: -31.5,-7.5 diff --git a/Resources/Prototypes/Entities/Constructible/Doors/airlock_access.yml b/Resources/Prototypes/Entities/Constructible/Doors/airlock_access.yml index 471b8ae38a..d477478015 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_access.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_access.yml @@ -154,7 +154,7 @@ access: [["Maintenance"]] - type: entity - parent: AirlockMaintCargo + parent: AirlockMaint id: AirlockMaintCargoLocked suffix: Cargo, Locked components: @@ -162,7 +162,7 @@ access: [["Cargo"]] - type: entity - parent: AirlockMaintCommand + parent: AirlockMaint id: AirlockMaintCommandLocked suffix: Command, Locked components: @@ -170,7 +170,7 @@ access: [["Command"]] - type: entity - parent: AirlockMaintCommon + parent: AirlockMaint id: AirlockMaintCommonLocked suffix: Common, Locked components: @@ -178,7 +178,7 @@ access: [["Maintenance"]] - type: entity - parent: AirlockMaintEngi + parent: AirlockMaint id: AirlockMaintEngiLocked suffix: Engineering, Locked components: @@ -186,7 +186,7 @@ access: [["Engineering"]] - type: entity - parent: AirlockMaintInt + parent: AirlockMaint id: AirlockMaintIntLocked suffix: Interior, Locked components: @@ -194,7 +194,7 @@ access: [["Maintenance"]] - type: entity - parent: AirlockMaintMed + parent: AirlockMaint id: AirlockMaintMedLocked suffix: Medical, Locked components: @@ -202,7 +202,7 @@ access: [["Medical"]] - type: entity - parent: AirlockMaintRnD + parent: AirlockMaint id: AirlockMaintRnDLocked suffix: RnD, Locked components: @@ -210,7 +210,7 @@ access: [["Research"]] - type: entity - parent: AirlockMaintSec + parent: AirlockMaint id: AirlockMaintSecLocked suffix: Security, Locked components: diff --git a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml index 6630242b3d..a2a5e423b2 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_base.yml @@ -74,7 +74,6 @@ - type: Sprite sprite: Constructible/Structures/Doors/airlock_glass.rsi - - type: entity parent: Airlock id: AirlockMaint diff --git a/Resources/Prototypes/Entities/Constructible/Doors/airlock_types.yml b/Resources/Prototypes/Entities/Constructible/Doors/airlock_types.yml index d82f1da00b..af5abe905c 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/airlock_types.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/airlock_types.yml @@ -118,68 +118,3 @@ components: - type: Sprite sprite: Constructible/Structures/Doors/airlock_security_glass.rsi - -# Maintenance Hatchs -- type: entity - parent: AirlockMaint - id: AirlockMaintCargo - suffix: Cargo - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_cargo.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintCommand - suffix: Command - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_command.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintCommon - suffix: Common - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_common.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintEngi - suffix: Engineering - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_engi.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintInt - suffix: Interior - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_int.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintMed - suffix: Medical - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_med.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintRnD - suffix: RnD - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_rnd.rsi - -- type: entity - parent: AirlockMaint - id: AirlockMaintSec - suffix: Security - components: - - type: Sprite - sprite: Constructible/Structures/Doors/airlock_maint_sec.rsi diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/closed.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/closed.png index a69784a26e1a707c95c170591d8b156fccab4e78..01f19f9a01a70c1aed84fc259024c214bc3239d2 100644 GIT binary patch delta 1162 zcmV;51aYM`vmhl&s}bwE_eMHCqWi5elHLQ_ix(gT%xNz_Ywtg1+@ltWK6x16~328SHN ziKY=!zYeHrTEce-v@s?Wi;`6d*Y(1W8 zoCQVryebPTW`BZ!%kAXx+!%N}MevG>%8bR4$SOqz`P9|bp(u(pa6BF-6bccEtTNEA z(mzm?;lm=axjN3-#&(1!m#Pwav`9roC92CU4WMc3%*-tucmf0cD&|%U)m0_kNFdNA z=JKsbpt{`D)SS)GfAs!ue08f{$N+ynd45>8hbK^8R)50u^mK;)i=_wrwY4K;fX_bh zV{XNckAM~2C3!V1Zo+F3cD4Cv1Ps$85NKm!;#UBX2dTkjxzQc0w`{%t0}1r@b{|ZY#K{~t z6oC2phkWfsh=1*wX_RF6(zNwV0ssXsm-5#6*O-}^ zp{c1!j6d9aWLq#dJCQaANa$u~_HZ~H?CmA47!HTs7C?JqZ}+xBw79q^8S{YTec{r3 zeKrTOQvCOJ9Dtj58id{Q@?$h@9gn9PfQkF}>;wvn%h3N#Xm(P@!s29bpI6ODEW?Zm zoqu5_l5qQZf`BXuD=I2&g-HAha$UuemzCp(Vg<;B_U2c!K69xWW;H@K?|~O7>_5C&|BY-b)AjC)a1dJ3|S`xc{kkMeZkaRX4#hE zl*{d8b9Ee_SLJ-;8S-OmoGE!BHCFdKVt?wdJ6LCvt&VtD9M}yvo<5_aqw7dc0j^zb z&iej;8v9b~@OdUbrKt2XD2=t6rZ3o9mu9!0UfQicYH z@p&N_>|u2DYXI8?#3GRn!~7Ay|ALSqSqD-HYT7!%U=K^-5DP1&_&QSN=N|%a`F~0u zLxaOWC?|>Z9bY_$IGKy*R;V8Bi9Ic&w;`7|lqin8@=UniAQCi(< c>pTAe$MF=$Bw8~$00000NkvXXt^-0~f=p{KasU7T delta 390 zcmV;10eSwD36=wp8Gi!+002a!ipBr{076hqR7DgUC>0hL9Va>@D>)}LO)M@lFfcGS zL{&F8H%UuSQB+%5XLnp&Twq{eU}9-wRv>kEfP``@g_EMTpFF&%R^`S^O+n&n0003G zNkl3`SArkGB5>sJ{QJ?xS3UO_S}A7(x%Ewtrw^jMm*?5j4!sE;m@m zY~T@XiTv%RL^#{n6jy&cx0VGM*0>4rkXY8|OL?wkVWY`GcrQT`;XI)(yaz${hFl8! zr?FoN`zJKAQ3X;1acQW5IQ>P?Iwv6vbOLjX4#F|;CWc6j8hUEQn#__TkJ)mT0d-A2%smHV7CcsE|B~NJ- kNJB)!RE5-q>4wy&Z|Gbw(k>`FX#fBK07*qoM6N<$f&~Vv9RL6T diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/closing.png index 6f047de24b5c8ea8fc62bb4e09bbb82d6904ddea..dd3f170aac09a70c808ed92e5b3cae514df43350 100644 GIT binary patch delta 1151 zcmV-_1c3XR2;2#fBn|;{Qb$4nuFf3k00018ktIxjML!KmLk`QmM8C2?esmwPr8>N? zJ|MxmH~;_uA9PYqQvm<}|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0M@gL(000C6 zNkl;He|85{`dVVjMd)Z3kfrmWB5feZF?n|YpF zO;|gBd#l2manx-`SgXge7H@#3Au z{D1-G9=l9^E0~?fZdVkJzJ%ND#C-@f#*kcY3wfF-N@G;OXTl`sqd9Ebj9dtX6 zoX1~5z<$pMoFd-i00Lo$4{#42p5Pl~(`r?J!Q%}GGY0p1(1*Jprd~S6yC(H{YT^@cKS{QSUIoY|!_BV~B0P z;g_qyASXEd8}0fLaky&+2`01!#&W$PfpIr=#e1A)fw8<_5km$U zX4j$IVBEZeo8Y7aZhMm(39wp$t0YJrN*+#5n#ro z3Feve0D`9{PJnB`IS<5X4V+LpVH+eKhNsWHvdU3NVx2}JF@%G$zSCk!a z6P25vT7XeX-a*v&nGVJJT*EBjB=2A&$aN@bgOOjrCkXN#inM@o0-{3^TO^r)?@+`R zsh&V+k%|fS>i9SU%oB8nq5@7VKqi2SF*7w+tvJ~tmF+;U>&y@cxJ)pAM@vJ1Hx)V* zmEd0^7@wlT&vhtj!?O!0AUJah9|$6zYm$lxqQcLld`A#)buVrUcc6m8&q_lTag{w~ zGC{15#4(NaF^|gx!Kix>j1sqUh(^D9N*ybQD@NQF?SN6oxO__7elDA4Cpa#f3h6qh z>}=6JXqgF6Rai>g+7eY}5%hg_0-vaqp~S6GMapib)iLUSMTuKA7brVP9fQFcnpSDl zbqfqQ#tt@WEF~Z&*a*PE8P*(pG@l~KPmmB`{P42J$07nP>wiVzE>B7G{{r$=%{_j7 Rj{ z6f_A*iP);qnE(Gz7cLL6y$=%HbGF^ihaT%(8N3ykX){fe(gf55sN$Qh)9OM%>8`8g z8>`chfVrt73D5VJ+a1B}(p$b!%=lJ8$$Z;hZYVBoYoFE)3oY_T7P^04K;VA`{s#di z6x8znfPj{Gwo5w*OjD(R68NrD-(5hfzxx&O6*~y1--T8y@B?+k1z z*;?;qp1r@fyrXTwu(E%{;_lccXT1G2A>Q!$z<7b}C*TE)Td9E`{8RqXA>;cn-n=A) zDmz1)4~`~PY~cnt>c}rc&P4&o$H$i;VTl8{d{8QYwJ;aJTIdD12$Tt+EzI8#Yas~m z5vaC>@_A6%!UBQ17B;mhQhLK3jF+wyC~((Y3;ll!H1GeJ3cY{sbVLw`9Z|D0TOk5p1X-t5M)pC4ok z(r)?*`=1BH2CIL7VtcT<3S400I&RxT+4C+R&@J%(pKd|UV`p;A2hs6t8g8_HrP32H z!d?q+ko-N8PG`WQNW%Ulcvwy$deJN=nVo;0fCnVrUZ>8l$?J}pgSaok0q3xMIi diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/locked.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/locked.png index 776327e50141a14f6159a6b245dc0788d1a1bf28..f5593718e7be1dddf63abac491f473f0b5cbe2b0 100644 GIT binary patch delta 1130 zcmV-w1eN=r1M~=x8Gi-<0047(dh`GQ00DDSM?wIu&K&6g00b^cL_t(og|(MUOdD4e zhCjk2HBe^8fNCKyHIP)5ODS~>BvOQgN*Y-z&@QNyO`>kvWz5DdsH#edC|07doi;NAoTdPH)cuhy}6eSMA3ep}>qRV7eU27UzFK5Obxm-s(5?IGz*oo6pp3bbL{{otZzLS< z6m!Ypkpr@#($v)Guz&deuY7UyRlxy%fAp-_u*D0gsekq|J3H&Jf4VZyDMA1s%3@2)YXFRm-9olGg+lE)1N6TACwrysf&=`q z`!@hzep93Xt1Mb0z=odOA2mP|_B!=MMgYT1vJ#654zT+yCBSd727 zB!Gp5MZWubET_}?clrg--Uk!6A7UDng41+eqqs(@nQHYk8mtDqEAbnnV_q~CP0B)r?y$M@{-|FfE zG;I^Vzab@U>Q1JB^2%!Te^Qn`+gM(iP96-%j*VrQNntBy6Z(9$8HGsv3-TSs(ubA9 zhks-x$cL`eFXz0b$Qm`(UcmuMOH&25rrKNZuP6b8P6vT>9kAbVt}bZ7ts7dXKiT58 z#3^9rm!*P^Zk-U^yCJ~TY~dmVa7Y_Clc49J{qt><`hgL?13uFmp)N3{QXBd0QW zx+4~cg57ZI$y2(!&mSl#qz)yy-v3V%-+v1(8G3@MhK{_!R$@^?p>}3wrd+RQSI6$I z#=Iw@b6q_w#Z3%7fnWk*ma9k*k1o9mr1ZmMiC>G@pn_q)+gh-$Epk;vamR?Q1%cXCv>a*b?Dpcf&z^ wEtGWh42aKjLr<{1Hko(9|3y_pM@HZI50lgj9xE(D8UO$Q07*qoM6N<$f*)2Kv;Y7A delta 400 zcmV;B0dM~F2%iIx8Gi!+002a!ipBr{07y_wR7DgUC>0hL9Va>@D>)}LO)M@lHbhlP zOHff%TT)XjS!Z`(VrgSmAZ%$Sb$5V-aw~_;{Y6) z>RkW;0TM|>K~y-)jgyOR!ypVrNm+>NbU>YE`~N@P#XJICB7gNDMF<}d;ev@VT6cj( z(J(tZUtk@xfk(6?^0(^}VQphmUH#>lS_WWP<0jNYVt&4Ul-IKiEHpU?>l`Ezjuq;_ zIta2g9-)zqDv%neOG6FR=@UWEISFB)6PROk5cYw$6$&y?h1j?d*kqXP zxD6cjqQdR>j(>K8F#Sh`?>pKJ_hQ_qtlq2em2p{cjQ zgfY%f!>WSpy|DM2ECP(iUjG8O8V`$nF^)6Rx+kkI>o6qGm!poC#mIn?q4DHPuU(I4 u!%cvZ@JjB|D3F$jhOP=Jh3SHn(;wJ}EgH;)7)JmA00{s|MNUMnLSTaXAFr?g diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/opening.png index be620a7d3490d8fc9a2cea980113eec8855d5624..68c73a9e9966e40976affd60e4fb1fb37f476ce2 100644 GIT binary patch delta 1127 zcmV-t1ep8p2gC`GBn|;{Qb$4nuFf3k00015ktIxjNkb0Hy+psVKz?)|v86h^uRi%w zQVak903LKwPE!E?|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0|NsC0^f($f000B-NklDBAEW>Wtq+#Z(B`~7Ih=8v zGhVd^C}o)O_C#r3aa_-rl0YQ@lOfIkJ%I6l>8TaRdOcgB%}#&|AZNGb_E>SOm&-c@m<%Hyal>(=cNheGpWp*PcjnLm_(0!uXaL^p$A~4jbfKLE6zE~lUv)dF52Dst4z1~86=iC;LjZY(PRQl0#Sf}tuPbt ztY6CM<0eo}02(S(t_u~J*qKuFDjRRpK zud(&5fhKABg6)=G@9|WjoVVuQe>YmF&o@nOA+-Pr<#d zX%=|z6!Z&J0yGHpO+kY|-xO4T1sKDW9_Zy2$SHh;fCn2uVgoM=NbcSRkXX-G1SEIw z0!XamC6)vvcTfIbV4DOackcp7ED4D383iPF?*d3Hy<~A6g;gYFD6x*0*Qq;jKzc@t zY|}odWYE9SxDz{G@_GgIVV>=5OIIMeLX@I^`vLG*An*Ti z0_TJm&*LZj*7HJqe?I{33bgb8g$g6j$M^0UxGT`!{}%)z&rRU87x>F~X-5Z(U22BE?*2huvPZDge?-Lzq+ z*3jK+egu95K3|~wQ2+N%0-YC-FCftA?EVLVN`N1MZy@juy6I=TikiQ#`u`eg{=Vw} t>jM1$HAMF;@n1tgx}kInbo>7b{s1jU%Wr+|QWO9H002ovPDHLkV1mqd8(9DV delta 913 zcmV;C18)4p3GWAxBmqc~GE9FtxXQBt0004WQchCMRPn0sHM9gk_kAs| ztdB9BL-<=f8slpN)A^5g`J3^L$hXttFlByw!}1E8J|$ql!qSsNdwzfa@OVGRH#*M` zQE#~>EYV;9P`cp+8m*gwu5c*%>u16>^Xj+&R$;+kKc|G?@VkK^KvZaFz<H@clrv|YE2AOe3CILtQ~tihb1i3$^sRhW3KFt{oD5zzO53KTq6AtaVGIDNd? z*NGA+cuW8|HX5AY?CWIv`u=xbhH>-;iAP$#hQyKvKLa%2t0eO)TENCC${?L@#4U6ca3ZdIB!LaoJ_uNE5k}}Xny;?trLmu;jTU&SfP7{WJK29C_M&OuPKydBrT`Fn z(H-3sEgr2*m$!!LzfQ_d{=y+?;+vqjMBoso6e;jS>>OJTJB2SIb@zKCa zIE)_Q(G&(k0px!O3j^b&joCeB1EBzBgv#}ihQQWmYIyZ6?gw26AE@PR@OrvI04cz+k>?G#bngT>Ht>Q0m+pU^0LMC>W4!^F?tT70RT^;V z-U)E5H_(Csm+qYa$NC=`4y+{y;Z< z@_E2tf&2xF0SId#+z;q0P{{xE6b7ErkM{%W3bf1r$Ot!{){p6$x&rO zgPUYm8eo4@xbedUo5IVmGeECEr2#gDiN~|)*SH@j3Dx;u0yDxm2i!WBHgec&EGzC* zaRjx!=4J3Qc)mgPq5k&`^p`h)m%;a6rZ0p4pqoBBRY>_>%>Qz-PItJFzpP`o7mD5xSQs;;Lzkt`eb5)0A?BI@Yc^+;{NPTDi6|t~7J0x4xA2 ze;`ADmvUvEz-7j&&D)2>+oqc2kF|X=0bf18NIb9NeEa$?@wyE-3bd869OiNb)5-nO zatCERC}3NT5p6uhI=GJq1==OYC)#K93h(2W0_{>}@(b zw!+;_EaKl^z^!v6_~k7_-0$avQm%B<^gSnkbS}oOn-G@{3b_h*Djwp&+S5rMGnYU@ zNIo&XGepK`#kkUhEzfI zM}fshjbniho~{E07B4l9G^h6(M~ZWSO^suLeSKc)xJhkms;-j)tD5RnhVN)wZ&Mt9 z_h9LQ_jNaiheJ5WjZ2^;_vcfb`=^ME=T`|dzyIP~Q=a36qlsS|GQMDla|haGP=-_H zd|qf$z4arN-SBt}782dy`SW=M+V3U7Qa}Daf&%{Uc2nDh36uS^gL^rv3jfCFWQZf$ zIGvvYQ4K|0L73UjXK)YC0c3EvcZU0E!w&A}=K^j5-D;nI1|8hZ74IUEZC1j+?TWa1_=6wi52E_M z)IU7@!GGcph8rE+;KJW)AE_t2eAf_BmrHKGGTupO{t6k00NImL_t(o!|j)ia;qQ^g-K{gkfyO3(%Nl! z|Hr($3sJlU?8x*^XRgOd#_?NOfAJjA_q|jZ$(~ikg)vGVGLp)eS}w4U)+dtxk5;wj zW2@sr66b!Wsdd)U?^>+KqGY;Znw zmefs0@Yrys0qS_vz}`mL)Bx*v)Zq3q>XsT{9iJN9Ub<1fVm`o1PB)n=klRsQf!yE3 zD*p2g_+6obZl`cA@m;nD${H_30s7i4m0jE6wOBP5^ zNojuXdj~z__Qy*kK#+fok@L%lulk8Dfe=OR2m*0Pacr>vY;f7*0K2ck2K(0rmpq4$ z2A3SC2A2kxJG!IV^s4sl> z6w!Aj%_WpMesCnvXG7lR8V8WR0ty@o`_qfY-J`iM%!lJ8THt@>{pk#3m`l3(bQqmM z1^;)msU6~i!TvqKT28Jad@+XU42Q>4z^`+M}J7bxWi!2EE8Y<>_9{k_8_ zmk%8Ke<I+! i`C!WjTR!;h`QQ&=tvqAlJ1;N*0000YXezi^E$Szxw=tP&f=zISo}j z4Ou@8UqTLXP!W`97KKzDivR!s{z*hZR5;6hlZkGGFbqTkyA5rr3tl|=|4(h43x^H0 zjEL-~nVio1`DaEL#8+&1@BB0N9S_1KLIDoUA`s*hNgv1Z3A8>?LFs@}Ybq+#1F0{j ze*wBq$$>>bi|ZucBn&_Ui>N>bAX?8{^PmE=T4;ePB6(0P=COsqC|oS)#zJ#7h_MK~ zw#ieqpdPRrA={?sVgPX84`I{uMgt~vHzh1fydjL~1e}-%%j2;G5jWi^WS~=seeB=+ z$DYnITWHO!0yut;&jW?f0=i|slKV>v!E^=cMah3kIRqMU3uNLy0Bt`;lSJX(6&NNm mz$b9`c#$8k63=0z=l=(q*ginm>l^3*0000B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MuFFuSfzD2GuKyXTi*q?9L-vP~KED7=pW^j0RBaMN9X_BXlV@Sl|x8dD=w-p4A zJUh4Z*{f%Hv+r#?{r`V@<*cKO&Ave^g9L(P*xo*fyg5(svdVo`M)_AILBHBf41C4f zf7;xxWcC?NAbklQi5pHJY; z>x+U-v9?w&8N!#a`bi zI0UCe{MRZgXV^Z>Z4`ZHc1Or${)c4;q?SLeJRx+&e}~=ykptR4bDvsk%-s-k;Gsi~ tg-nE<#$1D6|7#i>#Lwveom}%ly!gFf^_~54wZNpx;OXk;vd$@?2>_<%V_*OP diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/closing_unlit.png deleted file mode 100644 index 86ec2c739146eb2a068fe4c01ec34b686ec88c3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^2|(OlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_sw6%jfc2Rt4cLq?tF5b6g{r*& z6CMaCSlnPjcD~FkM4}{#e`A~i^(BQQiITI_BO0h^ArwF-N&yg1FM#Evvb_PTj%Y#f z0MlDtl#vfCIym|c@D#HG5&jhWA>S+191RC(ru-BV}V#js0OhJ=#7nt!x4av z!!Ckci(rIW>7tkA)sL8Hx(-jU;bYGk5FgksqTzkljctPtfYjH8==!#iZ3~=m{Y&mu zJ&1W0LtU}c21H=0Y5SL$pU+vm`kza{K^rJwsQJa2fnxTZePoD?k2+$k?&zEXG5^ay zb2Nn1IrENrTPC=HA%+KM=mGXe(Zplq1%?4bl#Cn!nkeuXKzk(+8WIgh-W(`8r2)DD kM~@fv<5k2tSj+SO2WGrX9g%s~H2?qr07*qoM6N<$f{|Lar2qf` diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/meta.json deleted file mode 100644 index c8a13cb4b2..0000000000 --- a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/meta.json +++ /dev/null @@ -1,226 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint_cargo.dmi", - "states": [ - { - "name": "closed", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "locked", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closed_unlit", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "closing_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "deny", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "bolted", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "opening_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "panel_opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "spark", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_broken", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_damaged", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 1.7 - ] - ] - }, - { - "name": "sparks_open", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "welded", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - } - ] -} diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/open.png deleted file mode 100644 index 353c4154ee131e4dbabb8b2352c82d0350ce311d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv^#Gp`S0F7eDXO3>r=qT*s;a7{ zrlz5zYh+~P?B*V9$s6y)R~R5TB}2^m)ZwW>rHmy(e!&b5&u*jvIZ2)_jv*T7lRY+X zn8(Rhe9HgaojY@mO}MpY2NzG@?kj7AHW?&)ybWnt!N7G!WEP`HMnVI_0x>o=J{87u z#=-%t5@|*YI1K{)6)Hm-k{Z+I8YeJ3nPEiy7PH$*Nu5DhvT2SY|jNMsjEAqh+r5l%G>P&f=wObk;w z4O2}GRXhz@KMh$^4PQbIUseuZgdTBF5tL{a{Px%G00001bW%=J06^y0W&i*Ji%CR5 zR9M69m*IBXAPj|_P&-{VmX>DK2Jio#0}F$|0zBw?`Xe0o)W)vyX_;;OlVa8h3061C$E5FrGP$0nfVu-HqZD}=VEs|{ zF$SJ~Wttdl*)TrPHRQ2I;&6$?b&f)#KAvdrb_>0$s*=ggu$ z3lNYN-~e{Bq=0@4tUjd+_4Sqjx-HlPEWyVQfDsEAz@&Wq02r}=1B4X-0~Qi@JAe+~2NuvsU|%8qBg0+$&y_1^C9tc|1C%BU0cvN#p#*>dl!jj|Fn}l} z5Ouyn9Ddy=W_HE#d_YG4KUI+VpY3>2=Xc|HJ}6BUasKB!-lms!V^JHtvcam{@#a=f zJ}_8SJKo&t$&J}^&9K(-=2lN`%$8_DrQ^-5o;>I=2S^*vpvQ**BOV_E40wDH(C={@ zFgREpnJR_`s~$k=@&5q)OMnO90eAqu2%vgG`53^!8LaCNn4Q7K0nIbmfQ5$+fgf;; vt)Ib0ES$3WJ~^Sp`JcCN(@Pe9%K6|gZ7&gf)yOVm00000NkvXXu0mjf$)-+~ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/spark.png deleted file mode 100644 index 4f1ad16e5fd20883002b9965ea5b6b284bbd9b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1171 zcmV;E1Z?|>P)tEMlY&kw-&}h`&>67e0lB0(L_1zfk4o-Ou4PEegY z_&*)jLN2&s31A<13u6{L3hIX#UQ-L+8d{e~DCVsCaaDa5g z&5ey_41kj+Nciw(aNQYgZ;v|HgAZFKH{&f8umzS1zKa5gK)>g2*(*@v`5t)ic;^@$ z({~{&kz7lAO!&z+1YzKhS&POO=L$zV=%X#3KSdB;qRUU0kgp&Yl&1vqy{pj`y zAL!g3&jq@)dtJa+c&;YUMHv5}oGA2<{6OUxBWpYt0JwUDf7l9_o^k>}Fr?qPSm9{w z@2ec~FB&u6NfJQmE6KG8q&)Bsf;_Io>jG?rML^U?74~f$Gi1ig0*L-io@et8Q7-2V z)_A(fcpJNr7h+VvH!+vnki1I-b|y&dMLG z{K3i}to*@$>krOu%g_Hs{=w!C&hGBcO3(jA{=wo8CeeHvg=OdeBL86egGn@fdz-&Z zO3wd9{=x7EB>!^xHhr0toBxaagFao~KR(Zvi^X#G{1}#+|BL*C<_{(>)A!}#^>wj) zpMKdbGyfO)hqQuUX#qrF_8je&ng5IYL*ft6pPyvD52HD2(fsjV^9T0%U-l0t7XOg= zgQvewh|Kp?0q2jxa`V67Xb+8$#XqE@<8ST{h{Eh43JrgN^85qH@(+$V|A*1TJi4`y z=Q;j?4!@><(5Gvra2Hy~bClyBP=1r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_cargo.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=ts(T!=$P zM@$qEq?R?lu04~CE}Z}X0TD?=K~y-)g_8kdgCGn=F>1Ra?vIV!|Efy}AhdLgD40C* zA*l0y|K1TN1_^lY{9WP;O>D`80u+ftK!CLn@=fBtfEEWT7zUvD CjF$!g diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/closed_unlit.png deleted file mode 100644 index 6e3cb09bcf701bc53ecc7886c19b82d386469aa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzDNh&2kcv5P4>B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!M%CMGsdC@d`~I8i7}Q7u1PEmK=EGBPtY zF*HeQIS>s(T!=$PM@VEBOcW7cgdU`pHNLJrug_lC00001bW%=J06^y0W&i*JtVu*c zR9M69SM74!AP~f+Zb+<#*jM^t-v2#&a3BsD1QPa-&X`dw%qq8NZ!GPKX;QxwNIuNv zV(niJUy{xRFFP0%QpFBf+WMqm!KPu-GG0BM{fC$O+0lVg%(LRSD)X z6BK*I393EnAsFh>4uWkx+C#9ZN4p5N^hn?@eZ9bDJnzvH2=X31gCOhCQwTWzB6tzJ z2>ufSc`|$ugp-FoP2&saTXe97ytvknZ>ZX;NefC!=^qB9x1M4)OCC@P?85+s~kF3(^iF8mcA z#gXj!08RvDcg+01)_2xWGaO7|K*|U1j_KdX-_xA?|4hw z0(#^yPyQbXeEnq4mw38GJZt|alQ(4n!VyF*$lr$zlq6&XMF}}UF=H`;vV==~DWOaf zl`~eh!<`a}R>m5YP_#1EsDz@Gu|_2nt&BA)q3FxO`y~|gv|P!-sv)6Tmr$_heK`lK zhJ>n>^i?AVtA>QCmGo632MOlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_DC@d`~I8iM>TQWruG)ZeU9xFKz4LKANIvpxK9UDSi zh(jDGLqmNlu2H?M*& zzOFsSmo>+fGs=xI2uWTl0003$NklWN;zmaGA&Jb(}B5=P6Oa7SKRn%Tq81 zhV94pZEH$ci{W@cunM63F5gQyf^;dOW$w9-J$FR^lmZdpKUYgU2YE*taKuBXSAZq% ycnyI2NKF!sQ-3Nj1YrTT0{{HHn%E`7{Qf`Rc{M08d3(?R0000d#}JM4$r|53 z1~D=jjEzlBg>l(k zt`$r?#*!CUBvz;g7->0dJRtb`ZUV!TclUUD-W17iH?i=r4B}&$f7R!=b(H&4pluAE Lu6{1-oD!M%CMGsdC@d`~I8i7}Q7u1PEmK=EGBPtY zF*HeQIS>s(T!=$PM@VEBOcW7cgdU`pHNLJrug_lC00001bW%=J06^y0W&i*JuSrBf zR9M69m+f}jAPk0`u&l1*l_r|IEx!NzoMd4>1$fZy>_=!?bC9D)dTS#w%=7p$!XgYn z!#rz*6c#oO0eXuvA68H`z39Nm!b^`23h7vVP5ZZ(9rxLYD;M<)7iA3!ZI6I>sJKvY6 zM*;>sAbASc0MIUh0ayv>`8%EHiQEBWMS`&`0og%?{+H!MZz@@myj zhI@m8iw7u3FqS3Q0B7*Va(jKfEdb|BBvG3L3?mfU%$Wnc-b;w z31}^PiuM5Lt4m%&0YKaJx1Vpn-oOxO0sQwM41oLx0Yn*Y5ts}O;EGR;e!pr%P-_6F z1yIV+0QOgmue@XUfN}t(3?qOgM1WcV`3z$KyT}4^0pv4G0Mv8w5CN3{(hU87vc7`3 zFP}jzfFwf$Q2wjT0F_8^C;%-0%FXXc&8-}Ov&$KB^GkP3;&APGhn)d(SK;;lV#RZI zc{g_FgIrhP`hU6N?RF*a#%fF(uWVzLuXxkPUC9MW-Q&h9*H{%R-c+l}mEMx<#fmr8 zYI3Ew+yJGDH`Qu#UE^}mpK1lCQ{zK`9*vIyIy62AXxF$7=xnTxbQN8VRSO{0_-_FI z#K9Br1Uv!%37~jF`5ZvU8La6L7@fiT0o5~DhlGa?fuC@UEuX=9BpjmtJ~*Mc{$G}G fx924MC+CCT3+VV&-lRBH00000NkvXXu0mjf+Y4kr diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_closing.png deleted file mode 100644 index d10b5345e1b8888777c37fa1d91cd92866251737..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(V)&NOtS#e}_LqcHZx&^A4;mmQu7e%+|e9AhIuQaRa v!-`7`Y&B|&v=h?Zi;Z`6N^o&$a3(Y8@yaSz3tyQHw1UCY)z4*}Q$iB}l@2$M diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_open.png deleted file mode 100644 index 6a72875dc712772afb7e4b561ef4a21d3112b868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvl>na*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/panel_opening.png deleted file mode 100644 index cc2dce59417809b2954d68ad7470d4c50db2e8e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(FVdQ&MBb@08sZfq5uE@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/spark.png deleted file mode 100644 index 7ccd97b4c63ac685044f2ca1206adef66431c299..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1184 zcmV;R1Yi4!P)KUDM>LacNZ)pGAv9rEk9c=Q(H1JGBQOFGfq}CNozG8D>W}eHB(hN5DhsL5;<37 zIa^aY9V$CpVmvreJslf9V_rXJT|qxvLR^SL94JFZM@TkLNMsjFjxtOX5ll5rPCs2z z79dhSTU0YiRT(5&J62zW9%?mCcRd%GNg0`$Hk<$eqpdxpmNlu2H><5ZuYxYGtv$Z3 zJ;s+c$CNY5jWPcK0RQqI$s6PB000AbNkl9zztj%009-9j6B(C#cVb0OfH4A$iC2 zPbEQZE?UH86OfQ4^t;l6+FWT7gfV@w?`8|?@a!b>L%?P7@7hVM$*Dk+mPi(e%K`7^ z37T*&kYJFIz2pekMb$SG>M6xgIG2xrP5G{eVXtcedaCC}3+2Z+C1Ys9- zzjh&CL3Sut3Fg;(^F7EFaDLy@xjmi>v;o=LfUj^9O`wf1{z5rX=so$K$}vXPcrE~N z^$5S%3U`*6{%6MuPb2?D<%r*6X1tRofYQyFSOhYT9~E8^SK@U6w!$JH>Z1xT zHjWuG<7ELve*>|ZM~DhJZ?ML*lZ;Pe8}dSo3iwGZT`z<$3??! zL+;QOyVflm&l_-O}FhX{x9mzVWs)M z%s*)UAdF`B%f-XPVtGINeoj#kU4~PROnEw$d^baV{U#$E=DgOtZO^f3z`uU>(00001r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_command.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=t&#%<300031Nkl{zs29Gm=*P{6xm5ft7E@P6BKON#=GVj&y8AeVtXBfUAdpGYJQ00000NkvXXu0mjfFc_Pj diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/closed_unlit.png deleted file mode 100644 index 6e3cb09bcf701bc53ecc7886c19b82d386469aa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzDNh&2kcv5P4>B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MNBl}kAC^3dc5&Q!1U?UyOpHeb~`=hTIZ6Xe)bvM<3I%Y9*76ZPQ%o0oui7ep^CX7i791dOX{8C?g`*D5a!qZo_+ctW%Pd*X%i-{$( zcBx;-ihO;RPM10{PLt;K@*Kx%`fmuQRWI>kVXFDty5NGcTH-c$*QQh*mgCh|oGx5l z%*^t;s-z_$yq{0-&C7`w@_&^z-mSQ`m|b9rZ54~-rN!+61%Et0s8k63QD-sGvXfb& z|L&V9FZ;Rj|2wyRecV{g&J;U;-`|SgU(@(y4lii9cX;AW&BlYJmcM@d{rP;dP4mu; zGQZ{uSu}07d-CzQq%HHA-y9tGx`iy5!X;1sJy+(&6gkOZ7t+z?%V zQ}Asi`#X+L?`Hh0KeEHNU-__SD%;VTgn1H~u}#10<0pSkKBBo%H<4${6XvNA`wbTV zzs|DFPOLEDN!rZ9zKgTdm|1=@JT#v$d4gby>JyfmJx4h{39b9MwM9VnRQj5fc6L>f ztvy$@7p_QM6UXVQoBY*FBTI61xYNaH&HdgQcdi#Hv!Cv2DT;PFxbOQ<869n*Q&E?u zPem~9Xku!W4$cOlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_HuIu&m*sacRd$)K^J^OJ%w^o zmx5lINg0`PQlgA#rh;Cnj5n)-UbTW=$%0<_`X0>y00A>eL_t(I%Y~DRa)TfcMbT7K zEZy`awU~q$G4YZA|Gx56usGep8D{U9dlv^#mZfhg)R6)yWEskKQb#yaND~UcHO7Ph z0ka6vAC~O}m~{XLk^r#1*+m(JfYynpuYf?YD-sb-u^#e|g$LXt5z^uA0YbFPYR$$0 zsfthy;SgdrE+UOb5bzvU5&doKV-ae#TA!v{A4Jr+orf2+WSq0=LxjNmBWU@H&Z~o$+QE8cE2u0}`-z}R4pN8w zC4b7bg^A!_2k=e-P<$581z182Sp~=3tLsGe#1hSeRWtzHMKQ#Kvynm+u*6jLumKoi zq+%1$ms?kCNU)rMwF3sP41gElpU10+U9|M`{{?15KXA`tKG*;N002ovPDHLkV1i}p B#C`w( diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/meta.json deleted file mode 100644 index fdeaa68851..0000000000 --- a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/meta.json +++ /dev/null @@ -1,226 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint_common.dmi", - "states": [ - { - "name": "closed", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "locked", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closed_unlit", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "closing_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "deny", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "bolted", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "opening_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "panel_opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "spark", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_broken", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_damaged", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 1.7 - ] - ] - }, - { - "name": "sparks_open", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "welded", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - } - ] -} diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/open.png deleted file mode 100644 index 402311c08055c5ac7d3b36870321f0f014273d4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvl>na*S0F7eA*QILprWp!s;a7{ zrlz5zYh+|(Y-;G>Z0qdio{$oqwI)y-sE)BD$S;_|;n|HeAScPw#W6(Ve6q*pO>Y>Q z-+hvmoh-iGaEV^n98R{|v8&R#B4-*dSr^c2Wi3nel_;N;u2_+u?UmRvj1=_~o>FVdQ I&MBb@06&j8<^TWy diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/opening.png deleted file mode 100644 index 6de5fb5d7dd2e6ac78edd220198f9b3122a01ede..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmV-81IPS{P)EiErAE-@=EMJq2aFEKPOGBPqVH8C?uF*P_cHB2%&5Dhv$ zH#$-`Ktnx4Mn_0w7fcipUxXfDWLt%DQkQ~WqKs&EL$VFurCfQe6urpgzP4_7>0pk_A!!5OiC?2LZ?ykP1W#5@1>G>A2$w2Q*uN zx(m3h2#qJ)qGk(nx|S?zu|Uul!J>8xlJ1T>K@f|2EI`0L-nOjz!T{|S1OT-_UoP$! zxdO(D1!LI)r-S10jk&ld6(XQ$!C1Dy>1SZ?7<0SXcY}g60Te74%NBUR3CJ?Hr>C0% zIGr~ZwON1wUVsDGmn8+XTVVBpFVy`h0W@2%2UtRg9|1iU2!KI__z}=!fdq&v0y-=> z2EYowa0_Au>dbmIT3}DI7VQ8wK0JSW`SIc_KnviNdfPUvCfy z?gOCD0Z+iiX9;X7^cjQ-1K{e~+51%of?61$mO!b(09YFh{$Kn-0p$cr6>b2LumRK( z$XB=pV2CUrmq5P49l#G4eu;oe0{aT-m#nW4uFF?YOJG-F04Vw>BS7seIFx`E0OjF# zbi=KjK+@$3arkvtOyWx8d54Ywd8#1uzu57TF29Y_{vbD1r1@X&c&na!8;_;IYcp8o zJKj|5$p;3jV#k|mJ-ISl`V31QZ>sg=%4~@i6gu8i>&cxSO90+*Iz2uF=<)a%pu^*X zfOe1TfX>0{$W+laShWDS$A1IxCjlOS2jBttPXNUo%I5$&_Fzq$z|9`4A5h(cby#?4 z6Zi?+*zz6>)N8Ya!)Cr`JCrp4%NDMB&cc7PKllyy%nK-PP2pPr0000j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/spark.png deleted file mode 100644 index 27e7c64a473e5988add781e408fcbc2b21434ab0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1196 zcmV;d1XKHoP)-kPwSr#Bf?ods0RQqIjsoxi000AbNklMl+nW2eu6W1dyEo(2tETvjn9$7l=57Vjz$c6z5!kUyEiz zCL$*&&V>NwK;l}0!dxtoO!%oRL1C^ek-CcUB`Cs|n;e^hwuuEf6_^=H#50(Q1Z6lE z2*c6x9I-EQg5uo5zjRy+xe$sWfPLXhP?A%DnfWf5i3DXh7f?zJl_iMt$@pQC#>0dq zBIigNqA!8qlkwx@c#_Q3crGxCHa`?4hH?Ulw;Hb3bQ_H%uEh%h`9=oY+vK^TB#1c9 z-*g=B@X$4LJ)R0cTjhhnHhJDckwD@!f2ZR#n{6YH#Z!SbsJtl#wHkiH+i*=Jkod}2hAo?GOBR)fv%J~9oe7VVZ8>^5P603l3Vk$Ssa{*iaDY5~!oS-_}yM`znI?LO&9k;zWzVUKSUKAUmWuam_Tv`|K=ZrKk(7-pSZs# zC9ow5etpsWfw}*e{ll)oKL~%|U;ep7b;uRSCU^7o|AM14)JF#Y5VejcS0}W;rwYTj zUf0+C0ZQ`^Ajv;ivHl+`yal}%-`Jj~_y^kj#{GldT{DH(?%dR#qZI#u68wY7ANbuD zKgob3`Ulbe>;6HpP@q8nuTLP^9}owS(*Gln>K{;&zgYQ$O#T;F9+fkC@)z6y0000< KMNUMnLSTZ=z7&N3 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_broken.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_broken.png deleted file mode 100644 index 400d23ef7ae3163984d2e67206aa7d127589da22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^2|(1r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_common.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=tmiE-gZOH})q(;un^!7VfH_z>uC%=8Hx2p&g+m_dq*k+BP{z1HkwF7&m#}IDr-2ro?4Q8{)B6 zz@dq_+-^$*-1B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MIS>s)Mn_0w7fcipUxXfZQWS_@7l?8fj$;~*cN&jl z7?x-omV6tWYa5(@8>Vs`tD-W!v^UR=BQCz@3jhEB0d!JMQvg8b*k%9#0<1|yK~z}7 z?N{w`+aM4`B(j>ezBX>?3Euxfdwd8E8H6P4ADuCynb<73J?)L9T``XGLn82HE*C?8 zkbrS?IOtjH8FALAkS_NXIIcZJC+6jV$Hn;mA*TV^GMBfvi$NSFcY<&O?!WR&gGsn8 zNSj*w`sf;PxFvvT$ZxMo&dAgV1cdsLpfV#SVR1%Pg192V`5EmY z=$g?9f@3o}LvUzDrwESBNYF2RyTD;QpV1Qt@)L%2{t9LIF-XcKfZo`VPLQu@ulA> zfhV}pOJ4oGslWjG7{QhVp1@ajo)H%dnFwS}0_h9Lngj`72qJ@CaN$n87gw_99k?d| z#p&nZj+y^o9CPZEj8($X6c(m@VDC6mc$ciA1PoW)eX4|GW?PmuV9W=GSwA9B-Xkaf zPXw;M%G@o-fsxx|);T6`8UuvA$awoO6aqwOpd=w9C`!l)iW!R$lqFo_YY8DqRL)pg zhbJWzt&G(xp=f2SUI|4jWA#cXS{bWXLa{FgpO;Yhr{zWtmJJEzwuFK`@5?z@HYAj- zq%RveST-b-t)wp-Ik;0o(aKo85{g#F>XlHmGFGpIqBo|tBow_dwI$&x<7Fk}#%tx9 zf`m9d%y_MRla+{D$EG!G8?SBaxWgLO3+%CuJ36cv*kc`cbXYHt zfqR189o`jKUU7OlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_z6}tD-WlRu!>h7_(s)wT&ybTo%1k6uq=J z#hfq3nJ&qaEYFT3pPEg}0003%NklbhzWYBq`g|A*zN zV99g`XK?TFUT`2Qiu^0bIZ>#DqR5J!(leH*%n%x2Gh+Yk7KA|C2wEe66OqkQ?G+&6w#~`-t5@r}rWm!L_sgxR;NgIAUfz_z}IFMk#<|00Mn%n(5kO z03eI?VQ9u{ui75i<8n$ab=wV9HFRw)_A8K~Dvp!C621j&HDKG;3aka#Al6Oo4j(7-q1z6&a zuK{zoO{Erzj-x*g41=-&TY-NruO@cMGS~kXoXtv{w4P3^00000NkvXXu0mjf@4?B~ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/meta.json deleted file mode 100644 index fa227896f1..0000000000 --- a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/meta.json +++ /dev/null @@ -1,226 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint_engi.dmi", - "states": [ - { - "name": "closed", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "locked", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closed_unlit", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "closing_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "deny", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "bolted", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "opening_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "panel_opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "spark", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_broken", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_damaged", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 1.7 - ] - ] - }, - { - "name": "sparks_open", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "welded", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - } - ] -} diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/open.png deleted file mode 100644 index 316fbd463e31cc73df40657516a2caec9eab218a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvl>na*S0F7eA*Q0Pp{lB?rlzK$ zqibYjWU9mK?B?DPC%&vm=6s*>>bb{00@X2=1o;IsI6S+N2IM4px;TbtoKNPsdSMnP z+vdw<=VGpioD#ScvV)6fn`HWWq3Z#u94~cRRxog#5t+{@l9ABBut1EBjZcN~++E=S zR*5vD1)K%}{t6i(4M~m5UfoS#c=GNZU(cHWUQuz2f-Ejp2EBQXhc>WZPX^k?;OXk; Jvd$@?2>_#@KzjfH diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening.png deleted file mode 100644 index 76be708a39a3163261d3f0d5f8a99fff3bfcc9b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 841 zcmV-P1GfB$P)IS>s)Mn_0w7fcipUxXfZQWS_@7l?8fj$;~*cN&jl z7?x-omV6tWYa5(@8>Vs`tD-W!v^UR=BQCz@3jhEB0d!JMQvg8b*k%9#0;WksK~z}7 z?U(I#+aL^v9oJ6QZDDIxCd2(-=n%quS%3@O&VIzlJ%{>r^hj@FOHAuJzs{hU1B|e) zRu@u&1Uv!ULP`R% ztZ4pKDWKZ|(lH>y6~#9kwWStyTM+BYp1To@MLiZoI(|;kw|KCq--4iTc$uQ8%%Tws z2(ZOp9-S%y^jqKn@$W<4@0i67m>U+%bqi1jk;d2hj!!ChK-Ge|ZUO2yNZv8}dNuC` z0k;THv0$!SU;!714t;%jxoUvREwiZ40s^E3Ai%sVV?e(JMxWAybi0fI-4+}HhT!6R zz=#D5U=l9A2aH(20sP?s0~VYEPz66y3w#CQmh@_}z$}Uu9RMai{QUCv_03j57T~q) zSF|U9AJt_G834Yne|>xZ{tk|S7a)EP(gZMml0a6W&A?UY01s?uzaP>Ogh~Ld1ZovJ zz~1g%PqSwXs3%aXFavl(252Qvt}q8sh$5hrK)J#Lzz!GoU;&K;jupmVvV4HMuUtVZ zfkTB3AmT@v0ODZ5sRSegs1Lt04!3*)LFX%^;TP{%*dvVR13CftsUn*H*^U=<{%sug z2c@YZ%>R7H+x61hc+Ll}%3xLQcuT7%pBSvF9dBv%1iGpu#IrPY%gvn5$j>3B=4 zCl7ke0n&yu=wB;f3#V+pPj)C_{^u>+^^%4EWPk7nd0Pb= TMR+o700000NkvXXu0mjfTjpLC diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/spark.png deleted file mode 100644 index b9b7c7df007de7a265c8688ddcb847025135a77e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1184 zcmV;R1Yi4!P)6Pi2@n|dIe005j`7o2MwoPQghOcI}?GooV}qp~=r zavY~b5U5=jsf;(OTNbKl8>+H6tD-WlRu!(YH?V6Pv11ssVHdTHE4Ew~y;Bsuv^T|^ zFUFZJ$&xJ3jwAm70RQqIPIy)9000AbNklDk`i-W%>XAXL*H$gqI6Gu83YWcXFPb1C;YPt=8I?H5gkCNIylv}pb-}W35QTl1Zsf#TnLDjDA&a>;8z!ucr6mh#vzTsWCB?Bn@ z_~@|T>2^E)!z16ujrCl>fyxoL*Vo%IgiabD;l4LI?{qgeyPfmVhaHof>n$1Z36>1L z$polC|Ipj9XP~ba*T99R+o$-H?SQ99$I=>8e)bi!6nKe7N5>k++xVkxy|{}Y9OLn) zF%&cCfOeM|6wmvJsXIKPeeoW!X z#tFmbdQ||kzd#=54sjtD1gLzoJ|1a|oHh(aW-u_hX|I7S?#UIS0-a4E0acj2N1@>laFKri zdH%sM`~NU{Uq-L?_PoG9u;$nF583XTE4+o)_8b@Z2b|*{to|T;%{3so{z10?S^uC} yC{UyS&u$>!A5aHS(Enpl=pS&NzgYQ$QvMGb`;(!h$>gR000001r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_engi.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=tKdx5s%k)B z!lR+1tE;cAXQ-{OuWx9gX9NVU0>-9>CZYPK7Dko=yjFJRHpylV&bH2O?mi-d2`SMk zT(vSl1OI!vIEGl9Zk^0s)NH`x!t2@C!ljh^>bLyXY4s_goSYy7M>2%(#W8XRM zbG95Z+4)lLRiD*ErG*TYN@)f`M#tL^ePg_072uH9uqQk;WCd%|T;IPeCR69gc5mx0 zo-8lKHlfcoK!CX;$2~7Iupv;l#F^_*W}wcoeXNHy=IA^*c)GAc!*WZ zko&UZ`~1Jv?rJ5>XVdLU=lnQ1Q^ArsHQ-WoQdy%{3{&S1?vBHrJ{`l)ZQ+}0oft21OePB>9c)I$ztaD0e0ssb@j*b8T diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/closed_unlit.png deleted file mode 100644 index 6e3cb09bcf701bc53ecc7886c19b82d386469aa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzDNh&2kcv5P4>B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MEiErAE-@=EMJq2aFEKPOGBPqVH8C?uF*H>#H8?UgOfoqT z4LUwII#M@0V>UoTJwrxENMsjG6cJy99$;i!@#uu-00001bW%=J06^y0W&i*J)=5M` zR9M69m+NxeAPj}ENxV&V)orSpwB`NZvw#2#EPT!W=*%*n#PRXy!$%YQNDYJj)CTyn zx0`jpj1z_-=rG>LaNN_0JAmtSk$#X)vQoqAr|vt$mc6~a+^jKOA8v8Fg}X5r4l~9R z9KlYyub9Xf`9Tf<=)3X(JOH5UfeL^FASMJFyj+a?+g*4Wo~Ue}>M``~;5z|}Y3e!l$<9~@7xVBYg5bFT%J2VQse%#S}G ze@!I#zo(D>UJEJ@2yk^@dHjWu0OL-8f%jm+o8SQfV(FBP{J{XaWr3ywI$7{hc`)e_ zkO^aw9l+o5Dy}J>AJS8N5BVO8U>xHy%m0WezGoeoZmh6qzEG6!S>;@U=l@uf^KsHm z5iQf|0zpx>MBx#p{OOlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_sw6cRcSt}=5R4rUNGhZ?+U{EVyWLsl4F=Zkj zX(l6bF)VjI7nw;Jsf;%)3h2xL00AsXL_t(I%Y~DTa)K}rgb@oi&|W-S6$}IkD7^m@ zHouTyoZf_)%vLLk?j>&bVLV2 z0NCE*qKra7>)`1dAW-azM1)gphkUW{02+yq4%7oEE!I_-jRR5@p&Ha7U^XryjYj}_ z4x0#isiP5U6=DVms@ha zHsd@^^VnS3ZUqvw#khFP)AKpa5Al7BI2Z#3j150}GZ4(b@{e3wm|F~nW)8smT^T1MXihN$s9pf9(s*pO&B`r<&)D+7=f i_~-E|VjnI2{Qm%#4Lra>ccDZ80000na*S0F7eA*QILprWp!s;a7{ zrlz5zYh+|(Y-;G>Z0qdio{$oqwI)y-sE)BD$S;_|;n|HeAScPw#W6(Ve6q*pO>Y>Q z-+hvmoh-iGaEV^n98R{|v8&R#B4-*dSr^c2Wi3nel_;N;u2_+u?UmRvj1=_~o>FVdQ I&MBb@06&j8<^TWy diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening.png deleted file mode 100644 index 4393aace1aa4ddae5f75590f4571f326f02f1d64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 873 zcmV-v1D5=WP)EiErAE-@=EMJq2aFEKPOGBPqVH8C?uF*H>#H8?UgOfoqT z4LUwII#M@0V>UoTJwrxENMsjG6cJy99$;i!@#uu-00001bW%=J06^y0W&i*J!%0Lz zR9M69m)n-xAPhzAFm^hV&~!?n7ykc03lWENqLM1vZK`X8}iH=CX#5E()aS3wV9}k2;5}lC%0FQK=j&V%@$0Y~=EP=XS{Vy^C z#6SYkm%zu3r2AWY^-rovfUX3hFM*F=40*@c``x`8q`4qKM*`88U<1qsEqi}^yIW)C zOCixQ2>?I~@BsI+#DL=xxcEdD#J5ufI4nU8aD=db0-TY60ZcONp8#hh-~eeQzzGTV z0ic4fRDx82ypUcE61bD5L>0j8Z@zqg|Mk9A01}uF^c~Oy{H?YvAp`KQ>u6kS78B2gaR;1 zpj}}JfGwJURs!t`E5K$hw#5Pl3DgzhFInA8xUOBnD1oZN0Fd}m27s(2*p+}{0Dbc- zyt(BQ$Z@_xFu(qagwoGCwNSy0<8Nk1d^L!9pMPVwUy%(*H7w3c4+gOyw zt8Fbi9d8-+WNfS&*0S62mQhbe-m+yayB%*C^pbZCU z%v#HV#=8Jij{tN+sRxuN0PuuT4=CpWaYAVfDCYrjLTL>sy&-QW049{yfbxVfR+;R->jA~c zkKPzN1SEf73@9SU`5`aP2Q3K)^8vE&C+35{bkhs@{^FNs00000NkvXXu0mjfS$<`t diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/spark.png deleted file mode 100644 index 49d5e08d338d59cef68a63b0ace370807db7d28b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1184 zcmV;R1Yi4!P)#H8?UgOfok{F*rstIS>sw6cRaMF*-gsI!iM;Qa3tPFg#;6Jslf8R5U(LH$Pc4 zKtnx1QaC_uH$iYWLNzf$TR1~TM?+FQL{>dSb~i^}JxF6cNMsjDJ~vB_GE5W^Off4> zCnrrVDo#o$Q7tJ^H8E2)FH<-&RaP%oG%i>=HCR43St}=5R4rUNGhZ?+UxXfDP%B_$ zTVpmcWg;JGCL?k&EO$K@nMoO(0060sH~#35QS&1ag4toD1-4 z$tuV~F64qIh5+`3m!Kx60-pUY@I-(*oC_!^dP)f_eCH^iXOxJX zZE1*Jf`soJAMfPxwo#(kZ6}-Wi4;9KfXur=|1|KkxjJ76$Tu=rTO-dEB|yr%!Rg*! z|FE0IwfR&4x+;(3HS)ZLB7n?E{J~)F^ssB^`g|&|0F^gI+-l(`ybBjZ0Euty9`pvI z(V%y*>)W_7p9wfnI^x#SQY(hgNdqL@5BleW(dz1GaNd8nVsdl7B?C6VlEEjD01@aN z1S|Fo)cJf5T)4iyj@Ic4Sc>q2Tw}sFz9X6fD^dURmcr3CdT*Q0?;;30sPnM{`3Q1B zxl1s=+#GE}u7KkQzRvCQxj>V=jzAOe5w52RG!e#MDJKfOv%pt5#>hIK3jmxw!hdXp zM^8BbAQ;kjE><|}2S+ML{6%BVcai{5dL?-lft35fv7g74`MLlbVG$7dQH3KL#|)YC zWdTJ0196xuM7f+7SmWs?<85q0o`{hF-^5&QpU(wc`KQPRxN?B%+@Z~JUUOTMJ9Nad z^+?{K56(<8|r&zsNsW{J}69KSg2L{=djS znEqfGJ-xh)?}sJ(|04fj_yZDuHhX!xAC~L?i~NJ$U0>ZiOlH&RZ1Qjumg@hD{DbBX z!f51r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_int.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=tPA4|Dq!xSXW^n}DZuOO=I$dR7?kD`mk^gpG6LZm3%? zqV6__<6x`xb6KA=nu-iA3@%PueJj`tb}+inThU~}AZESFW1-*$o3fw61}SIMgOZtxjG@(#`=JY z#6`JhLT{{Cr;1f|a=iQ`YS8cSe`;Z5N~~2w!kObcPE=iHtdJ`6x>J5n(P1AWpLO@| zx7*xZp2vr190+K9^78cl%DaKCP4{-orR;pjZr9K=fq^&K&TQlHG?pjE0Y=hOv%}^y zv40fOI1QsH$jvjlzz=6^pcTX*>T*8h*6Qeo6G$-#mZ7~Bk=u6{1-oD!M< D0;83k diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closed_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closed_unlit.png deleted file mode 100644 index 6e3cb09bcf701bc53ecc7886c19b82d386469aa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzDNh&2kcv5P4>B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!M%CMGW+Co3f=EG;ZHB`+^8FFGeMJ03DJGBrUXH$*NtL@qfH z4LM39Lq>_5c5~z#%wf5R$MTI^!FSrLfE{EE8!@^u7F+2)y+5 zs?7}z(Dx39X`Jk(a2!We?s)``yAgv<<~Gss^xr*s2W0N~UC5r7d;DlnrupV9nnhCTilJmhyk)6B3J z5NVM`?$HwY9B zb3?CS2f|0c(E<{<45ofw2Co3qK7ln0NPw6Jr2FKqC?HD~NFtCW3nD%X1chnFg`4r7 ztr*W6a1sEPo5IEOzX?_}i~&~+N1Z8*{ej(aU=9>K|9eiZuOf~~Y?c`m)jo%Zi1v*6GViAKYl6sP$N_7K&Pr)oP)r^;oSIiq{6_xS*d_-a%=FWdgzhSrHDbKPas*=KnmwjIW2^ cC-(>c00o!h!?UWMl>h($07*qoM6N<$f}$&L%>V!Z diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/closing_unlit.png deleted file mode 100644 index 86ec2c739146eb2a068fe4c01ec34b686ec88c3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^2|(OlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_EG;Q3B`Pc=Dl8={CLAj)BrGf>EH))ACmby; zBrY~3FD)c5HzY4QComxsFgGMHIwvtVBr!TCGA<)BHzYDUCNf13Gdm_UE+aKNCN?`J zH$*NtFd{faE;$elIYccvL@qi-Ejv9WJ4G!#F(EufEj>joJ~1IbMJzx?EI~#rLp~!z zMk_-`M?^*|ML#1)M=D4(A4xzWN;Dr!M=4Ac5ll57Oh6$_NGVS@C{RHmP)I0JW<*m$ zAX7;wQ)Wa|WCUN;tAU|wHfU0+~cVmljTU|MBhT4+Wb zYDOGxVO4KVA#ZVRaB*#Lac**PY;pqcW`KUK^J*&XL@jDesE%e zaA1UofrN*GhHqSmZ(Es38L5mnSMlQ*0005lNklX#n zW{EFHLe*4c6{2AW&@`1g{l7*ZDrB!V;5Q_UfTkgKr{LXLrE+dd_+1iK1vIk~n-Bt@ zF2ItY2R=o%wx&W0)j0mxWNHVe_$+@-Hp`$Jrz=p?* zvm)754o*)?(k_`k?zRDBEfk(grZdX*qpm+*OPRT3pAGnsxkb8yW6N9FnqIH#wd@w@ z4K@G{G8>&)+LW&J`pZjQzmkUg2bwAjOs{U2O`yEJ=KwU1eDl7}wv`l-OQu9=e>oL& zrl6l@2TTTH$#hP+t?7F0R>{qs^f^FB$gqxZTqFghR4)H01^1YF5Mmo8Bt#M$Bqx6> z@(0=QER+S{g=j)dlf8HHCMG;fZ3B2A5>KYYYU(K->nSz^2xB1}iH?s)BjLe75i~VP zA&l{$a3@qSc5N7X^pML!NTU~UfPW6JLA19tcKm+r=qT*s;a7{ zrlzi~s-dH+Z>4TzWMuB5=j`Sll;%?U(MKDol(8hpFPOpM*^M+HC&|;rF+}5hvc~pp zUd+vNW*)yJmamttad*uPMmF`>XC)kwvyG?Z1-GnV;9A0&%FJqJ;J^^T&CF~*iQ)E4 zmJr4^6E+h@wpW}Y{agV$8zP_cNHFY7=VMgfedm^m2w#)=bY=#tN8Y#IZq$nd+Q#7N L>gTe~DWM4fohdrF diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/opening.png deleted file mode 100644 index c0bb042b00fe6a671346d49dd72dd2e2540b362a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 839 zcmV-N1GxN&P)%CMGW+Co3f=EG;ZHB`+^8FFGeMJ03DJGBrUXH$*NtL@qfH z4LM39Lq<`q3WmfSoEHN%fP`Y3?X81g3;;7RUP}cw^7z-Ze-25?h z83U*jjL%7mq3)Dz+c?n&cSCGJ7$9YV(|>t=lN;DT>aqu?9XbNiT}9CUCs#bLr)OioKge|z zzW-0Jc)OmPji;#b$~RW|6>qMs$tN1C;)*xd*5pcWX)-LWcynz{uJo2@L1D$4Yin|+ z$0-0^a5_Cc1?chk9H7JFlYn-Q>wwP2>P%PB)mXIvsK}L zI`&{qo4~^!tRGO_gLPPVY7_Vc+t~6RtjEIP(BG3Citqo^7Vdh^!hfj>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/spark.png deleted file mode 100644 index 36ecca434a1f783c5d52b42f5969a0452a638a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1916 zcmV-?2ZQ*DP)FC-^0 zBquQ>Co&``D9Dl8-_EF~)@94jm& zD|Z(xEF>&8B`h~3EI1`CCmby;BrY~3FD)c5FE1}QBriHAFFPkMJSQ(bCNDoGFGVFV zArmk+BrrNBFgqSFLMt#yBrr-OFis;dP$Mu_Auw1WFj*lnHzYASCo(G~GA<)BGBPqZ zBr-cDGDQ$GJ0>(PBQ-lFH9;dbJ0>?ZB{xJaH$^TtM=dujoJ|rJLF(E%iEI>spK|w7+Ml3@rBtt$ULq;n@Mn^G#^VxDNBwrOcW7JH6KhsAxuaqPJTI0Hz-g+Ay7ytQE5X`W<*kFLsDl% zQfNa{LLgH~C{t!cRAxg}W=^ZggvIbZl=< zA#ZVRZ*pyLacyvMZgO#Kba88SJri|tX?AdEcRd$(aAfLdBv&WwvW*T0#m7Q47_U)`%8Mc*WF+f+kuanyQFYe6UhQX$6bc zIRBQjyR*s6X7c!w&)+iLreEgVJ7@2m+3h);%Qg4Sxgg3I00Aynxj5%qh;WW)49WK0Wbqaa)HuuOn~RoccI+~xj^Z-Nuc8*fm;?R z88=%*BKV?OP%=)ni0)!`3rfK=n`}%c5($yfg3@uF;7+E*gqi^OM$j}~pd1_%sA>XT zh+jp25~BWX0;%VH>+1ZyE<{faW)4|#yRz5yOXd3d*^8iO^6Vxd}-%hqC+apyZ9 zq5li{2g)Bj8R+c~hDKuXNNn_tKOX(KrU?CS^$#A4f1vz<^2&?B(CPSx7cY)QPKS1U z@=y`_zmR{R{DJbq!0<@?@{LsL#^uP!{(+T6=>J0gfl}8s_0JwUc4|5`JDZw5bu9F7 zeG&S_J>?JB`k(X<8yWt=^an?V{vCqO-htuK__gU& zYWiAybpNL-i_rfj4o|`)WcY`)blmm!F2UB=7YvlvLve}K9CMa3T!#Qy^ylYYZ|-Zmfr0000>n}! diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_broken.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_broken.png deleted file mode 100644 index 400d23ef7ae3163984d2e67206aa7d127589da22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^2|(1r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_med.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=t3Q=qyY8)d6Kz2w}=x9QHUK7V~~XD%dp1^tZJc!7!A;2c(qtN3&l`p(J3?w z(~;}kLJ~nE_j`*(ZSmJ$#1Y_r7xrEEr2{}?Kc!vw8x2@6oRqX}azY5p1vqq(w%ct> zfLq=uWMEK`K8~;B<1mG6p|x%m!1;52o+yMCFf8+-$B7?Y2#U`@{Y3d1EvG;u-U6BU y3$Vj&F`Fa`_o_hsr_2Cdz&}5)68CA?@Ba($={k~{BzejJ0000B?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MDA`TUdrb{@b#kWoG}k?xPIgybF8Ly!nGmVd_qx)Q zeePL>>N>Z++mcGP9)CAZ=WBoZ)%T3>#)W?R`s%JGXTS0FYMa<^VQ&@QxyWmW=8B)Z zjX!s=M%)p2VDnVkfTiPd&pL)ICe7s3Nz=JsX4}5~C~BLMaYpRT(s|!lCh)6IwEfD; z@%fim?2;)}Rzek>Z|uU>Cr))R{_$(!ftYuKw-YzIuX1DPm>?Wdbwowy+X^p%PNjn% z<=zVYkmLFKg2C~XV9A#k9FA{5l)yo@`)>tb)c>k$)PG#rFXu4f`wKyq$bLDe10U57 zPJZC|!Iz^Ttj5A){++j(QgIgbe;(hu=C41;THwX6FW-;&IWmc?W%tO#iolrSHM2_)nicYuPfdi&wre`G6pc`;&d))hbMZlO1+2EmCtl zwDajEp6mk$?|qDtIXRF2K_A27{7YP zWS(AdD#u$w_-M_7Nnfqm%k#NZ-oJcxTC1<;&YiS5$)A>KIv8}GVCUH1FsY?yfrg^G zMw*UWz_fzyeAOc=ftJas+BO=BTa2!)Xt{7IVzH2uc5<&5$J!oKEyXWSA3PRns*Za1 zB;n$OfH&S8Zz|)@9bBZiFhjNW;t2$!8Cet9Bm=47XrV(HKDnM1Cn_X4cYeI}Lrq`t zY`Jk<^!*f-N7puH^4>m{ec!4q;&4@?-0K?~55Xy!^J|rrU&KDlZRCBIw?p+s+(X|+ z-Mq7{vaU_vxVE#-VEW|sZ`&`vEbTSo1s0$7Z#q2jY4a_v$^Z4mIezT>SzBQDgFpKT Wn?l0%-66nq%;4$j=d#Wzp$PyHm4Idd diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closing_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/closing_unlit.png deleted file mode 100644 index 86ec2c739146eb2a068fe4c01ec34b686ec88c3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^2|(OlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_pGS}8%haaD0!6s|HC;i zNVZh790}~hy$(vUqR2mUSQ7!*D2l8&Vn3sa$PA$Yx>Cv*FtEv(Srp4Vu=N2v$Rfbi zHWe)t1E!Be$x4sJ7XHf;5%-+1z(l}5{~pqo(-tIQfeIu52q`ha=;Jc49>}$YE)Ze> zy$tRx^1wo4;HL-_HVdOeN?s)`Frn1J>-sykSn0NTj9IEhazA18KWj+iczLj?HaYKe=I6{G=2)SSEmEK$L0z#MK9 usUg8}na*S0F7eA*QILprWp!s;a7{ zrlz5zYh+~P?B-rqS2JhMtnJ&kM!Gy`2C8E$3GxeOaCmkj4aiCNba4#PIG^mXdBZGD zw#}!@&&AxCb8Nz`H9NR?w(SmCFSN-Z+2d_U%L)drGa|DXMKTf^7#4`JvGJ)ep1Uh7 zAu%D;;7p2xaKZt#1CG-iKCNIl%5?VD?t=^`?(XH3xS1)oY+-@GojGg_wZ0x!DRn&u QfmSkjy85}Sb4q9e0H6y<9{>OV diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening.png deleted file mode 100644 index c0389325ac383bf27571458c697384a843a678a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 842 zcmV-Q1GW5#P)Eiy7PIS>s)Mn_02Nl0WDOcW7TH&|bU9(Hzgetvv@l6-}Q zgN2!ch=_)bjf;(;i;|L$lBSQGoSL_{wQ1+$=l}o!0d!JMQvg8b*k%9#0;fqtK~z}7 z?U(I#+aL^vow#;3Z(it{m5KYm(1~wh1h~-c>_<4xDfR21!wOzS#-ok1}JP*_)^ z3n@W@J^7T~04Q3k;H@bk;tw>MLPwLqUc+(kYC{Z&=A zkOAn|^{?;mKi$ zvIU6Df>Q}d22gK)XWiWL2}GT*&^EvNiiI7qJs;35fbS|u|Ie;?QRm;raeq+iDq{c7 zuXtWBy^ZIr@hUe~rK?yPE8bFGlPRFv zV-65N9x&o@4G?~VUXRZMIz9dXpwHuTfWgMkN*bXBLSX(C*TSAPXN^& z%I5$E_F!F`z{4JF9MIf@4On<;6Zi?+*!mu9#KP&&-zPhi*#Gkudc9=fKiMDr0pI`z UAaDi1DgXcg07*qoM6N<$f(XEAOaK4? diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/spark.png deleted file mode 100644 index 5fe7ae165de93ac9593b3f47a6b97a0a2336e1d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1180 zcmV;N1Y`S&P)sw6cRlh8$(7%NGwT6WEV<4 zM@x<}OcW7TH&|9kR8~w=S5{D8CO=<<9&0a5ZH8lSE=qHZXmpBebu34Ac64_=7k7qm zc!Y9(etdqCe1n;Jg@uEKnS+Oxe~5^Nh@pLom4k|)fsKuejiHN>e)l74)W zl8=&}jFP60mS$v`Ng0`igPK-VoB#lvoSL9qTA+V?p^b~8e0ipJbf%JzsE3BBj5n%; zgRXvkwsLT{x3&KO0RQqIZY{EU000AXNkl09vi4+-a=?cRb7H z@Q8+-3V5;SA%qd;J3{R6;51Lrhzo&)V=M!anxH-x0^(dU3px=sL47U-7>9@s>c|i+ zL2WLVNGf+AM10nkpf=Z*2zCgNpUowx!_$k*Pv$JGAWCHOfWPVzSa`5k%yX6q zcHE&G=f)BwJlNm=TEw;SLLj+$(|3uhCQ$j%A6@xDKG(-f0i?b~&d%t2MN5$Kp?`IB zG`bz;@yvK8fIXeZ@fm&JVwphYG=H~ybagwl^Xzygu!6O3in!f|H@t^eWCDd>UYzv1 zy40wt3T)M`T-+Upg1inP0i%X4@E%MPeUfe|(kIDGc7>fvc zLc2?V@80+Bu~2~gevsw%@j_rgzmCuVi3rcl2n-0|pNvz5{(&Fp95Att7Xk>XC-B1~ zT(+wT5XG2%=Yqn)$ludB5s#QT-boT*LR_VGf%Qy)bh;He4fbB8s@Ma^wP?y!h; z>z20X4Y;%P2TOmj^ao3S@Zb7_@UVLSU*;cd{vbR){#LpFFY^x;e=v&{Z&6sa|1a|o zrazcPZ_m$**IC8>zsx@v{($D6&!693XVv=uGXIe6t{)zsrt`^UK7D!&EA{_n{vqQJ z!f5e6pPZjh=I@Ko+g1AiGXIcP@FOjN3QV7(?JE6$nSV(90r~xl_V-W%U!uk1L&hK2 z`+wCx+*tfW;tyW_zK}5%3XnevtM&hqlU>py7XOg8j(>zdpbFE|C^Y;5De?~}&p$Y3 z{~t!Di|Ekao)`EB*8H0OA=_PZh2zlLo|6LqKyv(p)gOe1xdtTHKgjk!>mM`=g=+Nw u*$L$P1L^<@`hS87{R7GK7fXLo%Krfj1r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_rnd.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--OrYXezi^E$Szxw=t66&`Ow+JOf&9@N(l!%m2s%_*20P(fTDIACHy8)ud!O!_nAijVl4mTz5yW9{T zmlJT&DDRKQo?~>&n+_EiI*5c|G+0;BXj_VWd=}%PUyajKsCyp z6mh93@FLyB?Wc})uc*XMaS bfSB*u1QZw;C7n&)0XYnwu6{1-oD!MBJ` zULSD+8pK!<z_g|!@TY> zKIc?e7F@@`#8Ehlg_}cU!V3THBTv6?cN5(s`^nE^KjWn1!4dbE?|o}{%2m0+^`8-k z#zN!TAmJ0$FvlK)uR!U%9+wf1y zmi31e&$SiI8?JIlWnE#8$Y$X+eZ`dW)2sJIcbM>xM7#ADr5P%F?=hap`Xc5q>pz2C z1OEei#*ULq4r=bHxLJSsF7t8WGv5wWGBSMq`u6%PGP2RU>fDHmU0s(bNx^N;m^ zbW0U3^nP7vpTWqSH|dcW=aplBSU#L-s$k+;IrG7vTMWe~n`W{;o5Y$qk5T*JQJWv- zI_(eb?Po1t$8`SCo7nO*ca5K?zTvp8>O7C(luU~kCa)oj}6iJRTd5l8oYI0Z8KotOV`=HeZ_Gn54MhW z$?WvN>8$~?H@fMz-0CsSQoNG3CXjofS#oa_M{aS!{?-dd?EMiOy~PFFTQ69!mq*|D z5`DA-LqlST&szUq&BXWIdN#q$6H^04?3CdUGwqQci)u2TUKGwho>ET9r^mk z1*vJQQBlX+WZ~4OntN7i4cBDtxZZsF!&Y9OlMfA0UuN~Ik^&;Ne?A7g*} z8b`)$vx?8}cD&2qw4Psn((&;2tq(uk%hRgx&dD~|v0MI%`%zMT>K5Dl87gb;F;BDmG;xt0 zgT(Y^y}Mhc$b?+gSg~3DHb0wyh4h`6 zyFWyoVTQcri=27QYZo$fRak0B`MGKs9sRe;`%tmc?;MSZ&Wr~F7z{)hcvu-QnGOw0 zE{Sq4U(EXDs-Eu+=9CrUzq*AKT3Hupo@xq;XlN1n`s|XFZJ&Dx; zmw7ABw|!c}A?bO(>%;f#iLWm-9mt3lsF|OaDYoJk^M&6f-dh~5%02KZ`^~o9f4j>S zcgF_{&YxmRe)l|(wW~+h;MvJg-7{JjnIeV7F5Eo5e(~zOvzHPY+joEPtJFIq^x)>{ z&}9({;%O&;TsAx=wxTY~Wd(Oy!Z+^CfA$o2WUTXOko?26@IyVXVvB%N2iLI~`DqWA W9esZ8q$Mx~FnGH9xvX>61w_lL-Zpi=Vw&v^;R7?sXt_@UX)-7ui(y7s4a?@Boqy3TYr){U){NrV9QZ7l!- zss&)Vy#r@mkOQ#wG;#v69z}^8a*Rkl)?-A7*`gAWk@9?v@R2{pf@pwJg!ejvXCMU- zMIs+_N(7Sk0<;n#I(aVIAv~Dib^#iv?nys{bqzyrU9$tmm12XizFuosX46z1#6WcptyUG(wJ8tePPm_b+_Q86|>s9#U^}1gWtQ10A<14pQk(GC|8sSO*F*eFQQ= w_!&SbRU5K!SBK3)19k`g`FVx7RV)4ef0|)Fxtu>Z^#A|>07*qoM6N<$f)IhJhX4Qo diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/meta.json deleted file mode 100644 index a1eca8b2a0..0000000000 --- a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/meta.json +++ /dev/null @@ -1,226 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint_sec.dmi, modified by ", - "states": [ - { - "name": "closed", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "locked", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closed_unlit", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "closing_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "deny", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "bolted", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "opening_unlit", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_closing", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "panel_open", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "panel_opening", - "directions": 1, - "delays": [ - [ - 0.2, - 0.1, - 0.1, - 0.1, - 0.1, - 0.6 - ] - ] - }, - { - "name": "spark", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_broken", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "sparks_damaged", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 1.7 - ] - ] - }, - { - "name": "sparks_open", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "welded", - "directions": 1, - "delays": [ - [ - 1 - ] - ] - } - ] -} diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/open.png deleted file mode 100644 index 689e8db2ebb61eae12cd0c53b0d4c07bc1f5f0a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvl>na*S0F7eA*QILprWp!s;a7{ zrlz5zYh+~P?B<@Jp;lpRxLTOczism;pgP8qAirP+hi5m^fShzs7sn8d^T{549kV#u zHlHp(7jrA?*n~T)c5v}*+a0oAsEdKCM9V3Jfi;cmtUo=J{87ucZDS+ zCWIQCNpTQPIG}dGahk)Y6%0q2&feO6km1DLy(bU#D4soJBEr`+`!d7*Sss}NKkLGP PRx)_H`njxgN@xNAgZxEP diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening.png deleted file mode 100644 index 485fed25cdb26044fe5b14298076705e8078593f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 835 zcmV-J1HAl+P)P)t-s0000N z7#1NSAS5R!B_$;$CMGB>Eiy7PIS>s)Mn_0w7fT-=OcW7cgdSihCT%P#Z8<7~_0L3q|4nuXGcF7UV|;X6D(0@^D}c=1o2=3Bxpv*HJEsA;B4e zf43WcF)N@`0<=r60{_c$Lx9`>Jrbb(EQ38}xm;jx;PUJN+9j}nlk~=N`S`djQl8Fx ziJBxJK$rjmV6zMW%@Tlp2nX5ir3Yx1AO--z`QHFN5+ncvcm6j(j|3^eHa0+q1a$z) z;1No&Wx&rtttJWJA}dh@0RQU#>+$=6Tb&{a6!+diAmM_KE_n$P0J~lPdH#JWN5C7( z{~v?_p#LC%U4}LSm!SjPp~{QrT{r^%FM{p596%|$SeQ}EIFus@3cc#!LBUbRe%8_wDwfRd)d>wv9%ABV!Eq%Nsz91t39_H zvrlvt2Nmz2CLeVb#fr!3YI3owC{{d{FG%%WMXBPkd`;%{T}7ejvwXqfRb9n_#w9>q zSHTX7KI`o&Sh?@11hi>f3+QUBYPyQ9#;OGnYWy95&p3Dk-hemYKLHd^C|?8UID<7E z0(WPye!$@wtV6=8L*SPjV@qeS9trLFAa_D>=YugP;cCxGIR3=>;2(N!@X{EI*{c8m N002ovPDHLkV1lCAT$=y@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening_unlit.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/opening_unlit.png deleted file mode 100644 index 553066879ddf2b0d9198ff3d933bc5675095ca08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^2|(j>p2Uj!<%i}gkMc- zxckfG+oz8kZ2zqTNVZPj)78&qol`;+05bo@-2eap diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_closing.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_closing.png deleted file mode 100644 index 8e330fb23624987ec8eb36abc265b379585dd2ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKaFsfr`WCjfKpfQc{!EOncaFYk(xStT?i|AtA7H-2&CjaOODSi=ta}K4l%qSDMxI vVOna*S0F7cp&}|ODl03iplPeB zs;Xh3plcasU|?Xz&21B{6T!gX=+&_SsE)BD$S;_|;n|HeAjiPd#W6(Vd~$*WYqO|{ zw6ysG4ihzBC(#VgTdisvPH=}R>{+eE;My=(_UFVdQ I&MBb@0CUtQ_W%F@ diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_opening.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/panel_opening.png deleted file mode 100644 index 8e7cf11e894e1f1124a0760c9ea8302584d36fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^2|(EamTaXdLef^~6% zNKey2_F28X(jJ#C%rIHmsKOjIsm%0&F+=cSrS)tzYza3c?u80AoM+&XzIjvfgLFfh sGP5%ya~$)9Tp5V=Km#Lf*H=soTOP@_FOvRo4rl{|r>mdKI;Vst0RP!HZvX%Q diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/spark.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/spark.png deleted file mode 100644 index 6fe7afa91a239279fd0cf726b27e53ab25e5f177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1011 zcmVs)Mn_0w7fT-=OO7&36cJG# z9AAVUU??VFGbUg_CSXM-XDTOcBqD7rDsLkpbUre4K{9te7kDx-cr!70L@|6UDt;&? zfHX0KH#CJRCyOQ{nMoO(0060sH>(p4!EP|hbus?{0RQqIje?2W0009XNkl=ly@>;W0Ak@XJ&|%U^>?V zk~c^i6=Efr%yo;zGvG}_Nh7ylwO}&0S|mgC?`{jGaI-~a1L9PNP^SfxxDa5X#IiI? zgdQ@TU=CLTj5UmvjjXaE4F5J0Oy>c7(xDdQtSqs_2Hpk{uUasZ3jtq=@D?zgU=CLT zvP6tPu6AG~n9j`>VFX-?yDgZ+wSXwGEGgXTgJ>r(`7Y0Qp99=luLTHjyv4W3YK5PB zD}ljxd6IxaFSpkVfh?vLuj>^CWIBPxA%7U6LJ#k(7Xo*g^`D|%F5w$K&hB&qlds>C zFp9$DeeLJn^->_njH_NgJS^)h3)%!N|J>za^!yx!`R>P)hdb*%703Wj1&OF2kpjs& zd-7LcuUBUf)AS|fDSlN^St5%;4NucZN=Xj1THwCzWL|^U>`5;#f?(p`I;TTh0h_gd=h=bg} zUJ0lzngOwyU^)-Pa6B~J&g6lJc=TTFcs_#%H-B*R2RDCk^9MJ7@J;@p_-21l9FE6B zaq0X&<{w;t0QukEK;gpqf6PBP{s8i?s%ixam(BlU{=uEDH{0rTsviX0^KXm;8 z6i}VMzE0Kg;PnSr`-irIkG235*lzkNxXwSE{Q>{`f%837AX{{F{DFV|H~mB6@ek+G zasO{G=6j(4`QeZ+n*YzU=_`-8$3L{A<6ij#RM@i4Yl{AW5BUeu=N|%h{x1&fc<33= z2mFH=eqI02ovxKa;T_NUfIr~Z_=BR~VD$O}J^uIk1Ku~^kInzx4fOj1bN~bMKPQ9! hf%o}~n?D%k{{cp{d|JZA1r*U0yg?d4_ z+N`H*RP-|9c$O-^6_Rz%UblFbD*9Tr`7=HI5PM^(=kc?by_BY;ZPsXPoNN@P-(BSD9xlbSa*3z= d0?R-1*k^uW+P`nc(*~ej44$rjF6*2UngHh$K#TwY diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/sparks_open.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/sparks_open.png deleted file mode 100644 index c005f849516d0cef67475c92684de8418d78d5a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@h94L%DH0iqSk?kF=5lw%?C%4{lc9IjDAgO+7 z<`L=PRKE(h4 diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/welded.png b/Resources/Textures/Constructible/Structures/Doors/airlock_maint_sec.rsi/welded.png deleted file mode 100644 index 47e0354168b78ce01f6583c47b471b2ec01dbd81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$DvS0HU-Vq#-sB547jBIYnhHNci--Or Date: Wed, 4 Nov 2020 08:08:47 +0100 Subject: [PATCH 12/41] Fix block game causing server crash (#2477) * Fix block game crashing server * fffff i just noticed * THIS is the correct property * Ignore unpause if game has not started * Init _currentPiece by BlockGame constructor --- .../Components/Arcade/BlockGameArcadeComponent.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs b/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs index 736442f95a..b60dc31c95 100644 --- a/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs +++ b/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs @@ -299,6 +299,7 @@ namespace Content.Server.GameObjects.Components.Arcade _component = component; _allBlockGamePieces = (BlockGamePieceType[]) Enum.GetValues(typeof(BlockGamePieceType)); _internalNextPiece = GetRandomBlockGamePiece(_component._random); + InitializeNewBlock(); } private void SendHighscoreUpdate() @@ -315,8 +316,6 @@ namespace Content.Server.GameObjects.Components.Arcade public void StartGame() { - InitializeNewBlock(); - _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game)); FullUpdate(); @@ -569,10 +568,10 @@ namespace Content.Server.GameObjects.Components.Arcade break; case BlockGamePlayerAction.Pause: _running = false; - _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Pause)); + _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Pause, _started)); break; case BlockGamePlayerAction.Unpause: - if (!_gameOver) + if (!_gameOver && _started) { _running = true; _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Game)); @@ -583,7 +582,7 @@ namespace Content.Server.GameObjects.Components.Arcade break; case BlockGamePlayerAction.ShowHighscores: _running = false; - _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Highscores)); + _component.UserInterface?.SendMessage(new BlockGameMessages.BlockGameSetScreenMessage(BlockGameMessages.BlockGameScreen.Highscores, _started)); break; } } @@ -654,6 +653,7 @@ namespace Content.Server.GameObjects.Components.Arcade } private bool IsGameOver => _field.Any(block => block.Position.Y == 0); + private void InvokeGameover() { _running = false; From f54016f91218f8c14becbabd5c6bfa8c3b68c5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 4 Nov 2020 10:16:28 +0100 Subject: [PATCH 13/41] Fixes incorrect reagents in produce --- .../Entities/Objects/Consumable/botany.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml index 1ee4463f89..64905e33a4 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml @@ -20,8 +20,11 @@ - type: SolutionContainer caps: NoExamine contents: - chem.Nutrient: 5 - chem.Flour: 5 + reagents: + - ReagentId: chem.Nutriment + Quantity: 5 + - ReagentId: chem.Flour + Quantity: 5 - type: Produce seed: wheat @@ -36,8 +39,11 @@ - type: SolutionContainer caps: NoExamine contents: - chem.Nutrient: 5 - chem.Flour: 5 + reagents: + - ReagentId: chem.Nutriment + Quantity: 5 + - ReagentId: chem.Glucose + Quantity: 5 - type: Produce seed: sugarcane From 5cac4c59171085531962ca991cd944aaa7d9947d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Wed, 4 Nov 2020 11:21:01 +0100 Subject: [PATCH 14/41] RotatableComponent QOL improvements. - Rotatable verbs only show if the entity can be rotated. - Adds parameter to rotate anchored entities. - Office chairs can now be rotated regardless of anchoring. --- .../Rotatable/RotatableComponent.cs | 20 ++++++++++++++++--- .../Constructible/Furniture/seats.yml | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs index 142cf392e2..403b7d73fd 100644 --- a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs +++ b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs @@ -6,6 +6,8 @@ using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Rotatable { @@ -14,9 +16,21 @@ namespace Content.Server.GameObjects.Components.Rotatable { public override string Name => "Rotatable"; + /// + /// If true, this entity can be rotated even while anchored. + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool RotateWhileAnchored { get; private set; } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(this, x => x.RotateWhileAnchored, "rotateWhileAnchored", false); + } + private void TryRotate(IEntity user, Angle angle) { - if (Owner.TryGetComponent(out IPhysicsComponent physics)) + if (!RotateWhileAnchored && Owner.TryGetComponent(out IPhysicsComponent physics)) { if (physics.Anchored) { @@ -33,7 +47,7 @@ namespace Content.Server.GameObjects.Components.Rotatable { protected override void GetData(IEntity user, RotatableComponent component, VerbData data) { - if (!ActionBlockerSystem.CanInteract(user)) + if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored)) { data.Visibility = VerbVisibility.Invisible; return; @@ -55,7 +69,7 @@ namespace Content.Server.GameObjects.Components.Rotatable { protected override void GetData(IEntity user, RotatableComponent component, VerbData data) { - if (!ActionBlockerSystem.CanInteract(user)) + if (!ActionBlockerSystem.CanInteract(user) || (!component.RotateWhileAnchored && component.Owner.TryGetComponent(out IPhysicsComponent physics) && physics.Anchored)) { data.Visibility = VerbVisibility.Invisible; return; diff --git a/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml b/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml index d66cf66bd4..5179d2cce2 100644 --- a/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml +++ b/Resources/Prototypes/Entities/Constructible/Furniture/seats.yml @@ -83,6 +83,7 @@ parent: SeatBase components: - type: Rotatable + rotateWhileAnchored: true - type: Sprite state: officechair_white - type: Physics From 8fa6f2c3dedd80530705b9e9d2114e0f0a357460 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Thu, 5 Nov 2020 03:57:49 -0800 Subject: [PATCH 15/41] Add feedback to the signallink command (#2482) --- .../GameObjects/EntitySystems/SignalLinkerSystem.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs index a9c58b076a..57406584c7 100644 --- a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs @@ -25,7 +25,7 @@ namespace Content.Server.GameObjects.EntitySystems _transmitters = new Dictionary(); } - public void SignalLinkerKeybind(NetUserId id, bool? enable) + public bool SignalLinkerKeybind(NetUserId id, bool? enable) { if (enable == null) { @@ -36,7 +36,7 @@ namespace Content.Server.GameObjects.EntitySystems { if (_transmitters.ContainsKey(id)) { - return; + return true; } if (_transmitters.Count == 0) @@ -53,7 +53,7 @@ namespace Content.Server.GameObjects.EntitySystems { if (!_transmitters.ContainsKey(id)) { - return; + return false; } _transmitters.Remove(id); @@ -62,6 +62,7 @@ namespace Content.Server.GameObjects.EntitySystems CommandBinds.Unregister(); } } + return enable == true; } private bool HandleUse(ICommonSession session, EntityCoordinates coords, EntityUid uid) @@ -129,7 +130,8 @@ namespace Content.Server.GameObjects.EntitySystems return; } - system.SignalLinkerKeybind(player.UserId, enable); + var ret = system.SignalLinkerKeybind(player.UserId, enable); + shell.SendText(player, ret ? "Enabled" : "Disabled"); } } } From 51d8d5dd9d9aa7cd90b76a67446ee561c7448513 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 6 Nov 2020 01:08:24 +1100 Subject: [PATCH 16/41] Disable climbing when buckled (#2488) Co-authored-by: Metal Gear Sloth --- .../Components/Movement/ClimbingComponent.cs | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs index 93f02320ac..8c3a5e84e2 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbingComponent.cs @@ -1,6 +1,9 @@ -using Content.Shared.GameObjects.Components.Movement; +#nullable enable +using Content.Shared.GameObjects.Components.Buckle; +using Content.Shared.GameObjects.Components.Movement; using Content.Shared.Physics; using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Maths; namespace Content.Server.GameObjects.Components.Movement @@ -8,8 +11,8 @@ namespace Content.Server.GameObjects.Components.Movement [RegisterComponent] public class ClimbingComponent : SharedClimbingComponent { - private bool _isClimbing = false; - private ClimbController _climbController = default; + private bool _isClimbing; + private ClimbController? _climbController; public override bool IsClimbing { @@ -29,6 +32,19 @@ namespace Content.Server.GameObjects.Components.Movement } } + public override void HandleMessage(ComponentMessage message, IComponent? component) + { + base.HandleMessage(message, component); + switch (message) + { + case BuckleMessage msg: + if (msg.Buckled) + IsClimbing = false; + + break; + } + } + /// /// Make the owner climb from one point to another /// From 14568bc10c95714abc4f1bab3195ca438a05c386 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 6 Nov 2020 03:58:41 +1100 Subject: [PATCH 17/41] Reset saltern disposal entries to default (#2486) Co-authored-by: Metal Gear Sloth --- Resources/Maps/saltern.yml | 51 +++++++++++++------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 54d139ef00..26b7021323 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -1676,8 +1676,7 @@ entities: pos: -17.5,-22.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -1775,8 +1774,7 @@ entities: pos: -29.5,11.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -1900,8 +1898,7 @@ entities: pos: -5.5,17.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -1967,8 +1964,7 @@ entities: pos: 6.5,11.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -2047,8 +2043,7 @@ entities: pos: 24.5,8.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -2221,8 +2216,7 @@ entities: pos: 34.5,-4.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -2379,8 +2373,7 @@ entities: pos: 37.5,6.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -2798,8 +2791,7 @@ entities: pos: -2.5,29.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -3111,8 +3103,7 @@ entities: pos: 11.5,-11.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -3190,8 +3181,7 @@ entities: pos: 12.5,-2.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -3608,8 +3598,7 @@ entities: pos: 0.5,1.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -3971,8 +3960,7 @@ entities: pos: -12.5,1.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -4103,8 +4091,7 @@ entities: pos: -22.5,6.5 rot: 3.141592653589793 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -4469,8 +4456,7 @@ entities: pos: -27.5,-8.5 rot: 1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -4523,8 +4509,7 @@ entities: pos: -10.5,-17.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -8298,8 +8283,7 @@ entities: pos: -5.5,-14.5 rot: -1.5707963267948966 rad type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: @@ -21437,8 +21421,7 @@ entities: - parent: 855 pos: 18.5,-0.5 type: Transform - - entryDelay: 0 - type: DisposalUnit + - type: DisposalUnit - deadThreshold: 100 type: Destructible - containers: From e62df15ef93a6909c4b129076435c72ba4553643 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 6 Nov 2020 04:04:07 +1100 Subject: [PATCH 18/41] Add cvar for events (#2478) There's also the existing events command as well that's separate. I think there's value in having both? (Where mods can turn it on and off but not change the default?) Co-authored-by: Metal Gear Sloth --- .../EntitySystems/StationEvents/StationEventSystem.cs | 6 ++++++ Content.Shared/CCVars.cs | 3 +++ 2 files changed, 9 insertions(+) diff --git a/Content.Server/GameObjects/EntitySystems/StationEvents/StationEventSystem.cs b/Content.Server/GameObjects/EntitySystems/StationEvents/StationEventSystem.cs index ac1ea379d8..6da998d840 100644 --- a/Content.Server/GameObjects/EntitySystems/StationEvents/StationEventSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/StationEvents/StationEventSystem.cs @@ -4,11 +4,13 @@ using System.Text; using Content.Server.GameTicking; using Content.Server.Interfaces.GameTicking; using Content.Server.StationEvents; +using Content.Shared; using Content.Shared.GameTicking; using JetBrains.Annotations; using Robust.Server.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Reflection; @@ -23,6 +25,7 @@ namespace Content.Server.GameObjects.EntitySystems.StationEvents // Somewhat based off of TG's implementation of events public sealed class StationEventSystem : EntitySystem, IResettingEntitySystem { + [Dependency] private readonly IConfigurationManager _configurationManager = default!; [Dependency] private readonly IServerNetManager _netManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IGameTicker _gameTicker = default!; @@ -164,6 +167,9 @@ namespace Content.Server.GameObjects.EntitySystems.StationEvents _stationEvents.Add(stationEvent); } + // Can't just check debug / release for a default given mappers need to use release mode + // As such we'll always pause it by default. + _configurationManager.OnValueChanged(CCVars.EventsEnabled, value => Enabled = value, true); _netManager.RegisterNetMessage(nameof(MsgGetStationEvents), GetEventReceived); } diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs index d01c1d9c19..94c17dc378 100644 --- a/Content.Shared/CCVars.cs +++ b/Content.Shared/CCVars.cs @@ -7,6 +7,9 @@ namespace Content.Shared [CVarDefs] public sealed class CCVars : CVars { + public static readonly CVarDef + EventsEnabled = CVarDef.Create("events.enabled", false, CVar.ARCHIVE | CVar.SERVERONLY); + public static readonly CVarDef GameLobbyEnabled = CVarDef.Create("game.lobbyenabled", false, CVar.ARCHIVE); From 864fa0a57cc960e157f9bbab3418c00740434ad5 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Fri, 6 Nov 2020 04:04:21 +1100 Subject: [PATCH 19/41] Minor device network changes (#2499) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Device network changes * Update too * Update Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs Co-authored-by: Metal Gear Sloth Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> --- .../ConfigurationBoundUserInterface.cs | 1 + Content.Server/DeviceNetwork/DeviceNetwork.cs | 17 +++++------ .../DeviceNetwork/DeviceNetworkConnection.cs | 8 ++--- .../Components/ConfigurationComponent.cs | 29 ++++++++++--------- .../Disposal/DisposalMailingUnitComponent.cs | 11 ++++--- .../EntitySystems/DeviceNetworkSystem.cs | 17 ++--------- .../SharedConfigurationComponent.cs | 21 +++++++++++--- 7 files changed, 53 insertions(+), 51 deletions(-) diff --git a/Content.Client/GameObjects/Components/Configuration/ConfigurationBoundUserInterface.cs b/Content.Client/GameObjects/Components/Configuration/ConfigurationBoundUserInterface.cs index d173f061ed..97bcdf20b6 100644 --- a/Content.Client/GameObjects/Components/Configuration/ConfigurationBoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/Configuration/ConfigurationBoundUserInterface.cs @@ -49,6 +49,7 @@ namespace Content.Client.GameObjects.Components.Wires { base.Dispose(disposing); + _menu.OnClose -= Close; _menu.Close(); } } diff --git a/Content.Server/DeviceNetwork/DeviceNetwork.cs b/Content.Server/DeviceNetwork/DeviceNetwork.cs index 414cbe9cb8..06a9f4e054 100644 --- a/Content.Server/DeviceNetwork/DeviceNetwork.cs +++ b/Content.Server/DeviceNetwork/DeviceNetwork.cs @@ -1,4 +1,5 @@ -using Content.Server.Interfaces; +using System; +using Content.Server.Interfaces; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using System.Collections.Generic; @@ -11,7 +12,8 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork { private const int PACKAGES_PER_TICK = 30; - private readonly IRobustRandom _random = IoCManager.Resolve(); + [Dependency] private readonly IRobustRandom _random = default!; + private readonly Dictionary> _devices = new Dictionary>(); private readonly Queue _packages = new Queue(); @@ -40,11 +42,9 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork public void Update() { - var i = PACKAGES_PER_TICK; - while (_packages.Count > 0 && i > 0) + var count = Math.Min(PACKAGES_PER_TICK, _packages.Count); + for (var i = 0; i < count; i++) { - i--; - var package = _packages.Dequeue(); if (package.Broadcast) @@ -72,7 +72,7 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork Sender = sender, Metadata = metadata }; - + _packages.Enqueue(package); return true; } @@ -132,7 +132,7 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork { var devices = DevicesForFrequency(netId, frequency); - var device = devices.Find(device => device.Address == address); + var device = devices.Find(dvc => dvc.Address == address); return device; } @@ -192,7 +192,6 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork public IReadOnlyDictionary Data { get; set; } public Metadata Metadata; public string Sender; - } } } diff --git a/Content.Server/DeviceNetwork/DeviceNetworkConnection.cs b/Content.Server/DeviceNetwork/DeviceNetworkConnection.cs index 204f00edf6..9cc17e8cb1 100644 --- a/Content.Server/DeviceNetwork/DeviceNetworkConnection.cs +++ b/Content.Server/DeviceNetwork/DeviceNetworkConnection.cs @@ -11,14 +11,14 @@ namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork private readonly int _netId; [ViewVariables] - public bool Open { get; internal set; } + public bool Open { get; private set; } [ViewVariables] - public string Address { get; internal set; } + public string Address { get; private set; } [ViewVariables] - public int Frequency { get; internal set; } + public int Frequency { get; private set; } [ViewVariables] - public bool RecieveAll + public bool ReceiveAll { get => _network.GetDeviceReceiveAll(_netId, Frequency, Address); set => _network.SetDeviceReceiveAll(_netId, Frequency, Address, value); diff --git a/Content.Server/GameObjects/Components/ConfigurationComponent.cs b/Content.Server/GameObjects/Components/ConfigurationComponent.cs index 77049e6260..6e468e2435 100644 --- a/Content.Server/GameObjects/Components/ConfigurationComponent.cs +++ b/Content.Server/GameObjects/Components/ConfigurationComponent.cs @@ -8,9 +8,7 @@ using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -28,18 +26,24 @@ namespace Content.Server.GameObjects.Components private Regex _validation; - public event Action> OnConfigUpdate; - - public override void Initialize() + public override void OnAdd() { - base.Initialize(); - + base.OnAdd(); if (UserInterface != null) { UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage; } } + public override void OnRemove() + { + base.OnRemove(); + if (UserInterface != null) + { + UserInterface.OnReceiveMessage -= UserInterfaceOnReceiveMessage; + } + } + public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); @@ -48,7 +52,7 @@ namespace Content.Server.GameObjects.Components (list) => FillConfiguration(list, _config, ""), () => _config.Keys.ToList()); - serializer.DataReadFunction("vailidation", "^[a-zA-Z0-9 ]*$", value => _validation = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled)); + serializer.DataReadFunction("validation", "^[a-zA-Z0-9 ]*$", value => _validation = new Regex("^[a-zA-Z0-9 ]*$", RegexOptions.Compiled)); } public string GetConfig(string name) @@ -90,22 +94,19 @@ namespace Content.Server.GameObjects.Components { var value = msg.Config.GetValueOrDefault(key); - if (_validation != null && !_validation.IsMatch(value) && value != "") + if (value == null || _validation != null && !_validation.IsMatch(value) && value != "") continue; _config[key] = value; } - OnConfigUpdate(_config); + SendMessage(new ConfigUpdatedComponentMessage(config)); } } private void UpdateUserInterface() { - if (UserInterface == null) - return; - - UserInterface.SetState(new ConfigurationBoundUserInterfaceState(_config)); + UserInterface?.SetState(new ConfigurationBoundUserInterfaceState(_config)); } private static void FillConfiguration(List list, Dictionary configuration, T value){ diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs index 67cac05d66..e757fb5ace 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs @@ -13,6 +13,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Utility; +using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Disposal; using Content.Shared.GameObjects.EntitySystems; @@ -603,12 +604,7 @@ namespace Content.Server.GameObjects.Components.Disposal UserInterface.OnReceiveMessage += OnUiReceiveMessage; } - var network = IoCManager.Resolve(); _connection = new WiredNetworkConnection(OnReceiveNetMessage, false, Owner); - - if (Owner.TryGetComponent(out var configuration)) - configuration.OnConfigUpdate += OnConfigUpdate; - UpdateInterface(); } @@ -673,6 +669,9 @@ namespace Content.Server.GameObjects.Components.Disposal switch (message) { + case SharedConfigurationComponent.ConfigUpdatedComponentMessage msg: + OnConfigUpdate(msg.Config); + break; case RelayMovementEntityMessage msg: if (!msg.Entity.TryGetComponent(out HandsComponent? hands) || hands.Count == 0 || @@ -745,7 +744,7 @@ namespace Content.Server.GameObjects.Components.Disposal return false; } - // Duplicated code here, not sure how else to get actor inside to make UserInterface happy. + // Duplicated code here, not sure how else to get actor inside to make UserInterface happy. if (IsValidInteraction(eventArgs)) { diff --git a/Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs b/Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs index f5b99a5988..0708dbada4 100644 --- a/Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs @@ -1,27 +1,16 @@ -using Content.Server.Interfaces; +using Content.Server.Interfaces; using Robust.Shared.GameObjects.Systems; using Robust.Shared.IoC; namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork { - public class DeviceNetworkSystem : EntitySystem + internal sealed class DeviceNetworkSystem : EntitySystem { - private IDeviceNetwork _network; - - public override void Initialize() - { - base.Initialize(); - - _network = IoCManager.Resolve(); - } + [Dependency] private readonly IDeviceNetwork _network = default!; public override void Update(float frameTime) { base.Update(frameTime); - - if (_network == null) - return; - //(ノ°Д°)ノ︵ ┻━┻ _network.Update(); } } diff --git a/Content.Shared/GameObjects/Components/SharedConfigurationComponent.cs b/Content.Shared/GameObjects/Components/SharedConfigurationComponent.cs index 413507d3b3..590f770b62 100644 --- a/Content.Shared/GameObjects/Components/SharedConfigurationComponent.cs +++ b/Content.Shared/GameObjects/Components/SharedConfigurationComponent.cs @@ -13,21 +13,34 @@ namespace Content.Shared.GameObjects.Components [Serializable, NetSerializable] public class ConfigurationBoundUserInterfaceState : BoundUserInterfaceState { - public readonly Dictionary Config; - + public Dictionary Config { get; } + public ConfigurationBoundUserInterfaceState(Dictionary config) { Config = config; } } + /// + /// Message sent to other components on this entity when DeviceNetwork configuration updated. + /// + public class ConfigUpdatedComponentMessage : ComponentMessage + { + public Dictionary Config { get; } + + public ConfigUpdatedComponentMessage(Dictionary config) + { + Config = config; + } + } + /// /// Message data sent from client to server when the device configuration is updated. /// [Serializable, NetSerializable] public class ConfigurationUpdatedMessage : BoundUserInterfaceMessage { - public readonly Dictionary Config; + public Dictionary Config { get; } public ConfigurationUpdatedMessage(Dictionary config) { @@ -38,7 +51,7 @@ namespace Content.Shared.GameObjects.Components [Serializable, NetSerializable] public class ValidationUpdateMessage : BoundUserInterfaceMessage { - public readonly string ValidationString; + public string ValidationString { get; } public ValidationUpdateMessage(string validationString) { From 60dd0de96f12667a407f1cbf40b2da20942c176c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 6 Nov 2020 10:56:14 +0100 Subject: [PATCH 20/41] Fix crash when invalid construction prototype is passed. Fixes #2501 --- .../EntitySystems/ConstructionSystem.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs index 96520441b8..f415bf2b98 100644 --- a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs @@ -20,6 +20,7 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Localization; +using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Players; using Robust.Shared.Prototypes; @@ -306,8 +307,18 @@ namespace Content.Server.GameObjects.EntitySystems private async void HandleStartItemConstruction(TryStartItemConstructionMessage ev, EntitySessionEventArgs args) { - var constructionPrototype = _prototypeManager.Index(ev.PrototypeName); - var constructionGraph = _prototypeManager.Index(constructionPrototype.Graph); + if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype constructionPrototype)) + { + Logger.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!"); + return; + } + + if (!_prototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype constructionGraph)) + { + Logger.Error($"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!"); + return; + } + var startNode = constructionGraph.Nodes[constructionPrototype.StartNode]; var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode]; var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name); @@ -352,8 +363,20 @@ namespace Content.Server.GameObjects.EntitySystems private async void HandleStartStructureConstruction(TryStartStructureConstructionMessage ev, EntitySessionEventArgs args) { - var constructionPrototype = _prototypeManager.Index(ev.PrototypeName); - var constructionGraph = _prototypeManager.Index(constructionPrototype.Graph); + if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype constructionPrototype)) + { + Logger.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!"); + RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack)); + return; + } + + if (!_prototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype constructionGraph)) + { + Logger.Error($"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!"); + RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack)); + return; + } + var startNode = constructionGraph.Nodes[constructionPrototype.StartNode]; var targetNode = constructionGraph.Nodes[constructionPrototype.TargetNode]; var pathFind = constructionGraph.Path(startNode.Name, targetNode.Name); From 6a469508cae0645531193e613826fe45257ca1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= <6766154+Zumorica@users.noreply.github.com> Date: Fri, 6 Nov 2020 12:38:24 +0100 Subject: [PATCH 21/41] Fix every BuckleComponent subscribing to EventBus when buckled (#2504) --- .../Components/Buckle/BuckleComponent.cs | 7 +------ .../GameObjects/EntitySystems/BuckleSystem.cs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 94e7b0d8a4..7e956d89de 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -287,9 +287,6 @@ namespace Content.Server.GameObjects.Components.Buckle SendMessage(new BuckleMessage(Owner, to)); - Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, MoveEvent); - - if (Owner.TryGetComponent(out PullableComponent? pullableComponent)) { if (pullableComponent.Puller != null) @@ -373,8 +370,6 @@ namespace Content.Server.GameObjects.Components.Buckle SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner)); - Owner.EntityManager.EventBus.UnsubscribeEvent(EventSource.Local, this); - return true; } @@ -407,7 +402,7 @@ namespace Content.Server.GameObjects.Components.Buckle /// too far from its strap. /// /// The move event of a buckled entity. - private void MoveEvent(MoveEvent moveEvent) + public void OnMoveEvent(MoveEvent moveEvent) { if (moveEvent.Sender != Owner) { diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs index 9fbb049322..e957fbd6c7 100644 --- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs @@ -2,6 +2,8 @@ using Content.Server.GameObjects.EntitySystems.Click; using JetBrains.Annotations; using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Systems; namespace Content.Server.GameObjects.EntitySystems @@ -15,6 +17,22 @@ namespace Content.Server.GameObjects.EntitySystems UpdatesAfter.Add(typeof(InteractionSystem)); UpdatesAfter.Add(typeof(InputSystem)); + EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, MoveEvent); + } + + public override void Shutdown() + { + base.Shutdown(); + + EntityManager.EventBus.UnsubscribeEvent(EventSource.Local, this); + } + + private void MoveEvent(MoveEvent ev) + { + if (ev.Sender.TryGetComponent(out BuckleComponent buckle)) + { + buckle.OnMoveEvent(ev); + } } public override void Update(float frameTime) From bb3aee90b23e0f891fb11d1129f0ca798e92c00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= <6766154+Zumorica@users.noreply.github.com> Date: Fri, 6 Nov 2020 12:38:41 +0100 Subject: [PATCH 22/41] FloorTileItem station extension/new grid creation (#2500) * FloorTileItemComponent can now extend the station, or create new grids. * Fixes wrong interaction system EntityCoordinates check. Needed for all this to work. --- .../Items/FloorTileItemComponent.cs | 49 +++++++++++++++---- .../EntitySystems/Click/InteractionSystem.cs | 8 +-- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs b/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs index 52cf806e84..a9df905b61 100644 --- a/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs +++ b/Content.Server/GameObjects/Components/Items/FloorTileItemComponent.cs @@ -1,4 +1,5 @@ using Content.Server.GameObjects.Components.Stack; +using Content.Shared.Audio; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Maps; using Content.Shared.Utility; @@ -8,6 +9,7 @@ using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Map; +using Robust.Shared.Maths; using Robust.Shared.Serialization; namespace Content.Server.GameObjects.Components.Items @@ -33,23 +35,52 @@ namespace Content.Server.GameObjects.Components.Items Owner.EnsureComponent(); } + private bool HasBaseTurf(ContentTileDefinition tileDef, string baseTurf) + { + foreach (var tileBaseTurf in tileDef.BaseTurfs) + { + if (baseTurf == tileBaseTurf) + { + return true; + } + } + + return false; + } + + private void PlaceAt(IMapGrid mapGrid, EntityCoordinates location, ushort tileId, float offset = 0) + { + mapGrid.SetTile(location.Offset(new Vector2(offset, offset)), new Tile(tileId)); + EntitySystem.Get().PlayAtCoords("/Audio/Items/genhit.ogg", location, AudioHelpers.WithVariation(0.125f)); + } + public void AfterInteract(AfterInteractEventArgs eventArgs) { if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return; if (!Owner.TryGetComponent(out StackComponent stack)) return; - var attacked = eventArgs.Target; - var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GetGridId(Owner.EntityManager)); - var tile = mapGrid.GetTileRef(eventArgs.ClickLocation); - var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; + var location = eventArgs.ClickLocation.AlignWithClosestGridTile(); + var locationMap = location.ToMap(Owner.EntityManager); - if (tileDef.IsSubFloor && attacked == null && stack.Use(1)) + var desiredTile = (ContentTileDefinition)_tileDefinitionManager[_outputTile]; + + if (_mapManager.TryGetGrid(location.GetGridId(Owner.EntityManager), out var mapGrid)) { - var desiredTile = _tileDefinitionManager[_outputTile]; - mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId)); - EntitySystem.Get().PlayAtCoords("/Audio/Items/genhit.ogg", eventArgs.ClickLocation); - } + var tile = mapGrid.GetTileRef(location); + var baseTurf = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; + if (HasBaseTurf(desiredTile, baseTurf.Name) && eventArgs.Target == null && stack.Use(1)) + { + PlaceAt(mapGrid, location, desiredTile.TileId); + } + } + else if(HasBaseTurf(desiredTile, "space")) + { + mapGrid = _mapManager.CreateGrid(locationMap.MapId); + mapGrid.WorldPosition = locationMap.Position; + location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero); + PlaceAt(mapGrid, location, desiredTile.TileId, mapGrid.TileSize/2f); + } } diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index b0e611e96d..0a6d5e4765 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -156,7 +156,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click private bool HandleWideAttack(ICommonSession session, EntityCoordinates coords, EntityUid uid) { // client sanitization - if (!_mapManager.GridExists(coords.GetGridId(_entityManager))) + if (!coords.IsValid(_entityManager)) { Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}"); return true; @@ -211,7 +211,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click private bool HandleClientUseItemInHand(ICommonSession session, EntityCoordinates coords, EntityUid uid) { // client sanitization - if (!_mapManager.GridExists(coords.GetGridId(_entityManager))) + if (!coords.IsValid(_entityManager)) { Logger.InfoS("system.interaction", $"Invalid Coordinates: client={session}, coords={coords}"); return true; @@ -242,7 +242,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click private bool HandleTryPullObject(ICommonSession session, EntityCoordinates coords, EntityUid uid) { // client sanitization - if (!_mapManager.GridExists(coords.GetGridId(_entityManager))) + if (!coords.IsValid(_entityManager)) { Logger.InfoS("system.interaction", $"Invalid Coordinates for pulling: client={session}, coords={coords}"); return false; @@ -303,7 +303,7 @@ namespace Content.Server.GameObjects.EntitySystems.Click } // Verify player is on the same map as the entity he clicked on - if (_mapManager.GetGrid(coordinates.GetGridId(EntityManager)).ParentMapId != playerTransform.MapID) + if (coordinates.GetMapId(_entityManager) != playerTransform.MapID) { Logger.WarningS("system.interaction", $"Player named {player.Name} clicked on a map he isn't located on"); From 089422fa996bef5ad6ba64d7a3a01acc9ab98cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 6 Nov 2020 12:43:38 +0100 Subject: [PATCH 23/41] Use EntitySystem proxies to (un)subscribe to event in BuckleSystem. --- Content.Server/GameObjects/EntitySystems/BuckleSystem.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs index e957fbd6c7..8e2f0c2422 100644 --- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs @@ -17,14 +17,14 @@ namespace Content.Server.GameObjects.EntitySystems UpdatesAfter.Add(typeof(InteractionSystem)); UpdatesAfter.Add(typeof(InputSystem)); - EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, MoveEvent); + SubscribeLocalEvent(MoveEvent); } public override void Shutdown() { base.Shutdown(); - - EntityManager.EventBus.UnsubscribeEvent(EventSource.Local, this); + + UnsubscribeLocalEvent(); } private void MoveEvent(MoveEvent ev) From 8930ba845b505acc697676b38c6f95ffe8898c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Fri, 6 Nov 2020 12:46:23 +0100 Subject: [PATCH 24/41] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 245c0f578d..fd93fcb89c 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 245c0f578d09f0664d85a6e356441e5fe1dfe634 +Subproject commit fd93fcb89ca1a9dc8a640eb2a10a74e18e0a7106 From 9926ef298c46832c794546e879b910dcceededf5 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Fri, 6 Nov 2020 12:52:01 +0100 Subject: [PATCH 25/41] Move rotate event subscription from NodeContainerComponent to NodeContainerSystem (#2506) --- .../NodeContainer/NodeContainerComponent.cs | 16 ------- .../EntitySystems/NodeContainerSystem.cs | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 Content.Server/GameObjects/EntitySystems/NodeContainerSystem.cs diff --git a/Content.Server/GameObjects/Components/NodeContainer/NodeContainerComponent.cs b/Content.Server/GameObjects/Components/NodeContainer/NodeContainerComponent.cs index de72f5b58e..23a2d1be45 100644 --- a/Content.Server/GameObjects/Components/NodeContainer/NodeContainerComponent.cs +++ b/Content.Server/GameObjects/Components/NodeContainer/NodeContainerComponent.cs @@ -1,9 +1,6 @@ using System.Collections.Generic; -using System.Linq; using Content.Server.GameObjects.Components.NodeContainer.Nodes; using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Components.Transform; -using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -34,8 +31,6 @@ namespace Content.Server.GameObjects.Components.NodeContainer { node.Initialize(Owner); } - - Owner.EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, RotateEvent); } protected override void Startup() @@ -55,16 +50,5 @@ namespace Content.Server.GameObjects.Components.NodeContainer } base.OnRemove(); } - - private void RotateEvent(RotateEvent ev) - { - if (ev.Sender != Owner || ev.NewRotation == ev.OldRotation) - return; - - foreach (var rotatableNode in Nodes.OfType()) - { - rotatableNode.RotateEvent(ev); - } - } } } diff --git a/Content.Server/GameObjects/EntitySystems/NodeContainerSystem.cs b/Content.Server/GameObjects/EntitySystems/NodeContainerSystem.cs new file mode 100644 index 0000000000..2c60a40bed --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/NodeContainerSystem.cs @@ -0,0 +1,45 @@ +using System.Linq; +using Content.Server.GameObjects.Components.NodeContainer; +using Content.Server.GameObjects.Components.NodeContainer.Nodes; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Components.Transform; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class NodeContainerSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(RotateEvent); + } + + public override void Shutdown() + { + base.Shutdown(); + + UnsubscribeLocalEvent(); + } + + private void RotateEvent(RotateEvent ev) + { + if (!ev.Sender.TryGetComponent(out NodeContainerComponent container)) + { + return; + } + + if (ev.NewRotation == ev.OldRotation) + { + return; + } + + foreach (var rotatableNode in container.Nodes.OfType()) + { + rotatableNode.RotateEvent(ev); + } + } + } +} From 560f89b2976b26d9ea0a27d90db2908d658ba69b Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Fri, 6 Nov 2020 15:04:13 +0100 Subject: [PATCH 26/41] Fix AI crash when an entity is moved to an invalid grid (#2507) --- .../EntitySystems/AI/Pathfinding/PathfindingSystem.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs index 5bdbbbe9d3..78d3778c8a 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Pathfinding/PathfindingSystem.cs @@ -328,9 +328,16 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding return; } + var newGridId = moveEvent.NewPosition.GetGridId(_entityManager); + if (newGridId == GridId.Invalid) + { + HandleEntityRemove(moveEvent.Sender); + return; + } + // The pathfinding graph is tile-based so first we'll check if they're on a different tile and if we need to update. // If you get entities bigger than 1 tile wide you'll need some other system so god help you. - var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GetGridId(_entityManager)).GetTileRef(moveEvent.NewPosition); + var newTile = _mapManager.GetGrid(newGridId).GetTileRef(moveEvent.NewPosition); if (oldNode == null || oldNode.TileRef == newTile) { From b5d00a2cf64b597bdb9c4767eaa72fbbc9153d19 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Fri, 6 Nov 2020 15:15:02 +0100 Subject: [PATCH 27/41] Buckle improvements (#2508) * Buckle improvements * Update doc * Remove redundant argument name * Remove import --- .../Tests/Buckle/BuckleTest.cs | 2 +- .../Components/Buckle/BuckleComponent.cs | 170 +++--------------- .../GameObjects/EntitySystems/BuckleSystem.cs | 72 +++++++- 3 files changed, 93 insertions(+), 151 deletions(-) diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 6e781970bd..6bcf4b5872 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -302,7 +302,7 @@ namespace Content.IntegrationTests.Tests.Buckle human.Transform.LocalPosition += (100, 0); }); - await WaitUntil(server, () => !buckle.Buckled, maxTicks: 10); + await WaitUntil(server, () => !buckle.Buckled, 10); Assert.False(buckle.Buckled); diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 7e956d89de..0eb0ffebea 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -15,21 +15,16 @@ using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; -using NFluidsynth; using Robust.Server.GameObjects; -using Robust.Server.GameObjects.EntitySystemMessages; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.ComponentDependencies; -using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; -using Robust.Shared.Log; using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -39,8 +34,6 @@ namespace Content.Server.GameObjects.Components.Buckle [RegisterComponent] public class BuckleComponent : SharedBuckleComponent, IInteractHand { - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null; @@ -69,7 +62,10 @@ namespace Content.Server.GameObjects.Components.Buckle [ViewVariables] private TimeSpan _buckleTime; - public Vector2? BuckleOffset { get; private set; } + /// + /// The position offset that is being applied to this entity if buckled. + /// + public Vector2 BuckleOffset { get; private set; } private StrapComponent? _buckledTo; @@ -91,20 +87,6 @@ namespace Content.Server.GameObjects.Components.Buckle [ViewVariables] public override bool Buckled => BuckledTo != null; - /// - /// True if the entity was inserted or removed from a container - /// before updating, false otherwise. - /// - [ViewVariables] - private bool ContainerChanged { get; set; } - - /// - /// True if the entity was forcefully moved while buckled and should - /// unbuckle next update, false otherwise - /// - [ViewVariables] - private bool Moved { get; set; } - /// /// The amount of space that this entity occupies in a /// . @@ -116,18 +98,20 @@ namespace Content.Server.GameObjects.Components.Buckle /// Shows or hides the buckled status effect depending on if the /// entity is buckled or not. /// - private void BuckleStatus() + private void UpdateBuckleStatus() { - if (_serverStatusEffectsComponent != null) + if (_serverStatusEffectsComponent == null) { - if (Buckled) - { - _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon); - } - else - { - _serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled); - } + return; + } + + if (Buckled) + { + _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon); + } + else + { + _serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled); } } @@ -135,7 +119,7 @@ namespace Content.Server.GameObjects.Components.Buckle /// Reattaches this entity to the strap, modifying its position and rotation. /// /// The strap to reattach to. - private void ReAttach(StrapComponent strap) + public void ReAttach(StrapComponent strap) { var ownTransform = Owner.Transform; var strapTransform = strap.Owner.Transform; @@ -161,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Buckle if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North) { BuckleOffset = (0, 0.15f); - ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset!.Value; + ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset; } else { @@ -266,8 +250,7 @@ namespace Content.Server.GameObjects.Components.Buckle return false; } - _entitySystem.GetEntitySystem() - .PlayFromEntity(strap.BuckleSound, Owner); + EntitySystem.Get().PlayFromEntity(strap.BuckleSound, Owner); if (!strap.TryAdd(this)) { @@ -283,7 +266,7 @@ namespace Content.Server.GameObjects.Components.Buckle BuckledTo = strap; ReAttach(strap); - BuckleStatus(); + UpdateBuckleStatus(); SendMessage(new BuckleMessage(Owner, to)); @@ -312,12 +295,12 @@ namespace Content.Server.GameObjects.Components.Buckle /// public bool TryUnbuckle(IEntity user, bool force = false) { - if (!Buckled) + if (BuckledTo == null) { return false; } - StrapComponent oldBuckledTo = BuckledTo!; + var oldBuckledTo = BuckledTo; if (!force) { @@ -357,16 +340,12 @@ namespace Content.Server.GameObjects.Components.Buckle EntitySystem.Get().Standing(Owner); } - if (_mobStateManagerComponent != null) - { - _mobStateManagerComponent.CurrentMobState.EnterState(Owner); - } + _mobStateManagerComponent?.CurrentMobState.EnterState(Owner); - BuckleStatus(); + UpdateBuckleStatus(); oldBuckledTo.Remove(this); - _entitySystem.GetEntitySystem() - .PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner); + EntitySystem.Get().PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner); SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner)); @@ -397,90 +376,6 @@ namespace Content.Server.GameObjects.Components.Buckle return TryBuckle(user, to); } - /// - /// Checks if a buckled entity should be unbuckled from moving - /// too far from its strap. - /// - /// The move event of a buckled entity. - public void OnMoveEvent(MoveEvent moveEvent) - { - if (moveEvent.Sender != Owner) - { - return; - } - - if (BuckledTo == null || !BuckleOffset.HasValue) - { - return; - } - - var bucklePosition = BuckledTo.Owner.Transform.Coordinates.Offset(BuckleOffset.Value); - - if (moveEvent.NewPosition.InRange(_entityManager, bucklePosition, 0.2f)) - { - return; - } - - Moved = true; - } - - /// - /// Called when the owner is inserted or removed from a container, - /// to synchronize the state of buckling. - /// - /// The message received - private void InsertIntoContainer(ContainerModifiedMessage message) - { - if (message.Entity != Owner) - { - return; - } - - ContainerChanged = true; - } - - /// - /// Synchronizes the state of buckling depending on whether the entity - /// was inserted or removed from a container, and whether or not - /// its current strap (if there is one) has also been put into or removed - /// from the same container as well. - /// - public void Update() - { - if (BuckledTo == null) - { - return; - } - - if (Moved) - { - TryUnbuckle(Owner, true); - Moved = false; - return; - } - - if (!ContainerChanged) - { - return; - } - - var contained = ContainerHelpers.TryGetContainer(Owner, out var ownContainer); - var strapContained = ContainerHelpers.TryGetContainer(BuckledTo.Owner, out var strapContainer); - - if (contained != strapContained || ownContainer != strapContainer) - { - TryUnbuckle(Owner, true); - return; - } - - if (!contained && !strapContained) - { - ReAttach(BuckledTo); - } - - ContainerChanged = false; - } - public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); @@ -494,32 +389,21 @@ namespace Content.Server.GameObjects.Components.Buckle _unbuckleDelay = TimeSpan.FromSeconds(seconds); } - public override void Initialize() - { - base.Initialize(); - - _entityManager.EventBus.SubscribeEvent(EventSource.Local, this, InsertIntoContainer); - _entityManager.EventBus.SubscribeEvent(EventSource.Local, this, InsertIntoContainer); - } - protected override void Startup() { base.Startup(); - BuckleStatus(); + UpdateBuckleStatus(); } public override void OnRemove() { base.OnRemove(); - _entityManager.EventBus.UnsubscribeEvents(this); - BuckledTo?.Remove(this); - TryUnbuckle(Owner, true); _buckleTime = default; - BuckleStatus(); + UpdateBuckleStatus(); } public override ComponentState GetComponentState() diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs index 8e2f0c2422..c6bcb65591 100644 --- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs @@ -1,8 +1,11 @@ -using Content.Server.GameObjects.Components.Buckle; +#nullable enable +using Content.Server.GameObjects.Components.Buckle; +using Content.Server.GameObjects.Components.Strap; using Content.Server.GameObjects.EntitySystems.Click; using JetBrains.Annotations; +using Robust.Server.GameObjects.EntitySystemMessages; using Robust.Server.GameObjects.EntitySystems; -using Robust.Shared.GameObjects; +using Robust.Shared.Containers; using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Systems; @@ -17,7 +20,10 @@ namespace Content.Server.GameObjects.EntitySystems UpdatesAfter.Add(typeof(InteractionSystem)); UpdatesAfter.Add(typeof(InputSystem)); + SubscribeLocalEvent(MoveEvent); + SubscribeLocalEvent(ContainerModified); + SubscribeLocalEvent(ContainerModified); } public override void Shutdown() @@ -29,17 +35,69 @@ namespace Content.Server.GameObjects.EntitySystems private void MoveEvent(MoveEvent ev) { - if (ev.Sender.TryGetComponent(out BuckleComponent buckle)) + if (!ev.Sender.TryGetComponent(out BuckleComponent? buckle)) { - buckle.OnMoveEvent(ev); + return; + } + + var strap = buckle.BuckledTo; + + if (strap == null) + { + return; + } + + var strapPosition = strap.Owner.Transform.Coordinates.Offset(buckle.BuckleOffset); + + if (ev.NewPosition.InRange(EntityManager, strapPosition, 0.2f)) + { + return; + } + + buckle.TryUnbuckle(buckle.Owner, true); + } + + private void ContainerModified(ContainerModifiedMessage message) + { + // Not returning is necessary in case an entity has both a buckle and strap component + if (message.Entity.TryGetComponent(out BuckleComponent? buckle)) + { + ContainerModifiedReAttach(buckle, buckle.BuckledTo); + } + + if (message.Entity.TryGetComponent(out StrapComponent? strap)) + { + foreach (var buckledEntity in strap.BuckledEntities) + { + if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled)) + { + continue; + } + + ContainerModifiedReAttach(buckled, strap); + } } } - public override void Update(float frameTime) + private void ContainerModifiedReAttach(BuckleComponent buckle, StrapComponent? strap) { - foreach (var buckle in ComponentManager.EntityQuery()) + if (strap == null) { - buckle.Update(); + return; + } + + var contained = ContainerHelpers.TryGetContainer(buckle.Owner, out var ownContainer); + var strapContained = ContainerHelpers.TryGetContainer(strap.Owner, out var strapContainer); + + if (contained != strapContained || ownContainer != strapContainer) + { + buckle.TryUnbuckle(buckle.Owner, true); + return; + } + + if (!contained) + { + buckle.ReAttach(strap); } } } From a7e7f20417bb9a39f14b3c37c0b62d37a5f31760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sat, 7 Nov 2020 01:04:15 +0100 Subject: [PATCH 28/41] Remove dependency. Yeah, let's not ever again. Please. --- .../Components/Configuration/ConfigurationMenu.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Content.Client/GameObjects/Components/Configuration/ConfigurationMenu.cs b/Content.Client/GameObjects/Components/Configuration/ConfigurationMenu.cs index d236ae0202..6e0b65d9a2 100644 --- a/Content.Client/GameObjects/Components/Configuration/ConfigurationMenu.cs +++ b/Content.Client/GameObjects/Components/Configuration/ConfigurationMenu.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Namotion.Reflection; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -101,7 +100,7 @@ namespace Content.Client.GameObjects.Components.Wires { _column.Children.Clear(); _inputs.Clear(); - + foreach (var field in state.Config) { var margin = new MarginContainer @@ -142,8 +141,8 @@ namespace Content.Client.GameObjects.Components.Wires private void OnConfirm(ButtonEventArgs args) { - var config = GenerateDictionary(_inputs, "Text"); - + var config = GenerateDictionary(_inputs, "Text"); + Owner.SendConfiguration(config); Close(); } @@ -153,13 +152,13 @@ namespace Content.Client.GameObjects.Components.Wires return Owner.Validation == null || Owner.Validation.IsMatch(value); } - private Dictionary GenerateDictionary(List<(string name, TInput input)> inputs, string propertyName) where TInput : Control + private Dictionary GenerateDictionary(IEnumerable<(string name, LineEdit input)> inputs, string propertyName) { - var dictionary = new Dictionary(); + var dictionary = new Dictionary(); + foreach (var input in inputs) { - var value = input.input.TryGetPropertyValue(propertyName); - dictionary.Add(input.name, value); + dictionary.Add(input.name, input.input.Text); } return dictionary; From bf5b9ad03bc333d8893b5dbffca8821457fd9e04 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sat, 7 Nov 2020 01:15:56 +0100 Subject: [PATCH 29/41] Change cvar usages to use CVarDef and define them in CCVars (#2250) * Change cvar usages to use CVarDef and define them in CCVars * Merge fixes * Remove duplicate cvar registration --- .../Commands/ToggleOutlineCommand.cs | 12 ++-- Content.Client/EntryPoint.cs | 2 - Content.Client/Parallax/ParallaxManager.cs | 5 +- Content.Client/State/GameScreenBase.cs | 3 +- Content.Client/State/MainMenu.cs | 7 +- .../UserInterface/OptionsMenu.Graphics.cs | 38 ++++++----- .../Tests/Commands/RestartRoundTest.cs | 3 +- .../Tests/Lobby/CharacterCreationTest.cs | 4 +- .../GameObjects/EntitySystems/AI/AiSystem.cs | 8 +-- .../Atmos/AtmosDebugOverlaySystem.cs | 4 +- .../Atmos/GasTileOverlaySystem.cs | 7 +- .../GamePresets/PresetSuspicion.cs | 17 ++--- .../GameTicking/GameRules/RuleDeathMatch.cs | 3 +- .../GameTicking/GameRules/RuleSuspicion.cs | 3 +- Content.Server/GameTicking/GameTicker.cs | 10 ++- Content.Server/MoMMILink.cs | 10 ++- Content.Shared/CCVars.cs | 68 +++++++++++++++++++ .../SharedPlayerInputMoverComponent.cs | 2 +- .../EntitySystems/SharedMoverSystem.cs | 2 - 19 files changed, 136 insertions(+), 72 deletions(-) diff --git a/Content.Client/Commands/ToggleOutlineCommand.cs b/Content.Client/Commands/ToggleOutlineCommand.cs index a96c9e40a5..ca96762eac 100644 --- a/Content.Client/Commands/ToggleOutlineCommand.cs +++ b/Content.Client/Commands/ToggleOutlineCommand.cs @@ -1,3 +1,4 @@ +using Content.Shared; using Robust.Client.Interfaces.Console; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.IoC; @@ -14,10 +15,13 @@ namespace Content.Client.Commands public bool Execute(IDebugConsole console, params string[] args) { - var _configurationManager = IoCManager.Resolve(); - var old = _configurationManager.GetCVar("outline.enabled"); - _configurationManager.SetCVar("outline.enabled", !old); - console.AddLine($"Draw outlines set to: {_configurationManager.GetCVar("outline.enabled")}"); + var configurationManager = IoCManager.Resolve(); + var cvar = CCVars.OutlineEnabled; + var old = configurationManager.GetCVar(cvar); + + configurationManager.SetCVar(cvar, !old); + console.AddLine($"Draw outlines set to: {configurationManager.GetCVar(cvar)}"); + return false; } } diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 4eab611fc2..ffa05119bc 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -101,8 +101,6 @@ namespace Content.Client { IoCManager.Resolve().CreateNewMapEntity(MapId.Nullspace); }; - - _configurationManager.RegisterCVar("outline.enabled", true); } /// diff --git a/Content.Client/Parallax/ParallaxManager.cs b/Content.Client/Parallax/ParallaxManager.cs index 441dbcaf08..a58c7710e9 100644 --- a/Content.Client/Parallax/ParallaxManager.cs +++ b/Content.Client/Parallax/ParallaxManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Content.Client.Interfaces.Parallax; +using Content.Shared; using Nett; using Robust.Client.Graphics; using Robust.Client.Interfaces.ResourceManagement; @@ -34,12 +35,12 @@ namespace Content.Client.Parallax public async void LoadParallax() { - if (!_configurationManager.GetCVar("parallax.enabled")) + if (!_configurationManager.GetCVar(CCVars.ParallaxEnabled)) { return; } - var debugParallax = _configurationManager.GetCVar("parallax.debug"); + var debugParallax = _configurationManager.GetCVar(CCVars.ParallaxDebug); string contents; TomlTable table; // Load normal config into memory diff --git a/Content.Client/State/GameScreenBase.cs b/Content.Client/State/GameScreenBase.cs index 3e0fa48f65..00e836ffd0 100644 --- a/Content.Client/State/GameScreenBase.cs +++ b/Content.Client/State/GameScreenBase.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Linq; using Content.Client.GameObjects.Components; using Content.Client.Utility; +using Content.Shared; using Robust.Client.GameObjects.EntitySystems; using Robust.Client.Interfaces.GameObjects; using Robust.Client.Interfaces.Graphics.ClientEye; @@ -71,7 +72,7 @@ namespace Content.Client.State } InteractionOutlineComponent outline; - if(!ConfigurationManager.GetCVar("outline.enabled")) + if(!ConfigurationManager.GetCVar(CCVars.OutlineEnabled)) { if(entityToClick != null && entityToClick.TryGetComponent(out outline)) { diff --git a/Content.Client/State/MainMenu.cs b/Content.Client/State/MainMenu.cs index 0d709c074d..b5f7503f49 100644 --- a/Content.Client/State/MainMenu.cs +++ b/Content.Client/State/MainMenu.cs @@ -8,6 +8,7 @@ using Robust.Client.Interfaces.UserInterface; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; @@ -111,10 +112,10 @@ namespace Content.Client.State return; } - var configName = _configurationManager.GetCVar("player.name"); + var configName = _configurationManager.GetCVar(CVars.PlayerName); if (_mainMenuControl.UserNameBox.Text != configName) { - _configurationManager.SetCVar("player.name", inputName); + _configurationManager.SetCVar(CVars.PlayerName, inputName); _configurationManager.SaveToFile(); } @@ -248,7 +249,7 @@ namespace Content.Client.State vBox.AddChild(userNameHBox); userNameHBox.AddChild(new Label {Text = "Username:"}); - var currentUserName = _configurationManager.GetCVar("player.name"); + var currentUserName = _configurationManager.GetCVar(CVars.PlayerName); UserNameBox = new LineEdit { Text = currentUserName, PlaceHolder = "Username", diff --git a/Content.Client/UserInterface/OptionsMenu.Graphics.cs b/Content.Client/UserInterface/OptionsMenu.Graphics.cs index 0e9861d358..7642cd3a90 100644 --- a/Content.Client/UserInterface/OptionsMenu.Graphics.cs +++ b/Content.Client/UserInterface/OptionsMenu.Graphics.cs @@ -1,7 +1,9 @@ -using Robust.Client.Graphics; +using Content.Shared; +using Robust.Client.Graphics; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.IoC; using Robust.Shared.Localization; @@ -121,7 +123,7 @@ namespace Content.Client.UserInterface }); ApplyButton.OnPressed += OnApplyButtonPressed; - VSyncCheckBox.Pressed = _cfg.GetCVar("display.vsync"); + VSyncCheckBox.Pressed = _cfg.GetCVar(CVars.DisplayVSync); FullscreenCheckBox.Pressed = ConfigIsFullscreen; LightingPresetOption.SelectId(GetConfigLightingQuality()); _uiScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale)); @@ -137,11 +139,11 @@ namespace Content.Client.UserInterface private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args) { - _cfg.SetCVar("display.vsync", VSyncCheckBox.Pressed); + _cfg.SetCVar(CVars.DisplayVSync, VSyncCheckBox.Pressed); SetConfigLightingQuality(LightingPresetOption.SelectedId); - _cfg.SetCVar("display.windowmode", + _cfg.SetCVar(CVars.DisplayWindowMode, (int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed)); - _cfg.SetCVar("display.uiScale", UIScaleOptions[_uiScaleOption.SelectedId]); + _cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[_uiScaleOption.SelectedId]); _cfg.SaveToFile(); UpdateApplyButton(); } @@ -159,7 +161,7 @@ namespace Content.Client.UserInterface private void UpdateApplyButton() { - var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar("display.vsync"); + var isVSyncSame = VSyncCheckBox.Pressed == _cfg.GetCVar(CVars.DisplayVSync); var isFullscreenSame = FullscreenCheckBox.Pressed == ConfigIsFullscreen; var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality(); var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[_uiScaleOption.SelectedId], ConfigUIScale); @@ -167,14 +169,14 @@ namespace Content.Client.UserInterface } private bool ConfigIsFullscreen => - _cfg.GetCVar("display.windowmode") == (int) WindowMode.Fullscreen; + _cfg.GetCVar(CVars.DisplayWindowMode) == (int) WindowMode.Fullscreen; - private float ConfigUIScale => _cfg.GetCVar("display.uiScale"); + private float ConfigUIScale => _cfg.GetCVar(CVars.DisplayUIScale); private int GetConfigLightingQuality() { - var val = _cfg.GetCVar("display.lightmapdivider"); - var soft = _cfg.GetCVar("display.softshadows"); + var val = _cfg.GetCVar(CVars.DisplayLightMapDivider); + var soft = _cfg.GetCVar(CVars.DisplaySoftShadows); if (val >= 8) { return 0; @@ -198,20 +200,20 @@ namespace Content.Client.UserInterface switch (value) { case 0: - _cfg.SetCVar("display.lightmapdivider", 8); - _cfg.SetCVar("display.softshadows", false); + _cfg.SetCVar(CVars.DisplayLightMapDivider, 8); + _cfg.SetCVar(CVars.DisplaySoftShadows, false); break; case 1: - _cfg.SetCVar("display.lightmapdivider", 2); - _cfg.SetCVar("display.softshadows", false); + _cfg.SetCVar(CVars.DisplayLightMapDivider, 2); + _cfg.SetCVar(CVars.DisplaySoftShadows, false); break; case 2: - _cfg.SetCVar("display.lightmapdivider", 2); - _cfg.SetCVar("display.softshadows", true); + _cfg.SetCVar(CVars.DisplayLightMapDivider, 2); + _cfg.SetCVar(CVars.DisplaySoftShadows, true); break; case 3: - _cfg.SetCVar("display.lightmapdivider", 1); - _cfg.SetCVar("display.softshadows", true); + _cfg.SetCVar(CVars.DisplayLightMapDivider, 1); + _cfg.SetCVar(CVars.DisplaySoftShadows, true); break; } } diff --git a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs index 83e4d111bb..aa9c2cdc54 100644 --- a/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RestartRoundTest.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Content.Server.GameTicking; using Content.Server.Interfaces.GameTicking; +using Content.Shared; using NUnit.Framework; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.GameObjects; @@ -31,7 +32,7 @@ namespace Content.IntegrationTests.Tests.Commands server.Assert(() => { - configManager.SetCVar("game.lobbyenabled", lobbyEnabled); + configManager.SetCVar(CCVars.GameLobbyEnabled, lobbyEnabled); Assert.That(gameTicker.RunLevel, Is.EqualTo(GameRunLevel.InRound)); diff --git a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs index afc4cbd6a9..218e6a85b6 100644 --- a/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs +++ b/Content.IntegrationTests/Tests/Lobby/CharacterCreationTest.cs @@ -38,9 +38,7 @@ namespace Content.IntegrationTests.Tests.Lobby await server.WaitAssertion(() => { - var lobbyCvar = CCVars.GameLobbyEnabled; - serverConfig.SetCVar(lobbyCvar.Name, true); - + serverConfig.SetCVar(CCVars.GameLobbyEnabled, true); serverTicker.RestartRound(); }); diff --git a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs index f951020547..cf99ce1086 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Movement; +using Content.Shared; using Content.Shared.GameObjects.Components.Movement; using JetBrains.Annotations; using Robust.Server.AI; @@ -42,7 +43,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI public override void Initialize() { base.Initialize(); - _configurationManager.RegisterCVar("ai.maxupdates", 64); SubscribeLocalEvent(HandleAiSleep); var processors = _reflectionManager.GetAllChildren(); @@ -58,7 +58,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI /// public override void Update(float frameTime) { - var cvarMaxUpdates = _configurationManager.GetCVar("ai.maxupdates"); + var cvarMaxUpdates = _configurationManager.GetCVar(CCVars.AIMaxUpdates); if (cvarMaxUpdates <= 0) return; @@ -75,7 +75,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI break; case false: _awakeAi.Add(message.Processor); - + if (_awakeAi.Count > cvarMaxUpdates) { Logger.Warning($"AI limit exceeded: {_awakeAi.Count} / {cvarMaxUpdates}"); @@ -101,7 +101,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI toRemove.Add(processor); continue; } - + processor.Update(frameTime); count++; } diff --git a/Content.Server/GameObjects/EntitySystems/Atmos/AtmosDebugOverlaySystem.cs b/Content.Server/GameObjects/EntitySystems/Atmos/AtmosDebugOverlaySystem.cs index e7b0380d1a..e40ce9ce3a 100644 --- a/Content.Server/GameObjects/EntitySystems/Atmos/AtmosDebugOverlaySystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Atmos/AtmosDebugOverlaySystem.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using Content.Server.GameObjects.Components.Atmos; using Content.Server.Atmos; +using Content.Shared; using Content.Shared.Atmos; using Content.Shared.GameObjects.EntitySystems.Atmos; using JetBrains.Annotations; @@ -47,7 +48,6 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos _atmosphereSystem = Get(); _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; - _configManager.RegisterCVar("net.atmosdbgoverlaytickrate", 3.0f); } public override void Shutdown() @@ -89,7 +89,7 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos public override void Update(float frameTime) { AccumulatedFrameTime += frameTime; - _updateCooldown = 1 / _configManager.GetCVar("net.atmosdbgoverlaytickrate"); + _updateCooldown = 1 / _configManager.GetCVar(CCVars.NetAtmosDebugOverlayTickRate); if (AccumulatedFrameTime < _updateCooldown) { diff --git a/Content.Server/GameObjects/EntitySystems/Atmos/GasTileOverlaySystem.cs b/Content.Server/GameObjects/EntitySystems/Atmos/GasTileOverlaySystem.cs index 461c45cd47..c26bbc6320 100644 --- a/Content.Server/GameObjects/EntitySystems/Atmos/GasTileOverlaySystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Atmos/GasTileOverlaySystem.cs @@ -4,12 +4,14 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using Content.Server.GameObjects.Components.Atmos; +using Content.Shared; using Content.Shared.Atmos; using Content.Shared.GameObjects.EntitySystems.Atmos; using Content.Shared.GameTicking; using JetBrains.Annotations; using Robust.Server.Interfaces.Player; using Robust.Server.Player; +using Robust.Shared; using Robust.Shared.Enums; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.GameObjects; @@ -65,7 +67,6 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos _atmosphereSystem = Get(); _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; _mapManager.OnGridRemoved += OnGridRemoved; - _configManager.RegisterCVar("net.gasoverlaytickrate", 3.0f); } public override void Shutdown() @@ -228,14 +229,14 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos public override void Update(float frameTime) { AccumulatedFrameTime += frameTime; - _updateCooldown = 1 / _configManager.GetCVar("net.gasoverlaytickrate"); + _updateCooldown = 1 / _configManager.GetCVar(CCVars.NetGasOverlayTickRate); if (AccumulatedFrameTime < _updateCooldown) { return; } - _updateRange = _configManager.GetCVar("net.maxupdaterange") + RangeOffset; + _updateRange = _configManager.GetCVar(CVars.NetMaxUpdateRange) + RangeOffset; // TODO: So in the worst case scenario we still have to send a LOT of tile data per tick if there's a fire. // If we go with say 15 tile radius then we have up to 900 tiles to update per tick. diff --git a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs index 9021cd4fef..3b497d8938 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs @@ -9,6 +9,7 @@ using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; using Content.Server.Mobs.Roles.Suspicion; using Content.Server.Players; +using Content.Shared; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.PDA; using Content.Shared.Roles; @@ -44,20 +45,12 @@ namespace Content.Server.GameTicking.GamePresets private static string TraitorID = "SuspicionTraitor"; private static string InnocentID = "SuspicionInnocent"; - public static void RegisterCVars(IConfigurationManager cfg) - { - cfg.RegisterCVar("game.suspicion_min_players", 5); - cfg.RegisterCVar("game.suspicion_min_traitors", 2); - cfg.RegisterCVar("game.suspicion_players_per_traitor", 5); - cfg.RegisterCVar("game.suspicion_starting_balance", 20); - } - public override bool Start(IReadOnlyList readyPlayers, bool force = false) { - MinPlayers = _cfg.GetCVar("game.suspicion_min_players"); - MinTraitors = _cfg.GetCVar("game.suspicion_min_traitors"); - PlayersPerTraitor = _cfg.GetCVar("game.suspicion_players_per_traitor"); - TraitorStartingBalance = _cfg.GetCVar("game.suspicion_starting_balance"); + MinPlayers = _cfg.GetCVar(CCVars.GameSuspicionMinPlayers); + MinTraitors = _cfg.GetCVar(CCVars.GameSuspicionMinTraitors); + PlayersPerTraitor = _cfg.GetCVar(CCVars.GameSuspicionPlayersPerTraitor); + TraitorStartingBalance = _cfg.GetCVar(CCVars.GameSuspicionStartingBalance); if (!force && readyPlayers.Count < MinPlayers) { diff --git a/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs index 03874a6d99..97d0dfb0a8 100644 --- a/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs +++ b/Content.Server/GameTicking/GameRules/RuleDeathMatch.cs @@ -2,6 +2,7 @@ using System.Threading; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; +using Content.Shared; using Content.Shared.GameObjects.Components.Damage; using Robust.Server.Interfaces.Player; using Robust.Server.Player; @@ -56,7 +57,7 @@ namespace Content.Server.GameTicking.GameRules { _checkTimerCancel = null; - if (!_cfg.GetCVar("game.enablewin")) + if (!_cfg.GetCVar(CCVars.GameLobbyEnableWin)) return; IPlayerSession winner = null; diff --git a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs index a6c33264fc..8f77126c78 100644 --- a/Content.Server/GameTicking/GameRules/RuleSuspicion.cs +++ b/Content.Server/GameTicking/GameRules/RuleSuspicion.cs @@ -6,6 +6,7 @@ using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; using Content.Server.Mobs.Roles.Suspicion; using Content.Server.Players; +using Content.Shared; using Content.Shared.GameObjects.Components.Damage; using Robust.Server.GameObjects.EntitySystems; using Robust.Server.Interfaces.Player; @@ -58,7 +59,7 @@ namespace Content.Server.GameTicking.GameRules private void _checkWinConditions() { - if (!_cfg.GetCVar("game.enablewin")) + if (!_cfg.GetCVar(CCVars.GameLobbyEnableWin)) return; var traitorsAlive = 0; diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index b6d396e95e..9e2a23b00b 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -88,7 +88,7 @@ namespace Content.Server.GameTicking [ViewVariables] private bool DisallowLateJoin { get; set; } = false; - [ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar("game.lobbyenabled"); + [ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar(CCVars.GameLobbyEnabled); [ViewVariables] private bool _updateOnRoundEnd; private CancellationTokenSource _updateShutdownCts; @@ -119,7 +119,7 @@ namespace Content.Server.GameTicking public event Action OnRuleAdded; private TimeSpan LobbyDuration => - TimeSpan.FromSeconds(_configurationManager.GetCVar("game.lobbyduration")); + TimeSpan.FromSeconds(_configurationManager.GetCVar(CCVars.GameLobbyDuration)); public override void Initialize() { @@ -127,8 +127,6 @@ namespace Content.Server.GameTicking DebugTools.Assert(!_initialized); - PresetSuspicion.RegisterCVars(_configurationManager); - _netManager.RegisterNetMessage(nameof(MsgTickerJoinLobby)); _netManager.RegisterNetMessage(nameof(MsgTickerJoinGame)); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyStatus)); @@ -286,9 +284,9 @@ namespace Content.Server.GameTicking if (!preset.Start(assignedJobs.Keys.ToList(), force)) { - if (_configurationManager.GetCVar("game.fallbackenabled")) + if (_configurationManager.GetCVar(CCVars.GameLobbyFallbackEnabled)) { - SetStartPreset(_configurationManager.GetCVar("game.fallbackpreset")); + SetStartPreset(_configurationManager.GetCVar(CCVars.GameLobbyFallbackPreset)); var newPreset = MakeGamePreset(profiles); _chatManager.DispatchServerAnnouncement( $"Failed to start {preset.ModeTitle} mode! Defaulting to {newPreset.ModeTitle}..."); diff --git a/Content.Server/MoMMILink.cs b/Content.Server/MoMMILink.cs index 0ea3befd25..692dcd59c5 100644 --- a/Content.Server/MoMMILink.cs +++ b/Content.Server/MoMMILink.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; +using Content.Shared; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using Robust.Server.Interfaces.ServerStatus; @@ -27,9 +28,6 @@ namespace Content.Server void IPostInjectInit.PostInject() { - _configurationManager.RegisterCVar("status.mommiurl", null); - _configurationManager.RegisterCVar("status.mommipassword", null); - _statusHost.AddHandler(_handleChatPost); } @@ -46,8 +44,8 @@ namespace Content.Server private async Task _sendMessageInternal(string type, object messageObject) { - var url = _configurationManager.GetCVar("status.mommiurl"); - var password = _configurationManager.GetCVar("status.mommipassword"); + var url = _configurationManager.GetCVar(CCVars.StatusMoMMIUrl); + var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword); if (string.IsNullOrWhiteSpace(url)) { return; @@ -83,7 +81,7 @@ namespace Content.Server return false; } - var password = _configurationManager.GetCVar("status.mommipassword"); + var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword); OOCPostMessage message = null; try diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs index 94c17dc378..ae6fde26bf 100644 --- a/Content.Shared/CCVars.cs +++ b/Content.Shared/CCVars.cs @@ -7,6 +7,21 @@ namespace Content.Shared [CVarDefs] public sealed class CCVars : CVars { + /* + * Status + */ + + public static readonly CVarDef StatusMoMMIUrl = + CVarDef.Create("status.mommiurl", null); + + public static readonly CVarDef StatusMoMMIPassword = + CVarDef.Create("status.mommipassword", null); + + + /* + * Game + */ + public static readonly CVarDef EventsEnabled = CVarDef.Create("events.enabled", false, CVar.ARCHIVE | CVar.SERVERONLY); @@ -37,6 +52,21 @@ namespace Content.Shared public static readonly CVarDef GamePersistGuests = CVarDef.Create("game.persistguests", true, CVar.ARCHIVE | CVar.SERVERONLY); + public static readonly CVarDef GameSuspicionMinPlayers = + CVarDef.Create("game.suspicion_min_players", 5); + + public static readonly CVarDef GameSuspicionMinTraitors = + CVarDef.Create("game.suspicion_min_traitors", 2); + + public static readonly CVarDef GameSuspicionPlayersPerTraitor = + CVarDef.Create("game.suspicion_players_per_traitor", 5); + + public static readonly CVarDef GameSuspicionStartingBalance = + CVarDef.Create("game.suspicion_starting_balance", 20); + + public static readonly CVarDef GameDiagonalMovement = + CVarDef.Create("game.diagonalmovement", true, CVar.ARCHIVE); + /* * Database stuff @@ -62,5 +92,43 @@ namespace Content.Shared public static readonly CVarDef DatabasePgPassword = CVarDef.Create("database.pg_password", "", CVar.SERVERONLY); + + + /* + * Outline + */ + + public static readonly CVarDef OutlineEnabled = + CVarDef.Create("outline.enabled", true, CVar.CLIENTONLY); + + + /* + * Parallax + */ + + public static readonly CVarDef ParallaxEnabled = + CVarDef.Create("parallax.enabled", true); + + public static readonly CVarDef ParallaxDebug = + CVarDef.Create("parallax.debug", true); + + + /* + * AI + */ + + public static readonly CVarDef AIMaxUpdates = + CVarDef.Create("ai.maxupdates", 64); + + + /* + * Net + */ + + public static readonly CVarDef NetAtmosDebugOverlayTickRate = + CVarDef.Create("net.atmosdbgoverlaytickrate", 3.0f); + + public static readonly CVarDef NetGasOverlayTickRate = + CVarDef.Create("net.gasoverlaytickrate", 3.0f); } } diff --git a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs index 14554be489..a1d2d659e8 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedPlayerInputMoverComponent.cs @@ -139,7 +139,7 @@ namespace Content.Shared.GameObjects.Components.Movement /// Whether or not the player can move diagonally. /// [ViewVariables] - public bool DiagonalMovementEnabled => _configurationManager.GetCVar("game.diagonalmovement"); + public bool DiagonalMovementEnabled => _configurationManager.GetCVar(CCVars.GameDiagonalMovement); /// public override void OnAdd() diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index c534d53ef4..a1cb02fe6a 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -41,8 +41,6 @@ namespace Content.Shared.GameObjects.EntitySystems .Bind(EngineKeyFunctions.MoveDown, moveDownCmdHandler) .Bind(EngineKeyFunctions.Walk, new WalkInputCmdHandler()) .Register(); - - _configurationManager.RegisterCVar("game.diagonalmovement", true, CVar.ARCHIVE); } /// From 54e0747577c7c965d5aa991811b79f46caccf340 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Sat, 7 Nov 2020 14:44:47 +1100 Subject: [PATCH 30/41] Fix crematorium visualizer crash (#2513) * Fix crematorium visualizer crash * Also morgue Co-authored-by: Metal Gear Sloth --- .../Components/Morgue/CrematoriumVisualizer.cs | 14 ++++++++------ .../Components/Morgue/MorgueVisualizer.cs | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Content.Client/GameObjects/Components/Morgue/CrematoriumVisualizer.cs b/Content.Client/GameObjects/Components/Morgue/CrematoriumVisualizer.cs index b7b5b9d8c8..861cb577a0 100644 --- a/Content.Client/GameObjects/Components/Morgue/CrematoriumVisualizer.cs +++ b/Content.Client/GameObjects/Components/Morgue/CrematoriumVisualizer.cs @@ -44,12 +44,14 @@ namespace Content.Client.GameObjects.Components.Storage if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return; - sprite.LayerSetState( - CrematoriumVisualLayers.Base, - component.GetData(MorgueVisuals.Open) - ? _stateOpen - : _stateClosed - ); + if (component.TryGetData(MorgueVisuals.Open, out bool open)) + { + sprite.LayerSetState(CrematoriumVisualLayers.Base, open ? _stateOpen : _stateClosed); + } + else + { + sprite.LayerSetState(CrematoriumVisualLayers.Base, _stateClosed); + } var lightState = ""; if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents; diff --git a/Content.Client/GameObjects/Components/Morgue/MorgueVisualizer.cs b/Content.Client/GameObjects/Components/Morgue/MorgueVisualizer.cs index 9f0a10305e..25747c1a36 100644 --- a/Content.Client/GameObjects/Components/Morgue/MorgueVisualizer.cs +++ b/Content.Client/GameObjects/Components/Morgue/MorgueVisualizer.cs @@ -49,12 +49,14 @@ namespace Content.Client.GameObjects.Components.Storage if (!component.Owner.TryGetComponent(out ISpriteComponent? sprite)) return; - sprite.LayerSetState( - MorgueVisualLayers.Base, - component.GetData(MorgueVisuals.Open) - ? _stateOpen - : _stateClosed - ); + if (component.TryGetData(MorgueVisuals.Open, out bool open)) + { + sprite.LayerSetState(MorgueVisualLayers.Base, open ? _stateOpen : _stateClosed); + } + else + { + sprite.LayerSetState(MorgueVisualLayers.Base, _stateClosed); + } var lightState = ""; if (component.TryGetData(MorgueVisuals.HasContents, out bool hasContents) && hasContents) lightState = _lightContents; From 50f03a5b17ab44e45df92bd455c52ad7b3758535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= Date: Sat, 7 Nov 2020 23:58:33 +0100 Subject: [PATCH 31/41] Fix firelock occlusion. --- .../GameObjects/Components/Atmos/FirelockComponent.cs | 5 ----- .../Prototypes/Entities/Constructible/Doors/firelock.yml | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs index 4584bec9c4..5724e64a4c 100644 --- a/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FirelockComponent.cs @@ -44,11 +44,6 @@ namespace Content.Server.GameObjects.Components.Atmos AutoClose = false; Safety = false; - if (Occludes && Owner.TryGetComponent(out OccluderComponent occluder)) - { - occluder.Enabled = false; - } - State = DoorState.Open; SetAppearance(DoorVisualState.Open); } diff --git a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml index 58b0c499ee..3da88aa3f5 100644 --- a/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml +++ b/Resources/Prototypes/Entities/Constructible/Doors/firelock.yml @@ -24,6 +24,7 @@ map: ["enum.WiresVisualLayers.MaintenancePanel"] - type: Physics + on: false shapes: - !type:PhysShapeAabb bounds: "-0.49,-0.49,0.49,0.49" # don't want this colliding with walls or they won't close @@ -54,6 +55,7 @@ - type: Airtight fixVacuum: true - type: Occluder + enabled: false - type: SnapGrid offset: Center placement: @@ -80,8 +82,6 @@ - type: Firelock occludes: false canCrush: false - - type: Occluder - enabled: false - type: Sprite sprite: Constructible/Structures/Doors/edge_door_hazard.rsi - type: Airtight From c580423f419b0087d1af93f89e2de4741d9eefac Mon Sep 17 00:00:00 2001 From: Remie Richards Date: Sun, 8 Nov 2020 00:10:55 +0000 Subject: [PATCH 32/41] Fixes. Can no longer open while cooking. Can no longer cook while open. (#2521) --- .../Morgue/CrematoriumEntityStorageComponent.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs index 879fd4d5b5..7b9b6a311b 100644 --- a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs @@ -3,6 +3,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.GameObjects.Components.Morgue; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; +using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.GameObjects; @@ -52,6 +53,16 @@ namespace Content.Server.GameObjects.Components.Morgue } } + public override bool CanOpen(IEntity user, bool silent = false) + { + if (Cooking) + { + if (!silent) Owner.PopupMessage(user, Loc.GetString("Safety first, not while it's active!")); + return false; + } + return base.CanOpen(user, silent); + } + public void Cremate() { if (Cooking) return; @@ -77,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Morgue var ash = Owner.EntityManager.SpawnEntity("Ash", Owner.Transform.Coordinates); Contents.Insert(ash); } - + TryOpenStorage(Owner); EntitySystem.Get().PlayFromEntity("/Audio/Machines/ding.ogg", Owner); @@ -89,7 +100,7 @@ namespace Content.Server.GameObjects.Components.Morgue { protected override void GetData(IEntity user, CrematoriumEntityStorageComponent component, VerbData data) { - if (!ActionBlockerSystem.CanInteract(user) || component.Cooking) + if (!ActionBlockerSystem.CanInteract(user) || component.Cooking || component.Open) { data.Visibility = VerbVisibility.Invisible; return; From 4a6d0ae5a480cf6414aec18deff026f85c1b0f4c Mon Sep 17 00:00:00 2001 From: Swept Date: Sun, 8 Nov 2020 01:40:49 +0000 Subject: [PATCH 33/41] More belts and welders (#2453) * Adds sprites * Added prototypes * Adds experimental and mini welder * Adds welder to CE's belt * Lazily filled out the belts * Added to spawn jobs * Merge branch 'master' of https://github.com/space-wizards/space-station-14 into pr/2453 * Update Resources/Prototypes/Entities/Objects/Tools/welders.yml Co-authored-by: DrSmugleaf Co-authored-by: DrSmugleaf --- Resources/Prototypes/Catalog/Fills/belt.yml | 25 -- .../Entities/Clothing/Belt/belts.yml | 179 +++++++++++-- .../Entities/Clothing/Belt/filled_belts.yml | 65 +++++ .../Entities/Objects/Tools/tools.yml | 34 --- .../Entities/Objects/Tools/welders.yml | 77 ++++++ .../Roles/Jobs/Civilian/janitor.yml | 1 + .../Roles/Jobs/Engineering/chief_engineer.yml | 2 +- .../Jobs/Medical/chief_medical_officer.yml | 1 + .../Roles/Jobs/Medical/medical_doctor.yml | 1 + .../Roles/Jobs/Security/head_of_security.yml | 1 + .../Roles/Jobs/Security/security_officer.yml | 1 + .../Prototypes/Roles/Jobs/Security/warden.yml | 1 + .../Belt/assault.rsi/equipped-BELT.png | Bin 0 -> 363 bytes .../Clothing/Belt/assault.rsi/icon.png | Bin 0 -> 382 bytes .../Clothing/Belt/assault.rsi/inhand-left.png | Bin 0 -> 341 bytes .../Belt/assault.rsi/inhand-right.png | Bin 0 -> 368 bytes .../Clothing/Belt/assault.rsi/meta.json | 74 ++++++ .../Belt/bandolier.rsi/equipped-BELT.png | Bin 0 -> 376 bytes .../Clothing/Belt/bandolier.rsi/icon.png | Bin 0 -> 342 bytes .../Belt/bandolier.rsi/inhand-left.png | Bin 0 -> 311 bytes .../Belt/bandolier.rsi/inhand-right.png | Bin 0 -> 309 bytes .../Clothing/Belt/bandolier.rsi/meta.json | 74 ++++++ .../Belt/belt_icon_overlay.rsi/crowbar.png | Bin 0 -> 176 bytes .../belt_icon_overlay.rsi/crowbar_brass.png | Bin 0 -> 206 bytes .../belt_icon_overlay.rsi/crowbar_large.png | Bin 0 -> 176 bytes .../belt_icon_overlay.rsi/crowbar_red.png | Bin 0 -> 186 bytes .../belt_icon_overlay.rsi/cutters_brass.png | Bin 0 -> 203 bytes .../belt_icon_overlay.rsi/cutters_red.png | Bin 0 -> 207 bytes .../belt_icon_overlay.rsi/cutters_yellow.png | Bin 0 -> 212 bytes .../Belt/belt_icon_overlay.rsi/drill_bolt.png | Bin 0 -> 223 bytes .../belt_icon_overlay.rsi/drill_screw.png | Bin 0 -> 223 bytes .../Belt/belt_icon_overlay.rsi/flashbang.png | Bin 0 -> 228 bytes .../belt_icon_overlay.rsi/jaws_cutter.png | Bin 0 -> 271 bytes .../Belt/belt_icon_overlay.rsi/jaws_pry.png | Bin 0 -> 271 bytes .../Belt/belt_icon_overlay.rsi/meta.json | 236 ++++++++++++++++++ .../Belt/belt_icon_overlay.rsi/multitool.png | Bin 0 -> 141 bytes .../belt_icon_overlay.rsi/multitool_red.png | Bin 0 -> 141 bytes .../multitool_yellow.png | Bin 0 -> 141 bytes .../belt_icon_overlay.rsi/screwdriver.png | Bin 0 -> 145 bytes .../screwdriver_brass.png | Bin 0 -> 172 bytes .../screwdriver_head.png | Bin 0 -> 110 bytes .../screwdriver_nuke.png | Bin 0 -> 172 bytes .../Belt/belt_icon_overlay.rsi/stunbaton.png | Bin 0 -> 210 bytes .../stunbaton_active.png | Bin 0 -> 210 bytes .../stunbaton_nocell.png | Bin 0 -> 210 bytes .../Belt/belt_icon_overlay.rsi/wrench.png | Bin 0 -> 180 bytes .../belt_icon_overlay.rsi/wrench_brass.png | Bin 0 -> 168 bytes .../belt_icon_overlay.rsi/wrench_medical.png | Bin 0 -> 180 bytes .../Belt/belt_mob_overlay.rsi/baton.png | Bin 0 -> 196 bytes .../Belt/belt_mob_overlay.rsi/gun.png | Bin 0 -> 147 bytes .../Belt/belt_mob_overlay.rsi/handcuff.png | Bin 0 -> 148 bytes .../Belt/belt_mob_overlay.rsi/injector.png | Bin 0 -> 275 bytes .../Belt/belt_mob_overlay.rsi/meta.json | 101 ++++++++ .../Belt/belt_mob_overlay.rsi/tank.png | Bin 0 -> 327 bytes .../Belt/belt_utility.rsi/equipped-BELT.png | Bin 294 -> 0 bytes .../Clothing/Belt/belt_utility.rsi/meta.json | 1 - .../Clothing/Belt/ce.rsi/equipped-BELT.png | Bin 0 -> 459 bytes .../Textures/Clothing/Belt/ce.rsi/icon.png | Bin 0 -> 433 bytes .../Clothing/Belt/ce.rsi/inhand-left.png | Bin 0 -> 333 bytes .../Clothing/Belt/ce.rsi/inhand-right.png | Bin 0 -> 334 bytes .../Textures/Clothing/Belt/ce.rsi/meta.json | 74 ++++++ .../Belt/champion.rsi/equipped-BELT.png | Bin 0 -> 510 bytes .../Clothing/Belt/champion.rsi/icon.png | Bin 0 -> 580 bytes .../Belt/champion.rsi/inhand-left.png | Bin 0 -> 336 bytes .../Belt/champion.rsi/inhand-right.png | Bin 0 -> 360 bytes .../Clothing/Belt/champion.rsi/meta.json | 74 ++++++ .../Belt/holster.rsi/equipped-BELT.png | Bin 0 -> 351 bytes .../Clothing/Belt/holster.rsi/icon.png | Bin 0 -> 295 bytes .../Clothing/Belt/holster.rsi/inhand-left.png | Bin 0 -> 247 bytes .../Belt/holster.rsi/inhand-right.png | Bin 0 -> 234 bytes .../Clothing/Belt/holster.rsi/meta.json | 74 ++++++ .../Belt/janitor.rsi/equipped-BELT.png | Bin 0 -> 369 bytes .../Clothing/Belt/janitor.rsi/icon.png | Bin 0 -> 495 bytes .../Clothing/Belt/janitor.rsi/inhand-left.png | Bin 0 -> 354 bytes .../Belt/janitor.rsi/inhand-right.png | Bin 0 -> 345 bytes .../Clothing/Belt/janitor.rsi/meta.json | 74 ++++++ .../Belt/medical.rsi/equipped-BELT.png | Bin 0 -> 342 bytes .../Clothing/Belt/medical.rsi/icon.png | Bin 0 -> 387 bytes .../Clothing/Belt/medical.rsi/inhand-left.png | Bin 0 -> 356 bytes .../Belt/medical.rsi/inhand-right.png | Bin 0 -> 336 bytes .../Clothing/Belt/medical.rsi/meta.json | 74 ++++++ .../militarywebbing.rsi/equipped-BELT.png | Bin 0 -> 721 bytes .../Belt/militarywebbing.rsi/icon.png | Bin 0 -> 376 bytes .../Belt/militarywebbing.rsi/inhand-left.png | Bin 0 -> 440 bytes .../Belt/militarywebbing.rsi/inhand-right.png | Bin 0 -> 451 bytes .../Belt/militarywebbing.rsi/meta.json | 74 ++++++ .../Belt/security.rsi/equipped-BELT.png | Bin 0 -> 366 bytes .../Clothing/Belt/security.rsi/icon.png | Bin 0 -> 452 bytes .../Belt/security.rsi/inhand-left.png | Bin 0 -> 341 bytes .../Belt/security.rsi/inhand-right.png | Bin 0 -> 368 bytes .../Clothing/Belt/security.rsi/meta.json | 74 ++++++ .../securitywebbing.rsi/equipped-BELT.png | Bin 0 -> 867 bytes .../Belt/securitywebbing.rsi/icon.png | Bin 0 -> 487 bytes .../Belt/securitywebbing.rsi/inhand-left.png | Bin 0 -> 440 bytes .../Belt/securitywebbing.rsi/inhand-right.png | Bin 0 -> 451 bytes .../Belt/securitywebbing.rsi/meta.json | 74 ++++++ .../Clothing/Belt/sheath.rsi/meta.json | 65 +++++ .../Belt/sheath.rsi/sheath-equipped-BELT.png | Bin 0 -> 315 bytes .../sheath.rsi/sheath-sabre-equipped-BELT.png | Bin 0 -> 500 bytes .../Clothing/Belt/sheath.rsi/sheath-sabre.png | Bin 0 -> 418 bytes .../Clothing/Belt/sheath.rsi/sheath.png | Bin 0 -> 277 bytes .../Belt/suspenders.rsi/inhand-left.png | Bin 0 -> 362 bytes .../Belt/suspenders.rsi/inhand-right.png | Bin 0 -> 371 bytes .../Clothing/Belt/suspenders.rsi/meta.json | 38 ++- .../Belt/utility.rsi/equipped-BELT.png | Bin 0 -> 402 bytes .../utilitybelt.png => utility.rsi/icon.png} | Bin .../Clothing/Belt/utility.rsi/inhand-left.png | Bin 0 -> 331 bytes .../Belt/utility.rsi/inhand-right.png | Bin 0 -> 352 bytes .../Clothing/Belt/utility.rsi/meta.json | 38 +++ .../Doors/airlock_maint.rsi/meta.json | 2 +- .../Tools/welder.rsi/{welder.png => icon.png} | Bin .../Objects/Tools/welder.rsi/meta.json | 216 ++++++++-------- .../Tools/welder_experimental.rsi/icon.png | Bin 0 -> 583 bytes .../Tools/welder_experimental.rsi/meta.json | 121 +++++++++ .../off-inhand-left.png | Bin 0 -> 345 bytes .../off-inhand-right.png | Bin 0 -> 358 bytes .../on-inhand-left.png | Bin 0 -> 868 bytes .../on-inhand-right.png | Bin 0 -> 809 bytes .../welder_experimental.rsi/welder_flame.png | Bin 0 -> 296 bytes .../Objects/Tools/welder_mini.rsi/icon.png | Bin 0 -> 312 bytes .../Objects/Tools/welder_mini.rsi/meta.json | 30 +++ .../Tools/welder_mini.rsi/welder_flame.png | Bin 0 -> 295 bytes 122 files changed, 1786 insertions(+), 190 deletions(-) delete mode 100644 Resources/Prototypes/Catalog/Fills/belt.yml create mode 100644 Resources/Prototypes/Entities/Clothing/Belt/filled_belts.yml create mode 100644 Resources/Prototypes/Entities/Objects/Tools/welders.yml create mode 100644 Resources/Textures/Clothing/Belt/assault.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/assault.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/assault.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/assault.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/assault.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/bandolier.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/bandolier.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/bandolier.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar_brass.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar_large.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar_red.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_brass.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_red.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_yellow.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/drill_bolt.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/drill_screw.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/flashbang.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/jaws_cutter.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/jaws_pry.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_red.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_yellow.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver_brass.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver_head.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver_nuke.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/stunbaton.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/stunbaton_active.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/stunbaton_nocell.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/wrench.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/wrench_brass.png create mode 100644 Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/wrench_medical.png create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/baton.png create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/gun.png create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/handcuff.png create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/injector.png create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/tank.png delete mode 100644 Resources/Textures/Clothing/Belt/belt_utility.rsi/equipped-BELT.png delete mode 100644 Resources/Textures/Clothing/Belt/belt_utility.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/ce.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/ce.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/ce.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/ce.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/ce.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/champion.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/champion.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/champion.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/champion.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/champion.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/holster.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/holster.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/holster.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/holster.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/holster.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/janitor.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/janitor.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/janitor.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/janitor.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/janitor.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/medical.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/medical.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/medical.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/medical.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/medical.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/militarywebbing.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/militarywebbing.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/militarywebbing.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/militarywebbing.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/militarywebbing.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/security.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/security.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/security.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/security.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/security.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/securitywebbing.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/securitywebbing.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/securitywebbing.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/sheath.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Belt/sheath.rsi/sheath-equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/sheath.rsi/sheath-sabre-equipped-BELT.png create mode 100644 Resources/Textures/Clothing/Belt/sheath.rsi/sheath-sabre.png create mode 100644 Resources/Textures/Clothing/Belt/sheath.rsi/sheath.png create mode 100644 Resources/Textures/Clothing/Belt/suspenders.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/suspenders.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/utility.rsi/equipped-BELT.png rename Resources/Textures/Clothing/Belt/{belt_utility.rsi/utilitybelt.png => utility.rsi/icon.png} (100%) create mode 100644 Resources/Textures/Clothing/Belt/utility.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Belt/utility.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Belt/utility.rsi/meta.json rename Resources/Textures/Objects/Tools/welder.rsi/{welder.png => icon.png} (100%) create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-left.png create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-right.png create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/on-inhand-left.png create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/on-inhand-right.png create mode 100644 Resources/Textures/Objects/Tools/welder_experimental.rsi/welder_flame.png create mode 100644 Resources/Textures/Objects/Tools/welder_mini.rsi/icon.png create mode 100644 Resources/Textures/Objects/Tools/welder_mini.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/welder_mini.rsi/welder_flame.png diff --git a/Resources/Prototypes/Catalog/Fills/belt.yml b/Resources/Prototypes/Catalog/Fills/belt.yml deleted file mode 100644 index 12f5fc37db..0000000000 --- a/Resources/Prototypes/Catalog/Fills/belt.yml +++ /dev/null @@ -1,25 +0,0 @@ -- type: entity - id: UtilityBeltClothingFilled - parent: UtilityBeltClothing - suffix: Filled - components: - - type: StorageFill - contents: - - name: Crowbar - - name: Wrench - - name: Screwdriver - - name: Wirecutter - - name: Welder - - name: Multitool - - name: ApcExtensionCableStack - -- type: entity - id: UtilityBeltClothingFilledEvent - parent: UtilityBeltClothing - suffix: Filled - components: - - type: StorageFill - contents: - - name: Crowbar - - name: Screwdriver - - name: Multitool diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index f7f4cbd9e1..201ed2fe0e 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -1,30 +1,162 @@ +# BASE - type: entity parent: Clothing - id: BeltBase + id: ClothingBeltBase abstract: true components: + - type: Sprite + state: icon - type: Clothing Slots: [belt] - -- type: entity - parent: BeltBase - id: UtilityBeltClothing - name: utility belt - description: Belt for holding all your usual tools - components: - - type: Sprite - sprite: Clothing/Belt/belt_utility.rsi - state: utilitybelt - - type: Clothing size: 50 QuickEquip: false - sprite: Clothing/Belt/belt_utility.rsi + +# CONTENT +- type: entity + parent: ClothingBeltBase + id: ClothingBeltAssault + name: assault belt + description: "A tactical assault belt." + components: + - type: Sprite + sprite: Clothing/Belt/assault.rsi + - type: Clothing + sprite: Clothing/Belt/assault.rsi - type: Storage - capacity: 40 # Full tool loadout is 35, plus an extra + capacity: 40 - type: entity - parent: BeltBase - id: SuspendersClothing + parent: ClothingBeltBase + id: ClothingBeltBandolier + name: assault belt + description: "A bandolier for holding shotgun ammunition." + components: + - type: Sprite + sprite: Clothing/Belt/bandolier.rsi + - type: Clothing + sprite: Clothing/Belt/bandolier.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltChiefEngineer + name: the Chief Engineer's toolbelt + description: "Holds tools, looks snazzy." + components: + - type: Sprite + sprite: Clothing/Belt/ce.rsi + - type: Clothing + sprite: Clothing/Belt/ce.rsi + - type: Storage + capacity: 60 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltChampion + name: championship belt + description: "Proves to the world that you are the strongest!" + components: + - type: Sprite + sprite: Clothing/Belt/champion.rsi + - type: Clothing + sprite: Clothing/Belt/champion.rsi + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltHolster + name: shoulder holster + description: "A holster to carry a handgun and ammo. WARNING: Badasses only." + components: + - type: Sprite + sprite: Clothing/Belt/holster.rsi + - type: Clothing + sprite: Clothing/Belt/holster.rsi + - type: Storage + capacity: 20 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltJanitor + name: janibelt + description: "A belt used to hold most janitorial supplies." + components: + - type: Sprite + sprite: Clothing/Belt/janitor.rsi + - type: Clothing + sprite: Clothing/Belt/janitor.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltMedical + name: medical belt + description: "Can hold various medical equipment." + components: + - type: Sprite + sprite: Clothing/Belt/medical.rsi + - type: Clothing + sprite: Clothing/Belt/medical.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltSecurity + name: security belt + description: "Can hold security gear like handcuffs and flashes." + components: + - type: Sprite + sprite: Clothing/Belt/security.rsi + - type: Clothing + sprite: Clothing/Belt/security.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltSecurityWebbing + name: security webbing + description: "Unique and versatile chest rig, can hold security gear." + components: + - type: Sprite + sprite: Clothing/Belt/securitywebbing.rsi + - type: Clothing + sprite: Clothing/Belt/securitywebbing.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltMilitaryWebbing + name: chest rig + description: "A set of tactical webbing worn by Syndicate boarding parties." + components: + - type: Sprite + sprite: Clothing/Belt/militarywebbing.rsi + - type: Clothing + sprite: Clothing/Belt/militarywebbing.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltSheath + name: sabre sheath + description: "An ornate sheath designed to hold an officer's blade." + components: + - type: Sprite + sprite: Clothing/Belt/sheath.rsi + state: sheath + - type: Clothing + sprite: Clothing/Belt/sheath.rsi + - type: Storage + capacity: 40 + +- type: entity + parent: ClothingBeltBase + id: ClothingBeltSuspenders name: suspenders description: For holding your pants up. components: @@ -32,6 +164,17 @@ sprite: Clothing/Belt/suspenders.rsi state: icon - type: Clothing - size: 50 - QuickEquip: false sprite: Clothing/Belt/suspenders.rsi + +- type: entity + parent: ClothingBeltBase + id: UtilityBeltClothing #Change to ClothingBeltUtility + name: utility belt + description: "Can hold various things." + components: + - type: Sprite + sprite: Clothing/Belt/utility.rsi + - type: Clothing + sprite: Clothing/Belt/utility.rsi + - type: Storage + capacity: 40 # Full tool loadout is 35, plus an extra diff --git a/Resources/Prototypes/Entities/Clothing/Belt/filled_belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/filled_belts.yml new file mode 100644 index 0000000000..4959eac56f --- /dev/null +++ b/Resources/Prototypes/Entities/Clothing/Belt/filled_belts.yml @@ -0,0 +1,65 @@ +- type: entity + id: UtilityBeltClothingFilled #Change to ClothingBeltUtilityFilled + parent: UtilityBeltClothing #Change to ClothingBeltUtility + description: "Holds tools." + suffix: Filled + components: + - type: StorageFill + contents: + - name: Crowbar + - name: Wrench + - name: Screwdriver + - name: Wirecutter + - name: Welder + - name: Multitool + +- type: entity + id: UtilityBeltClothingFilledEvent + parent: UtilityBeltClothing + suffix: Filled + components: + - type: StorageFill + contents: + - name: Crowbar + - name: Screwdriver + - name: Multitool + +- type: entity + id: ClothingBeltChiefEngineerFilled + parent: ClothingBeltChiefEngineer + suffix: Filled + components: + - type: StorageFill + contents: + - name: PowerDrill + - name: JawsOfLife + - name: WelderExperimental + - name: Multitool + - name: ApcExtensionCableStack + +- type: entity + id: ClothingBeltSecurityFilled + parent: ClothingBeltSecurity + suffix: Filled + components: + - type: StorageFill + contents: + - name: SecGlasses + - name: GrenadeFlashBang + - name: GrenadeFlashBang + - name: Stunbaton + - name: Handcuffs + - name: Handcuffs + +- type: entity + id: ClothingBeltJanitorFilled + parent: ClothingBeltJanitor + suffix: Filled + components: + - type: StorageFill + contents: + - name: Soap #Make a soap group and pick between when i'm not lazy + - name: SprayBottleSpaceCleaner + - name: # GrenadeChem + - name: # GrenadeChem + - name: FlashlightLantern diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index 0941fe2bf0..cafa7ee90f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -61,40 +61,6 @@ cyan: "#18a2d5" yellow: "#ffa500" -- type: entity - name: welding tool - parent: BaseItem - id: Welder - description: 'Melts anything as long as it''s fueled, don''t forget your eye protection!' - components: - - type: Sprite - sprite: Objects/Tools/welder.rsi - layers: - - state: welder - - state: welder_flame - shader: unshaded - visible: false - - type: Item - size: 10 - sprite: Objects/Tools/welder.rsi - HeldPrefix: off - - type: ItemCooldown - - type: MeleeWeapon - - type: ItemStatus - - type: SolutionContainer - maxVol: 100 - caps: AddTo, NoExamine - contents: - reagents: - - ReagentId: chem.WeldingFuel - Quantity: 100 - - type: Welder - weldSoundCollection: Welder - - type: PointLight - enabled: false - radius: 1.5 - color: orange - - type: entity name: wrench parent: BaseItem diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml new file mode 100644 index 0000000000..d36404eeb6 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml @@ -0,0 +1,77 @@ +- type: entity + name: welding tool + parent: BaseItem + id: Welder + description: "Melts anything as long as it's fueled, don't forget your eye protection!" + components: + - type: Sprite + sprite: Objects/Tools/welder.rsi + layers: + - state: icon + - state: welder_flame + shader: unshaded + visible: false + - type: Item + size: 10 + sprite: Objects/Tools/welder.rsi + HeldPrefix: off + - type: ItemCooldown + - type: MeleeWeapon + - type: ItemStatus + - type: SolutionContainer + maxVol: 100 + caps: AddTo, NoExamine + contents: + reagents: + - ReagentId: chem.WeldingFuel + Quantity: 100 + - type: Welder + weldSoundCollection: Welder + - type: PointLight + enabled: false + radius: 1.5 + color: orange + +- type: entity + name: experimental welding tool + parent: Welder + id: WelderExperimental + description: "An experimental welder capable of self-fuel generation and less harmful to the eyes." + components: + - type: Sprite + sprite: Objects/Tools/welder_experimental.rsi + - type: Item + sprite: Objects/Tools/welder_experimental.rsi + - type: SolutionContainer + maxVol: 1000 + caps: AddTo, NoExamine + contents: + reagents: + - ReagentId: chem.WeldingFuel + Quantity: 1000 + - type: PointLight + enabled: false + radius: 1.5 + color: lightblue + +- type: entity + name: emergency welding tool + parent: Welder + id: WelderMini + description: "A miniature welder used during emergencies." + components: + - type: Sprite + sprite: Objects/Tools/welder_mini.rsi + - type: Item + sprite: Objects/Tools/welder_mini.rsi + - type: SolutionContainer + maxVol: 25 + caps: AddTo, NoExamine + contents: + reagents: + - ReagentId: chem.WeldingFuel + Quantity: 25 + - type: PointLight + enabled: false + radius: 1.0 + color: orange diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml index 6aabd73d23..e621a685ff 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml @@ -19,3 +19,4 @@ head: HatPurplesoft idcard: JanitorPDA ears: HeadsetService + belt: ClothingBeltJanitorFilled diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index 6ee26c2903..7a9aed6f53 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -23,5 +23,5 @@ backpack: BackpackEngineeringFilled shoes: ShoesBrown idcard: CEPDA - belt: UtilityBeltClothingFilled ears: HeadsetEngineering + belt: ClothingBeltChiefEngineerFilled diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index de798fc49d..24861e8d62 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -25,3 +25,4 @@ outerclothing: OuterclothingLabcoatcmo idcard: CMOPDA ears: HeadsetMedicalAlt + belt: ClothingBeltMedical diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml index 376f81107e..4455b8b2a1 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml @@ -20,3 +20,4 @@ outerclothing: OuterclothingLabcoatmedspecopen idcard: MedicalPDA ears: HeadsetMedical + belt: ClothingBeltMedical diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 47117c74f7..57fe23f4b3 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -28,3 +28,4 @@ head: HatBeretHoS idcard: HoSPDA ears: HeadsetSecurityAlt + belt: ClothingBeltSecurityFilled diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml index 1abec1dabd..cd49ef39c9 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml @@ -22,3 +22,4 @@ outerclothing: OuterclothingArmorVest idcard: SecurityPDA ears: HeadsetSecurity + belt: ClothingBeltSecurityFilled diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index 9e223a4a9a..00b6db25c3 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -23,3 +23,4 @@ outerclothing: OuterclothingArmorVest idcard: WardenPDA ears: HeadsetSecurity + belt: ClothingBeltSecurityFilled diff --git a/Resources/Textures/Clothing/Belt/assault.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/assault.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..77a7c17193ed651608539e1c959555b956b994ce GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU^Mb{aSW-L^Y)gZ_hAQ#V;{{Q zg=lywWb+jUPjR}=rx?A=;aZJd_`&l6;f^AAT^?zPs80A=IzjvT3?6mQU4QBY`r`U+ z_#@woG6IbR0yfpmW$&^ildsqXKQG_B`)&=ZU3;(LuBiMcA0Nhry*`_F|8H#Q)Es;J zJ@;Nut}m-oRA2sZ{{Niz-M6LJze%2d*mw1(zgzFFz591xQgU@w-Ne_cPan+Nx5uub zxaPF0g75F&7pHeS zyxKJ{#p;OBu@$qgZ`pPI_*-+%?{ak+aS432H_vbY?Wp*{IIm%1fO%WwB#^zHu6{1- HoD!M<+oYs1 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/assault.rsi/icon.png b/Resources/Textures/Clothing/Belt/assault.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..18047a5740a46576225cb3c988c2a1d0ba01bf93 GIT binary patch literal 382 zcmV-^0fGLBP)Z@v6t24 z0})Je&X?N}2m}IwOD9^=nI)<8>DPZYCZ)uKw0bMBOwY+y+$i3ptYL0}t7&?c&4Oi4JmKrOGDktySXh_r}p zi@XI?ay6rykM7DxfOCF2ANym0{cdZ_2qzx_-{b(`oRN9j_q#2MJOdGdhz93@hyVap zNq80=s*+GQt^V#}as_(PMVxcFilf0kzP-NS_U<0Q_)rQV@Klz75TjU&1x)Iu#VY=e zVO}wth+^&v0v?r66{1xf;r&zUw+&NL_4&2Hl*oBtTbW)`lD&C&tS0{lEJ>w${ycFY c5D5GiU&KybI{*Lx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/assault.rsi/inhand-left.png b/Resources/Textures/Clothing/Belt/assault.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..9edac4c151b0a91f22ab69a32f6a0502f3f2699f GIT binary patch literal 341 zcmV-b0jmCqP)Ip-E*Y*u+O#+Gw7%RBPcfg;jW)p>6h?Y(!Z>O{o62<8PCjd=l7brKQx zv#zGOBH~naG7WWfK))IA{dkz>G6Op4HUny{W|_6tac011k3j$c000000KgR?1lyfh zXXby4&-46co!L{D&Cp$45JFf}O6~amY{t;5v17NTl-euZ*QEg4w%Kk*|FD1C%d$+z z>)9?C_6Yn}*$Ex>*r@9co9%nGo7_)^N#D)SX@dknwh#wn$?7ykJA4D)^aok9rf naq^c^o_8F-k2Bh@PkfSJD=%zZmgvjU00000NkvXXu0mjfklLF# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/assault.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/assault.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..2489dcd7ec23c35c0bc39cefef4cf9daed9e79b6 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU^Mr1aSW-L^Y-RhuOkKm>>n~6 z-Z#dcKPBV(Lb_#7Yo+u3Me73u`kUvyJ# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/assault.rsi/meta.json b/Resources/Textures/Clothing/Belt/assault.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/assault.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/bandolier.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/bandolier.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..55062fea789c43f4a1e56eaac7e8684bf9b8345f GIT binary patch literal 376 zcmV-;0f+vHP)2b@d<00000 z&`nkS)#krP4cb?7Gb3gmvI)%WW=8u;q4VFO2C1r_=Sj=5keShO9AUFX#7iku=Wp8< zHao<=l8cBlvqv}7W-zmhNN7gLPKt<|*^u_zjCu-6DMK>;ZC}Y%)tT8-qw8 WE%k&^)cl12000015QU#psaR06Flq#IfVoUA5J(Y7mnyApkUED5Bt@>^E~V6^ak(i4Dg;7I3L|2K zte>?NgW0d%<<0j-DHXV0)eaN7h6x#(;_Spd;kCd07*qoM6N<$g7`+4*#H0l literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-left.png b/Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..8cbd98c83997f8c658d0809b9e3c20758777a510 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=|2$nBLn`LHy>*bc$w1`T$M)_$ zyn8lwsb6~`vgY7L-ztTRoK~E2OO_crCH=aU_2a)#FyE(&Df|{9f+je4icjf$=LyY8Z|qabw=BHE;`4gO?TS0~xBiB=E#jQ;=h#}cB4JLA zkm)RI9vcc@=)bgfwi>6$D@KTM3?IDrOpbmnH)~Ur*!ra>4tcBf<+`g}|)hr@r&n?9kJ=xjI6aFq)dP?_0-O<_V3T7Aji?*$ao^+Gt$mIQT zhwiR=HgD|;^WCgbd;aUnHP!3xV|%>*C-a7>hv!-F*f9La54*EyA=5;V<({s7F6*2U FngGHTh4}yg literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/bandolier.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..56ae9791dc3271e94f9c8c7fb73b0e64968a44b1 GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=e>`0rLn`LHy|tV7kby|+L+0)~ zye}eJyG(6ZvzMd@i%(2w@)6=P;NnkYK4$iz-gnWFU3YG<2T5=O^@2dbleuoj(%IiX zav4kS4c_v-^2xs_D?gWM>$qlq+1=OM>+3K*YK7s#`|loVsH!O}4M?6O-pBGp>xzU> zfz`h04Nu)RUvcVvxup9aBg8z0A7=M5!*{o@vfCIce_L|b!@0i->TWf^m+w8lbmmp_ z&7bG1EqlJy&bs{Uav_1RYKgX+Um~esRct$)5P zmbZFk%&T{+ekx0Z)GAjjx3j4@c|D={-?xJwlleL>h26Qg+_w#6wWq6}%Q~loCIJ4K Bf@=T( literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/bandolier.rsi/meta.json b/Resources/Textures/Clothing/Belt/bandolier.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/bandolier.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e98598fae3877ee2a484fa8e45c9841a6582fd GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJa!(h>kcv5PuNv|-DDbpCTrQng z#Bs-J^P|7&d`+`^c3C9~Urspj`?=a*4+VxEL$fTUqReM$tDi=5Xti)MFoeAiEly*| zeazGs^owarFZToO7km%2f1FjV`90wbW3`uWi)2C}pP}2Ft!B^Fv=4l~Vwt|#wx{+T Z+v+D`kGHT*sDx6}C z(x*f>aE9desVrfbYN5TOd1=!Frh{b-muy!zod0-+>Ava_?ErI0hJ;N&SF`@+Tho2; z#`J!nHB7IQ7#RFs9+#Xi{`hFgU)GpK8{e`=_bL2&#^PxuD!smMiXhN|44$rjF6*2U FngHglPVxW% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar_large.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/crowbar_large.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e98598fae3877ee2a484fa8e45c9841a6582fd GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJa!(h>kcv5PuNv|-DDbpCTrQng z#Bs-J^P|7&d`+`^c3C9~Urspj`?=a*4+VxEL$fTUqReM$tDi=5Xti)MFoeAiEly*| zeazGs^owarFZToO7km%2f1FjV`90wbW3`uWi)2C}pP}2Ft!B^Fv=4l~Vwt|#wx{+T Z+v+D`kGHrYd zw^f*V#+=_w9Xo}Y3xXS%jl+#0-*=hw9t%G%$iCDBbPR*1tDnm{r-UW|=(9qa literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_brass.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_brass.png new file mode 100644 index 0000000000000000000000000000000000000000..f8510d2abfb77aad3112e069f0eedd042d84e147 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJNuDl_Ar*6y6C_v{Cy4Yk1sZU< z9TZ^ye=%bcqp<2UZf-6k10Zn7+$8I`jaeeVxj~0LK!}MaL(!q!;Dh3X>~sB2m+vxO zVVGjkFp**YGrj~6Sivu{RO5Hx69z?1Gd5*yMm9ywZHbuSM@>WJ4!DkI&*Q5;?w^y^TFZ@-?aNubL(}O*?XMZn(Eu8hq97YbsKk5t$OH+3JPRqLAaDsVDnPk@XFAHA-UC7|+>gTe~ HDWM4fMR`>| literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_yellow.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/cutters_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..eb18cbd9a50ee8dd4bb28aa1dc0609432991b2a1 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ*`6+rAr*7pURLBfY#`F`aKEsq zVWTKl>y4E%>E<(DCN5i+T{d@Ow#c%u6P!kY#%gN!q%~W=&vbX06t9xdV|Z+aZFS7; zPnN2DmwGRINbdT2Z=tr2@*i;W6EM1Dh%l-cDFM8_LCM)cp82YE~zP!cm z`pfdGT3D_LG(@VrIMS4~vgD)uDpuRL0H8tpkIZ}c|8ktzn#=@|o|uN!F%qmH>>F|{ z5~ls%xA^b>+m(E~EE+gxKUm#sE_v_$@52uLO&r-5yL5l7jAZU>3N+wyJE-Bn#!xiN W>cqk~o-sfdGkCiCxvXi;W6EM1Dh%l-cDFM8_LCM)cp82YE~zP!cm z`pfdGT3D_LG(@VrIMS4~vgD)uDpuRL0H8tpkIZ}c|8ktzn#=@|o|uN!F%qmH>>F|{ z5~ls%xA^b>+m(E~EE+gxKUm#sE_v_$@52uLO&r-5yL5l7jAZU>3N+wyJE-Bn#!xiN W>cqk~o-sfdGkCiCxvX{w%_BYWYh;Qw0YNB>T1N&ho9HC@{Il;yHRP>n+K=CyXs8#WkheXDkk(Z23a z!jHed%@1F{zlF21iSNOK2MIq8A2}7U?%Q-nFUOf`eF`l9x;r}lq$eaStLB5ajE8}t XLS0Wum9?q>=xhd0S3j3^P6>|>te zxPOsvDLA_p*S!hn1_0ni>|>te zxPOsvDLA_p*S!hn1_0niv?HDcwl^L5`Qxqe63Xg63^t(#`eP6`R?R%L& pXu7*~r1UReeKojP-SjCYe#(v>RTLqPKxJYD@<);T3K0RRaBG35XN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_red.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_red.png new file mode 100644 index 0000000000000000000000000000000000000000..008bd7995f954b05c31d1b766176410ee978b01c GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ5KkA!kcv5PFKy&)FyL{yxWRGT z2`)WJ-P~g*%;cV%8Hlp3)KxlCKk4>v?HDcwl^L5`Qxqe63Xg63^t(#`eP6`R?R%L& pXu7*~r1UReeKojP-SjCYe#(v>RTLqPKxJYD@<);T3K0RRaBG35XN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_yellow.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/multitool_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..008bd7995f954b05c31d1b766176410ee978b01c GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ5KkA!kcv5PFKy&)FyL{yxWRGT z2`)WJ-P~g*%;cV%8Hlp3)KxlCKk4>v?HDcwl^L5`Qxqe63Xg63^t(#`eP6`R?R%L& pXu7*~r1UReeKojP-SjCYe#(v>RTLqPKxJYD@<);T3K0RRaBG35XN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/screwdriver.png new file mode 100644 index 0000000000000000000000000000000000000000..d4ba4ba4218fbc253a6ee0d4afa64ee946cc0c04 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ2u~Nskcv5PFE8X`aO7YK*qQfv z^Iz}PxlI>Oi}P*Uar)4nBte-LK}98{MbSH|>fwW|JYu`{+%k|0fACGB6zI59xG|e)s97paB1v}5?GcPi~I?d&x^u*wln}-+t;_pag_wimYy&-S02SdXy?%Hhv V(Q4fv6M@zkpyK`{-Ji<^7#SE2^!s!#UH+}2>!OO2v_t-ZvR4fU z-bfp`)G*Jx7t7pt{*K$$4_c{wf?Q`xwr{g_T6*o(FZMGp{yTW>W3)`4%)n62{jox5 V`hkD*P64fF@O1TaS?83{1OWE>LfZfU literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/stunbaton.png b/Resources/Textures/Clothing/Belt/belt_icon_overlay.rsi/stunbaton.png new file mode 100644 index 0000000000000000000000000000000000000000..784617bd4fe826cfe74a807ad2071091c1b6343c GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJnVv3=Ar*7pUNhu6Y{26XXxjX& z>EoM|FN9{5w#w;Mzk6zF{^5~Nqt8Yz(M68=V%OM{4IDTWTb64rEoM|FN9{5w#w;Mzk6zF{^5~Nqt8Yz(M68=V%OM{4IDTWTb64rEoM|FN9{5w#w;Mzk6zF{^5~Nqt8Yz(M68=V%OM{4IDTWTb64rD{?eE+`sI3 zLP<%=tB0fj0-g|tvt-b1(dyG0Q z8y4>`KKFO$;(CULRkKz_d1c;K=wIzFxN(kgG7rPGs56%O*?H&yaq(dC6Z-pw$eX Lu6{1-oD!MD{?eE+`sI3 zLP<%=tB0fj0-g|tvt-b1(dyG0Q z8y4>`KKFO$;(CULRkKz_d1c;K=wIzFxN(kgG7rPGs56%O*?H??4-wFom?-%nT&DYjyEG$E{ekOR#;;$x+pM&^ud)7I;>??tc{0)l zh0IaRGgjy}Oci`y{aVW0U$%PfobUV@n~hfW{jFyPY6F5gPkBYDbr%=+FBV>Zac+*o nakd`51&41id=Ugeh8?e&@)oHSZekS41*!IQ^>bP0l+XkKJa0s> literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/gun.png b/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/gun.png new file mode 100644 index 0000000000000000000000000000000000000000..ed96666e883efae004b0b59d84fba48e3814509c GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=QJyZ2Ar*7p-g4wSpuoZ6aQnx9 z{p;TG3bVxKc-nXs9OjK?2C8a^JYOC3k~?cj^%p%&^#}iUHD+D%1&V{fhidO_7e%)n pUMQf&QsAl=&ha4PpArLu3(uQVTr6jc=iUV=@^tlcS?83{1OSSaFa-br literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/handcuff.png b/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/handcuff.png new file mode 100644 index 0000000000000000000000000000000000000000..f22fd5cb89da9ebe0166cb49a2157eff3e2bd53b GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=(Vi}jAr*7p-a5#8K!Jz(z?=Og zzmpgOniuSoW_Z&Pzk&&^0d^Z#AGaD!wS7#iv> sYHxn=saY}PhrqfY))#bl*)Zr-Fun;CdGqq>vPB>zp00i_>zopr0O$ucbN~PV literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/injector.png b/Resources/Textures/Clothing/Belt/belt_mob_overlay.rsi/injector.png new file mode 100644 index 0000000000000000000000000000000000000000..85fa72599d661fb0193c8719aba574143f3446c5 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=w>(`OLn`LHy>+m+*+8K6;q=g1 z3pk`^2&+rYP`bp%yR^}=u!vdYp^;j9XqezF-zTaHuD|xr-gtDgj>S(;pnedDJ9TFH zWB#JN$egsBrE}L!T9$b#QNrZ>W;M@u^R|Xf4f5Ol=8Izdq+k2OT{2|cbx$jK{__79 ze)`e;>G5I0)35&V^U_=%wK{8U7l&t%%ZqLdL}nDHxIgHP^u7Lg zzv1SR?^E_!GvD6+<&N#)yO+8d zIrrTJqp81JCr>R*GO~5_xXiV#L1}$zeZ;Bf*JtP4mtW^6cx6hHe!$8f56_qHovbci zcdWkXqd&xa5UIFk>&a~=o1>HKO_%=KeR%T{D{TWS#@P2ywq8z2XLVCQkYbg&cuP=c zROVvgfG1n;oGA}_Qrc6|_iNtT#q-Q}ZMQ$e?PIEK5aO^VU-dhS&$2VB3=9It`K7M8 Uir8f-b%3n!boFyt=akR{0OQ$)lK=n! literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/belt_utility.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/belt_utility.rsi/equipped-BELT.png deleted file mode 100644 index b8cad1678990049e1537495bb96a324e60f7fad5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Z#`WcLn`LHy=BPPWFT_vV|!t7 zN%0$pI}aJ+4sfnlC=Xiy;2Gn38nKO~~~BeWsV*zig$fwkiQl z0fGb9XSFZNRJj#eAO6~?BsXEY=LEM!ubWxcKYZSOLa$oxy|a+?@Aj;BHq$RN-8pPJ zUBzry?6XZbB;FUqyGBMHKd$_J=N$0`8rqWma=usm=NH8Peth!R^j5j(11D|vu-^C< zCDnPY6k-+FI{nRa|EX=fsA9HC`{KE7Zuu)`Ha*=rFMvNrdWNt1ts4DPt4hNc_@7;~ iXie1LFCd>X{5vB0sxyYwioGxu#PxLbb6Mw<&;$U}rF*ad diff --git a/Resources/Textures/Clothing/Belt/belt_utility.rsi/meta.json b/Resources/Textures/Clothing/Belt/belt_utility.rsi/meta.json deleted file mode 100644 index c6d2b08e03..0000000000 --- a/Resources/Textures/Clothing/Belt/belt_utility.rsi/meta.json +++ /dev/null @@ -1 +0,0 @@ -{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/discordia-space/CEV-Eris at commit 9a3a3a180344460263e8df7ea2565128e07b86b5", "states": [{"name": "equipped-BELT", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "utilitybelt", "directions": 1, "delays": [[1.0]]}]} \ No newline at end of file diff --git a/Resources/Textures/Clothing/Belt/ce.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/ce.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..e5bacdb467288033048b52e5411cac6eda471385 GIT binary patch literal 459 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV4URX;uumf=k2ZiS%(5d*gl-U z)LyV5c-uPN+77R|yGvg@2w9k*ebqO^%A(A3>gxv=Lib42G&Bepby}1aXwIx@z3e#2 zZPAOZy-Pp*RZy{1-}(Fre`FD(5)>@zU6SZoB>S>#w~%h+_YDy`*RI_Vx&Q3O7nbX# ztdF^x6gs&5mIsS)wbs6pz8Ka0{`ZWtX)C+G*2+g^YfkmDoNU;ef8c2(s|53N_3MQ> zCc7LrMjS~oGL$`c;_6Y`4_puQ=33Xr%illtgKfn_;k=JbrZrwJ_Gh)#3D@%KsSdW;3g0o^^Jai+9=8@ah|;elEyh|8xC+r!|+lXnuXX%Uz9~pRGCMV8%QL z0hUQ~j3CD?h8CIMd_Pn_B y*ImS=EjgQn33V7bPDknXHa)UYtKFfc$O z3yTwVvCXZ>?Um@{{gS3h@8AFY_q06)i^XF3@05Nb7D6N@x*!OQeG7$Z(R#gZWICJ8 zjKgRbg%F8abh%s_1*lf5xiGpAI~UU8YEji#$JcvwAr5s$&1RE+zn`^UZLJPfpL*;< z8=z4;rQIH629FQHfk}Y#3$X$4yF;SqW35&jV6qr68jbL~L#RywHah)$KF`kb_La$E zfRr~lj@J)TZ=$J$&EKu7_dBYPABOQmGKfF;dEGz13V6m|f>^E}cZ?#nf}F5%Nvt^*Kfk3hYzXbxxt z1VKLo%ke`a+C2|(Ypp6ld8*#KV~m)cxX7|vk1g!pyA9?e;1bVhW@=( z|08nUF|W5wz5fjIeptWO%kkFAzA^9G%iSF>9?U7;ow~M2u60Vp^PkuKv%}{*s&>!F zIn~nb@R|RLdBe2* cwFMG8n4fd5?mn)n_Xp$vPgg&ebxsLQ0J)8mBme*a literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/ce.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/ce.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..512d21a2da90ea8e850b843479e75ed42cafb19f GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU=;OqaSW-L^Y-S!-a`fgt%>@* zPacT9P~hF*x`au-_8ybPa*l0{9ywm1T|C*I^r}ea)op*TL*Ev^NC1&NBzdLfFWcQNJdo$hYXY?hW)2!$&y}p;} zNyWRpkCsnJv7ML9WVf%*ZmxIyhfvlH``T7*`&V}Ehel8M`LOJa%Wg5}AAL=>6;1p1 dmjAf?XYM;1Yr=Y8|1<+x?dj_0vd$@?2>|?VkTw7S literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/ce.rsi/meta.json b/Resources/Textures/Clothing/Belt/ce.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/ce.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/champion.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/champion.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb41718c1ac7bd27be9febd05fdbc0bb1182b57 GIT binary patch literal 510 zcmVG5% zW>PUri?K#jJn_W=0FNq%{P?yF zz_Y;+CkGB?D+)ky=ewu%A9@WUm9FBP71`apAd(noYrW3n=Lx1qe>Q^(%G$>=Z>FA- zN>?dcQRY58Au=#bcBY?CS>tO?Pua>PV~ri~E)0OP)yQ8c{)_k7a{v~;T7m6=$&nZ4 zWz+&_zVY^JuRFk3ux=t;CkIZT4=y4iA|fIpA|fIpA|fL4w|a7**;+6$`{g*$L(*I_ zX6~gZBcB;F?We+S`_<{HIVud9qryFTxqPBGr5>jc=f3M-5CYwatGbuRZy#3#bor43Ju`(c+hh);yM z+%Mf2k6o*DJzr10q1J7G7yp2}T1!MkMC70L8|ntJ+D->^_y7O^07*qoM6N<$ff~0McTl&2MFJ&sF&x)y z?dBq!;-px05>hyc!+CZv8g2B{bnJbWJD%U4@Avt0_kfFwi_8Cxut{>_AUs+puT*QS z-FIc;tY{%W#4<$ctv)|0aC+{=GQ>wUCl?QGSDA4PCJw@*iRj;rohamo09b~|$%Wu( zVrgI^{^{c#dQ}D>n>N|s^UbZmA~LE6fY_nQyH`F(6Vj^L=vA3)+5{k1lNtMnzhx&NVHv(v?QyiXzvsg;M0#C|Gj*F}G%yu6 zH62sa=Vn;Q4@pJ?oT=ONx)zdRQ*ZU3W}sAS2$NI46OfP;n^dGT6|cAY$nh9*JT_OC zigb_^`+fyPaz)wkD{$T*SUQ8q`_~NG8iTgR)@~fj5ZT&|uT?vX;~6N`8Un@e=*WMI zWr$pspK+{cND5P708`U}@z`ZKNQw@#GvP)@GaTgaC7l1zu_Tb>1 SIZ-?S0000-Va3&%eGTBQjG(9@ez zHZ?qVjBmQQ+bhhpBKYLbZcoPLW#O-O_j-lNtn=|U_{nrR4nROwbW7N1;nB1CV z^7v5dQp3mtiTkI#IH?^Y2D9+O*10`r=WWuRv4`jB%X^1>xh&4v7e_W$|9G1+Cq;Ad z7w#7|XKcP#Yfom9YrFrfzcNZYSa(5=_=1ik#_NaE=RR8dDI)UWPVx9_-W$H??rJ}m cU3zopr0D>Bj+W-In literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/champion.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/champion.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..2137c63d34b44d76ae95c0d919a420ccb7fd51b6 GIT binary patch literal 360 zcmV-u0hj)XP)bF5XbS!oqrBV3@4&k$ssmAfY#$bn#U5G0LJl2{$CSGb$o z?1bp|)1(>5Z)az>SrGsL000000Km7G>x25~_OR|cM-xpl4{QaabRuya`=?SgN+*(3 zsZ;HSt)MD0iHf0jC{0z7IoDbzVDI!qlJg6%K-z}Mv2(4p0iWX|+00(O0%xn%znR zG_`%?T4_M2-C4Cfa-Ckj<|Vj#A@*luJ%r+o-c9HX+%Bxl6>6BjI>i@ZWlG5%0?P zKefAcnSe&xq?n1urmV`@COT6qJ^13jEDfX3XD=<|=fz$B+%x^&s!tgk*FAgO8TEAK zi;pgA#a?ISNu4fXuzSD9di(E{cHfSFzMTE2>gCq0zi+Xf&3#e&`|hhf9UemNe(Vd* z$$pW)GF8RjRlRV@Znl$V<3-f6R_s8r%t$LTw2TWx9`lQ#2OKaTYYJD{-sM8}u%s2o!U#p(MyPF&AVi9NhJ tSMc}ZTo&W^`RxXs|App%p9D7X|4B}^kMUm_8PZKbd{0+Dmvv4FO#rn}m|_3` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/holster.rsi/icon.png b/Resources/Textures/Clothing/Belt/holster.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d77d1088c9739ed7a40ba34224a6770ac893ea98 GIT binary patch literal 295 zcmV+?0oeYDP)8&rk3$dng_TfyX135DbdU@Bl@WrW-742O&UmpS)i0zux^R z2!bF8!aq{yn5M!MDaOT$)W+)E$6{Er3aDnsH$Fzd=$_gGXK3=34t)R?cvnP4G z0VlpY*#%op?vq^?J-zh;RST+U4(Xe`#Xm)_va2CfRj<7uVdiVAXr}ZTW%4B@cFm+@D`j z_tFMz)Q$}q$2E2vhwRSY?V6$!DO|9uzdvh{xx`C}R9^>g-BoH@3Wr!^Y#W50NvlLk re}49xQFktb=GC1F8&^*=d*WQfs2Od{@JHr!6v#ABS3j3^P6WQNFLjtIaT`eSABXJx5|WnVis4`)@;A{ zHg5j@?e{)0flT|Nzo=8_>Ws{L5}j`pT-VIqXDp)hRq#bG(;L}@{H^aks9pRop!0fr fPSvvej1%rKi(fJ1D__5;2Bg)~)z4*}Q$iB}1EgZ% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/holster.rsi/meta.json b/Resources/Textures/Clothing/Belt/holster.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/holster.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/janitor.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/janitor.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce0f6c5dbd81ab94ba30c635847b1914b92b56a GIT binary patch literal 369 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV6^abaSW-L^Y)gb*I@^dV;{o{ zgU$6^cWLYp<68KQ!7E(sp!X5u9hw!5ath@y7P%MbKjOUODdjBYdp$MAcgD8GAD4Qv z{QRFVP`ER(tdkr7N0YGwrU1<8} z_7&Rw3#9sgKl>CYAU#|9!`=0>Zy%rTd10R8SH_yp-|y~mxO~cp^Hxv8E9NJ&Q?hw% zrM{f4i(3%+`DKnayTHA8(dU&m)n;o`S?;{vKjZA~nJwEkaRSZ$e@a}u`H+ZJv||Lw NK2KLamvv4FO#p8KqO$-1 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/janitor.rsi/icon.png b/Resources/Textures/Clothing/Belt/janitor.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..94cb6d95325d61b2ec78e034d1793cc37320c11b GIT binary patch literal 495 zcmVEPzv-5c)ygM#3Hpo8w6i%S<5uRji~L%~G{ z1*OQ{VAYaKPg0e<4z?lH_H8OUT|N*pyidN*hbO!b`1ttv{O>4(6fcHT!b@G=%y`c2 zTj*{&u1tCgHAKy`jP!6ZoD%M)^}v-Ufk<z*+ME zkyvNtv;aWP#Fo`xM2pXFihO@4aMJuq{h!=fDgZDO4e@}*X?)2M0Vp*#xenX_FwxXF zie&jV8{+e)2#4o&wkiv(vB%DpP3$cKc{8IBM#KS?pd+GuSw)ny%!ht3_g4ep*Vqk5 zWGP?XQNFx$GE{=ZZj;hm(02mcl?E|0&2lU7`p<7B2vTZnvOC(EKtqEFSZ3#*%9-iD zdqDbw@@7Vf-6kE8oSAll4N*h2Y*fqkd^@_~d1baY;zhLBb*#FszgpAPYIUGhKafZ_ lbX^zi=iM9o`1tsI6i=dEuuk)6OcekC002ovPDHLkV1lV^=@S3| literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/janitor.rsi/inhand-left.png b/Resources/Textures/Clothing/Belt/janitor.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd433aaeb816ff53008dfcfe78a6760935da945 GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVAS+d3CT!d;;;`5@b!ea}^1{dX7o zabQdpwsn^d?K^npHVX;3lL=~+QHB~D&ty?4{>UgNH3yZARbpVEG}4QQRE^k&o9OL(U8-6&fw-g_tF|Casx z%w21I-Zq`|Yy96eC#vQm)0fYN>FjsB)-e1%Ti*RkV`^pZ!D$Z_^B0$5Ch~b7y`%H%;FCRntrX->9gCgO;G6v=Rikc7?`*z` z?*^9=_r2~7P2Vx0?NnpG#=txp}p~3Y#IOmzxn~!6(g?SWQ7>aa3FNa;k{pG zZQUh#X?bOQmG5ho8KFDw9q0&Oni21Ljq}3t%KLk?Rxi@hi&T9O)_S$@mVte2$w4b? zo>dXowHVhotbP0l+XkK&)<&d literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/janitor.rsi/meta.json b/Resources/Textures/Clothing/Belt/janitor.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/janitor.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/medical.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/medical.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..4da4f1e6b2055157095360d39b1a55102befe37b GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV3hTAaSW-L^Y+$WFJ?!Pwuk&1 zJ!gf4X|`Npl-}x-s2+B&A@oFS1^dqBPl8gU6crVG5-Zmno2w#SetuS@<2`o1%|3PK z45H`xGXaeR0>4ey#ZO;<@-i`N*X7r{Wp3X1-gN4cj~NR-W?Xp6^Y-dj zzp3Bm)`)-DIN52%wd2~FEV<=@+b1vFzCHfl?+ussU0(WI+%W8Qk*@1^`;zJ3|GoSi zlw-HK#`j(RI^EEl!ZP3UZm~n`1Cj-HvFV@p7p}8u%D0I#ulKKx3|p|G+2_#7&s(1C zZrJs+n&Z;%=&9lwYc(f7IK%NnPvO{J!!2ji%ch8HNkl1v!xEC|J`x~Ut$=x6+;^HFW&_z@N8Jq)|x;VJHbVw=b-lR2)VoWd-5f@fWcre{C8S)COcu2=*%1SZ0+32iTR>!%hC#63!yEe z9CX4c$rsHBtB}{IBuWR;;`yRYI*?|RN$jbDylw|~Jjn{z?Z8@yETasi06=hdngzUG z+B-S|$1l;Bytc8x{>2Hwa0-CSCb$gC>u*lHKJFsMpUo>}D+P)~0Q}iJdn9ekV)y!- ztGfpdZf^N_9uOQI;w|Fl9T@fO7GabO3Pe7KQ@n2H$MpbM#qX>h?~AkQ3gmIe6J(LC z4gm3TxwWopA5aRUU64iOwyuRh?*pwVkVybY+pv6RP8cO`=}QO*|EboNtc~h_;Dk|< h9=~4LU@#c|if^1pw6vpvKC^cJW*Y^Z+Tf!57FJ2y_TOMWHB5W8BaV zcAg{$|9_M4@boNywhR&h000000001-r;3bCi_&V;N{iA~kx{AjmywI2U#}m%uGi#b z0midwuj@6D0PTWV65HM5TyC}-wVLDERI(&?@*QxJ0BtT4;Kb**9riAu{n5I(1ONa4 z000000EVK9%sO-rL1`U`_~PVX#8(RTi-%t)P+jJ|(rwAFXLDPR)1tIbA|k6iSU+_m zKIW++vp${c=Nz$B3NH2)n5^>aHrM~7x&X%~(zb~%vLsenWVHo2-u(T`@?EQD7s0mS z5EG|GS?>bPaT{t0@Dck{cln!$^e2764F2yEXE*?L2!K>2!*)sl0000 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/medical.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/medical.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e40d34a82a4514761d16ffecd9b030a65a1d55 GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU=;UsaSW-L^Y+$8t|kYW;~y6< zT>c`r=a%#lv*Qako>XkVr|alN|zR2uD|x3xoO3N^Sl4w zIuauSus7G0~cPjXmys}zqw7pBtLVx>wb)f*W@?RWbRduYs_%~eru z{K>XzEd^O^9nd)_v1$WmcP0rsJGD|HV(tzwWt3c~hr>^^(<2 eXYSWo)SVH%t=lqrij1`o$a+s#KbLh*2~7apfR0%J literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/medical.rsi/meta.json b/Resources/Textures/Clothing/Belt/medical.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/medical.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/militarywebbing.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/militarywebbing.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..06cec5d458517c5675c9976f05ecd0a43262d911 GIT binary patch literal 721 zcmV;?0xtcDP)S0f*=TjKU!;hZ@eY_MT~Mp1R}a#w*z>k-R*WjM3d5;mjYgU zE|&|GWjT_uY3Stu4n0JKs;U40Cgs$9T?gy-asUxQS(ZRVa6X^! zN}jhg{7ly6MgZ$}=lSBb3$$%p0DuMfw*^f}0D#l!#Pb)0ZD`xJK*Z6%OhlvmA$*`XEQd2(U5I!+pf$!6 zY+nf8;i9#+QzxzNOCw_Pl;9|2KC{X9R5&OCrr?S#SBX=@mFT6KGNM{!7%rFPZjs@B zgpW3v;Ci6TA`#&B2&7yGwAS{vFJUgT9N;!8t;Jj$7Ks23NtUU|scVv{@NSyMDy1yT z)Hb-fruO{M6bxDfr##L*db#=nxDkSN`q(I>;u(4d=GqVyvTi*d5m)OK&{|u!b2Y|} zs9k{bj9-3@k~H@PaF1~I+*e9vS@pMKhad=oAZ(Do6P6Q&6%tFD00000NkvXXu0mjf DD(6R{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/militarywebbing.rsi/icon.png b/Resources/Textures/Clothing/Belt/militarywebbing.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5767c157047206c7a97f63197b9a54f1576cb62f GIT binary patch literal 376 zcmV-;0f+vHP)RYPvCd)YX!?7R0!otGBUxYCx zbNoHL{H8b&A*J-~toW_9(|O;x1OVU+0dm_Qgs8q4BSHuuB33Rofs_)62q6T75FXB2 zop~Aot#u}%<}Hg~Yn_kdnEDMY0z?F*6k?1`5=tp}@27LVatHu`_Z~tBq?BsAi!Fp; z6$cm{Fveu1R3$O80pyu&7!tVdwv-aU*Tj!(?|uEYN2E*Oe(Uo*>)DJw(~YSaD7TVQ zvh5MN9Z*U^N(tv2Qc7^n0l>rlx9k$X?>hj%TKi*-?vNDOy(hm4PRj;>ZQClD)-M=N zX&Izzkr9E9n;O1%L}^N`iUMAV^l*(GDI!Y=%RA6pD`QM9aZiQTn)TLm;};hGFFpaj WTg$10we&3j0000?4k{S1y zJK*5oME=(fp>G*#=Iie-+kN+mt$aF%^UtbJiW=qi?jPElcuUn|M82i z0awpin*WIIxwwU6+5Lu1IuG}@7xNjqSv=nmwYI=Q#x4D*gzo=azG_5)jN@6BG^YkMR~E^(UTN`XUfa&uN!wrqd5 fwYaU}MW#I$|IVdyf-5wDF~Z>K>gTe~DWM4f>{`qQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/militarywebbing.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/militarywebbing.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8280138ae7516e8099c3829e2ec1c711cff76f7e GIT binary patch literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVC?dAaSW-L^Y)fu-ys75)(hvg zc=MDVa$j&=xr0HJeTH;_C*OupJ%_h#M!eH9-Y9u2R20gX`@lir=H35RIg@?dw#}Ao z=zxJ2@-s_)yF7Rw{QgzE`Sx3@>;8`SXH4!$&x`AO^?6b9zp5s@; zelX$8yhb%f=Y7V@>=jbB%xk={seDcQUq;2`FFbdq?c09)ZG!v4aHd(CDkG<9oEFNQ zweM+6+r8COn!d}0hAv#S>fk)tT9#c^Y%WXczQ=y>d1>vo-a28;yvA*pz6&f8Hb^_~ o5Gb-4$XQ*L8-4A5=f64JkAQ|w-~MGAFmf0?UHx3vIVCg!09YB%!2kdN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/militarywebbing.rsi/meta.json b/Resources/Textures/Clothing/Belt/militarywebbing.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/militarywebbing.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/security.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/security.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..b04e3d4b7b776d7f89c3fb3d8b17d7a7088f6fc5 GIT binary patch literal 366 zcmV-!0g?WRP)7@C6pAj+n&6qAs@HMDsWWA;GN%Z()MZrMrY`sJX&c0ZP~+{igA>#Cl0)$w-p{2y;O*55yud;kCd000000000N zqO18h8PA$D$(qS{)-3ZpdUJA_=gsHLQ)>K9@O;2A=d6liF6ZpQyg)3A>F6NySm=zv z$rm8)`tw~MZ~O8Ok5AF2Lt1S{*DOHv8HKNI_AmPK=Tr*-0KmWW0p&Q2k(y9EMgRZ+ M07*qoM6N<$g4T|y#{d8T literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/security.rsi/icon.png b/Resources/Textures/Clothing/Belt/security.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3b17da538df06296d6ef747773d2e7c431bd2c0d GIT binary patch literal 452 zcmV;#0XzPQP)v*Vrrg4#W=aB2?(I6c9)O2@_0-0vCVl2`1r- zpe23%x&;z!+O%oYFKf4EQl95+c-C6)`tNg2xoZ z>^HFA@2RS)OB{@6Dr$`}1CZb`rH?s)=kp1Cw?0i%gb=gs)LQR^5Q8oRk15S=0l@iu z2HbmaY&N-A)NGZFRloF*B&bcmD*ELC!47|p)*a3hjiaLlm zj=O#Rr!@e7ivs5yaU6HaqbOQqy$sN=3g}wwz2{G!10drVAp~Vv0?;%KP1CFbSUiYc uWB+p(^y6;&C>Vat910000Ip-E*Y*u+O#+Gw7%RBPcfg;jW)p>6h?Y(!Z>O{o62<8PCjd=l7brKQx zv#zGOBH~naG7WWfK))IA{dkz>G6Op4HUny{W|_6tac011k3j$c000000KgR?1lyfh zXXby4&-46co!L{D&Cp$45JFf}O6~amY{t;5v17NTl-euZ*QEg4w%Kk*|FD1C%d$+z z>)9?C_6Yn}*$Ex>*r@9co9%nGo7_)^N#D)SX@dknwh#wn$?7ykJA4D)^aok9rf naq^c^o_8F-k2Bh@PkfSJD=%zZmgvjU00000NkvXXu0mjfklLF# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/security.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/security.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..2489dcd7ec23c35c0bc39cefef4cf9daed9e79b6 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU^Mr1aSW-L^Y-RhuOkKm>>n~6 z-Z#dcKPBV(Lb_#7Yo+u3Me73u`kUvyJ# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/security.rsi/meta.json b/Resources/Textures/Clothing/Belt/security.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/security.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/securitywebbing.rsi/equipped-BELT.png b/Resources/Textures/Clothing/Belt/securitywebbing.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..42d3c6a6295c5077c6283f6a3ef3b6c83f85805e GIT binary patch literal 867 zcmV-p1DyPcP)!vZ546^fh#EqP2wH1b zRaMkgk+I|l8vp>98GnD}FVE*$mu@<9GMfR`HlMZb)K{3C}FUN5V zX2xo@!eX&#l+29paU9ZJCzu)2=@hHgs!=j?r~Xffthi8 zd;4aolU2LNSR;@h7&O5jxq05>-`{{0VSKA%T^ zkt3qUEHiVXJ*3~(FQ;khk|b$vKU?_rAq;R3ycgR;E`X!6@9+JtgzDMKRkJK}M1-;| zad~-(#bSXx&kx4U>-zbfqOE?xpTgJI*AW1mrK$UU0I{B?sq=$P({wm59klZg(eI!ag z%Wz(18y$tAIE0*mzB+VrS$`kz-G8iHfh^0M{}2nw38>R)8}xDJ2S3IiBCWN{^E{eN tCJmkTMw+JX5boj+MGrv`1VQ+O`~!;^NV;RSpXpT{@h1qcldRupc81Y@y{Yhk9jHf(VN zaaTp==H6nn{MDZ`XU_cmbLIdYI&|ppFT(fzQYYSo&$=6g5T$9F2qA6`tK$3p{?msE z0LZfp%d+r1ua3oWOqONZwX_9{MkBtOCND`y@*}C^UjW1PKUP3xzfuZU-L5A}X8OZ41f}76w;_r2vIJVOW@V|*=z>D;c#Fwnbdqd9@Fdf zYF_0#jsrjt1P?{D>H*ufNz;_=c3XexHQ()aH@w=H=Xqo8Mh8}_RcYHcQ52D78U21A zfXn65ichCg7K;UWp0i%B^&JR;fcbn5!1;Uz;QOyVhU@c^gaCK>&u^lx5k(Q3&E{yVO8LjryT|{Y18;7^YY|dPfL251I``RA)EY!ZQ6Qxx48w;-ecvyuym!UD-|u_o dcj)l{;x|Se%M>hP^%DR9002ovPDHLkV1id^-%tPm literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-left.png b/Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..dbce144c6084de943654b099a4a588cae4638495 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV669aaSW-L^Y)fuUz39f+k<*@ z6F=uiyBlN|eqsu%ZYXEgf62J*6VtWJ5tj@)&-yTO-u6gzQT|bI{muW?4k{S1y zJK*5oME=(fp>G*#=Iie-+kN+mt$aF%^UtbJiW=qi?jPElcuUn|M82i z0awpin*WIIxwwU6+5Lu1IuG}@7xNjqSv=nmwYI=Q#x4D*gzo=azG_5)jN@6BG^YkMR~E^(UTN`XUfa&uN!wrqd5 fwYaU}MW#I$|IVdyf-5wDF~Z>K>gTe~DWM4f>{`qQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/securitywebbing.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8280138ae7516e8099c3829e2ec1c711cff76f7e GIT binary patch literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEVC?dAaSW-L^Y)fu-ys75)(hvg zc=MDVa$j&=xr0HJeTH;_C*OupJ%_h#M!eH9-Y9u2R20gX`@lir=H35RIg@?dw#}Ao z=zxJ2@-s_)yF7Rw{QgzE`Sx3@>;8`SXH4!$&x`AO^?6b9zp5s@; zelX$8yhb%f=Y7V@>=jbB%xk={seDcQUq;2`FFbdq?c09)ZG!v4aHd(CDkG<9oEFNQ zweM+6+r8COn!d}0hAv#S>fk)tT9#c^Y%WXczQ=y>d1>vo-a28;yvA*pz6&f8Hb^_~ o5Gb-4$XQ*L8-4A5=f64JkAQ|w-~MGAFmf0?UHx3vIVCg!09YB%!2kdN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/securitywebbing.rsi/meta.json b/Resources/Textures/Clothing/Belt/securitywebbing.rsi/meta.json new file mode 100644 index 0000000000..6fd2d07a08 --- /dev/null +++ b/Resources/Textures/Clothing/Belt/securitywebbing.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/sheath.rsi/meta.json b/Resources/Textures/Clothing/Belt/sheath.rsi/meta.json new file mode 100644 index 0000000000..f2beb8d38f --- /dev/null +++ b/Resources/Textures/Clothing/Belt/sheath.rsi/meta.json @@ -0,0 +1,65 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "sheath-equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "sheath-sabre-equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "sheath-sabre", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "sheath", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Clothing/Belt/sheath.rsi/sheath-equipped-BELT.png b/Resources/Textures/Clothing/Belt/sheath.rsi/sheath-equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..eb54d79fd53baea52acc921dd23fe82370c3175f GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU}W-iaSW-L^Y+$3-a`gFtq3UvAx?_+e?ZmF=r9*Ix4}oPJe) zDep?m`gZLGoz?%(1#bt@`#at=U1iv0|9SQ6^MB54KYj4j*BP72Aoeh1M1R|Veszl6 z%y9pzP5oz_AAj^WGLL_&b5rx>gOZO|SEb(ncK(ok<#di9H2_U;XUHx3v IIVCg!0N;6!VE_OC literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/sheath.rsi/sheath-sabre-equipped-BELT.png b/Resources/Textures/Clothing/Belt/sheath.rsi/sheath-sabre-equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..b11ba9b56bb89bf6a4b19030aff51b39a349e134 GIT binary patch literal 500 zcmV15QU!tsRYL9tzOqrlM5JffgB{Y1HOPR;1j4aZiDN@xby}SS1KmOvOzWh@2*x@ zgWp#Qw0iTiD|Ti8LI@#*5JCtcaa1LwHMQJY$4#h8$ZP@u0MiueobV9yQa9S`J+M0> zOD9PQrYWQweE^VUt}X+jF-;)?{l-V7Zfk1!`FI5YOt%NS(EM~C+h7HVX$sLA@k@fD zwgTi6zy`p3WcG}Wpud0y;}@NC$p>!-tO6Il6&qM5`0Dj`fQIM;R^J9zuMb`h&=UPi zd~|y`Kuh!;Az5(M0opG)z4dGU=gTq|jTbaR2qA{|YHnb6M7G`oGEiwg z`4$kQF+Q80GM5EkZ#ll3B8|YIXiY7qDb6~_DXPgTD$@V8%vA_Sf=-Y2mU-_pK(q0^ zSpf2)v~lW)ikkMc?-INP#%z2{8$ZYaV>TYJ=TWE=f<|PAKg*w4|LS*d51LuPg q$u3Q;sYTmqpL8xj^MC{)Wx=str5WYg@Q(G&do7}`baJhv5WHJCi zhJBb%ZC0aQ;7wQiaeRfWqd=n2E35$5i6?05E2IpOtPmkyrej*1oOwjDH>{%|Ek6Ns zh$!^r{r*^d6*qbXaslQLN#jX*8wjfk0dRA-U1tn(4m<$MudDPswEg^tmvv;*6YR&BLRuSwYubNnbO!;Pi6oBC$V?&%ltJ{E<(pgx**3u;`Tz~~!Kr2IQW#s}`Xl3y%AWAfv-(otgM9VnvKmRk7Z9mIu4OLeb}SjFA|l&`3CIFC0>$I9e*RrU+l2*0 z^BU1ed=b`wP>5E55Qx?QZG;m*6X6WdLU;i*5Z(Y^gbKh1p$2e8r~+IN>VUS0Ab?MZ z*uduC{}Zz=0a=4AK{BeDqB+vZQUVm`Y=#f#DQU=@Z>ej&rG=9INZ^l_V$0bM?~N8wIXjkfhK{# zhklm+Mav~}H$*;8+O;RY{@CfwYt}aPExh>JWapZ%Cl|j+*sPMe_s`qEE9bFKXE=6L zWv#X1a=%^nS3ehg(6|+r7+W&+`_mxlt)Ua12sfSPo3LbEpVj$kSDBvQbP7Kn zG(*1pW#_9u`)=nuM6-VNJ#lM$t?-*$ett1bFJ7%E+^D2$pr`iU4B{FfdHV^U^S5Va zQn$VH9_+Vj2<|E4>0M&lq5Js9BgQ4HZxc8CtSU-*EwQeGVcv2}n|ZM&4R?eU?H5Kc zyi5pr=ki0YdfRR1SF;md#y|M>OKx|quKvrVw*8kF>u;!^(=7N^-SL|nWR<6@pUXO@ GgeCxsm7zZX literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/suspenders.rsi/inhand-right.png b/Resources/Textures/Clothing/Belt/suspenders.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..25c1b5429c545c6c515059950112a49dc0b29cf1 GIT binary patch literal 371 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV6^gdaSW-L^Y)f)UWjU#Z z7GJI14;W&U9tquPZGIEG!)1zh0RvaeQqHqWI`-UBGt+r?{M7GNQ_mc#FnOHDBOnL^ zf0c!zYU-QAS{H~l-!@^LzjxBPDA_BCb42IIKeXM~BKCJad#UE*+jINPw^b@kYB(3g z+E92+rBU|i@z;;}D|vN)8Li@CoZv6C%BgO0z!7cp2*$m^nO?JXHYl4eb$wqF&CPJ& z`1dJli<)(Nt!Fe`>$rDXQ+Z!*wDQFRi**gob=|qOKvVZvr1(|_n1g_H?Bz+0$D=M@ zj5s03D4Sc#WR-n2e~;Ma43^qd|Ih|`%e%`w`}Wubc600000z>ivf-MZJv)%lr?R$4v$c0W!=^RnNl z+N?1W=5lgs!}JC?X=acaN%nYBcLbyIeam$YdpJjNIHmsp{`(UhegWGI{@$ zUVkWqU@8}v2QmnzG8#{$QaIB5Y9ns#%DHBC&eQ_O7{_BC+U2p~d7!b`y1c_w0+AruKB&eFI4CmVHoC4eRTe90k zQt~&f7O}`S`?{I=+$`VQQhV>q{!56BZLx8==oQ|Zk~wMrzSEJxZt=~#au#JWXaSW-L^Y+%pyk-M|hKI_l zqE;>nOuHedf8dPr0f9Ip9~-9p#$OCGSDUT6!dJR%3x{h2-?6f(|7SZy6jRCDTS6!)Vg0d!=Ur0<8}q_M^6PU(}XsgF|I#;c~L?QQ1qR4g7NnaTE(S*>LzVJ zTUHog7m~WpmVJxp2l>C-4t(w|dz-^r@>f8$KYr8i%I!ikv?GPQryaTU)p<#D_4jrK zs6`Bot4{6N`uE&TdF6$jcJ|-4-OrrUu*-vgaklBc_{&ne^^2leO(s8VJ{D$haP_G@ zbN%A3xURZ(Ywk(~wa|5{2acAnSG~`s-M*lk>&35yf*a=-EN0oE^;L3h$MY}=|Ae2j u6gKY^+`i>NiTIrGqf2G?a4nE!;669?Z)oMNU2=~=Zt!&Vb6Mw<&;$T`9G3?G literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Belt/utility.rsi/meta.json b/Resources/Textures/Clothing/Belt/utility.rsi/meta.json new file mode 100644 index 0000000000..d1facf554c --- /dev/null +++ b/Resources/Textures/Clothing/Belt/utility.rsi/meta.json @@ -0,0 +1,38 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "states": [ + { + "name": "equipped-BELT", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/meta.json b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/meta.json index d1d5eee5b6..147cef6c90 100644 --- a/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/meta.json +++ b/Resources/Textures/Constructible/Structures/Doors/airlock_maint.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint.dmi", + "copyright": "Taken from https://github.com/discordia-space/CEV-Eris/blob/d86e175508b8553ca8396f39f2af7ecec4595375/icons/obj/doors/Doormaint.dmi - modified by rexonaje#5787 on discord", "states": [ { "name": "bolted", diff --git a/Resources/Textures/Objects/Tools/welder.rsi/welder.png b/Resources/Textures/Objects/Tools/welder.rsi/icon.png similarity index 100% rename from Resources/Textures/Objects/Tools/welder.rsi/welder.png rename to Resources/Textures/Objects/Tools/welder.rsi/icon.png diff --git a/Resources/Textures/Objects/Tools/welder.rsi/meta.json b/Resources/Textures/Objects/Tools/welder.rsi/meta.json index a000fa54c8..c18016dab0 100644 --- a/Resources/Textures/Objects/Tools/welder.rsi/meta.json +++ b/Resources/Textures/Objects/Tools/welder.rsi/meta.json @@ -1,112 +1,110 @@ { - "version": 1, - "size": { - "x": 32, - "y": 32 + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/199fffd989d6f7fd6ea9c5188c875137df4f34b8", + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] }, - "states": [ - { - "name": "welder", - "select": [], - "flags": {}, - "directions": 1, - "delays": [ - [ - 1.0 - ] - ] - }, - { - "name": "welder_flame", - "select": [], - "flags": {}, - "directions": 1, - "delays": [ - [ - 0.2, - 0.1 - ] - ] - }, - { - "name": "on-inhand-left", - "directions": 4, - "delays": [ - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ] - ] - }, - { - "name": "on-inhand-right", - "directions": 4, - "delays": [ - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ], - [ - 0.2, - 0.1 - ] - ] - }, - { - "name": "off-inhand-left", - "directions": 4, - "delays": [ - [ - 1 - ], - [ - 1 - ], - [ - 1 - ], - [ - 1 - ] - ] - }, - { - "name": "off-inhand-right", - "directions": 4, - "delays": [ - [ - 1 - ], - [ - 1 - ], - [ - 1 - ], - [ - 1 - ] - ] - } - ] + { + "name": "welder_flame", + "directions": 1, + "delays": [ + [ + 0.2, + 0.1 + ] + ] + }, + { + "name": "off-inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "off-inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "on-inhand-left", + "directions": 4, + "delays": [ + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ] + ] + }, + { + "name": "on-inhand-right", + "directions": 4, + "delays": [ + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ], + [ + 0.2, + 0.1 + ] + ] + } + ] } diff --git a/Resources/Textures/Objects/Tools/welder_experimental.rsi/icon.png b/Resources/Textures/Objects/Tools/welder_experimental.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2a36d550027e42f9a1071b68423d997ed493d3d1 GIT binary patch literal 583 zcmV-N0=WH&P)fFDZ*Bkpc$`yKaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainGjE%TBGg33t zGfE(w;*!LYR3K9+wW2&VCndE=iHkEOv#1y-WXQ#tR+N~V3Syf8MN@MUD?!3KV92Gc z;OgfBwh927dLLCp7n+~|00AROL_t(oh3%GYZ-gKagm+w5_PnESRL{(2A0L`zVM>sR1y_Ixb_Xszt%)+9l{(SL|6)P`&|GMXw*|6aR zeS7~fj;{s8c6Knv=;xNl0vo>0z-tGv7*v&ZeCgnphfj3871k)XYS=8n5f2VQD>5Q# zx8emJw#ltBqG8+{N_^I^>Q9^?!XWkU_M4xfx2_b?A?%AU8vad&9RsrMYb?arf71IONI0eg_XE zIess%s;YXXd~lwx-&{VJFYi+}AH)K=d=Lv{^TEA5{I5egML? VA_;lcqvQYp002ovPDHLkV1h4%^UweQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/welder_experimental.rsi/meta.json b/Resources/Textures/Objects/Tools/welder_experimental.rsi/meta.json new file mode 100644 index 0000000000..ed824e60cf --- /dev/null +++ b/Resources/Textures/Objects/Tools/welder_experimental.rsi/meta.json @@ -0,0 +1,121 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/199fffd989d6f7fd6ea9c5188c875137df4f34b8", + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "welder_flame", + "directions": 1, + "delays": [ + [ + 0.2, + 0.1 + ] + ] + }, + { + "name": "off-inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "off-inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "on-inhand-left", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "on-inhand-right", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-left.png b/Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..045e42531c729bbc364e19bb0916cc59daab13d4 GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|ei2$DvS0JsXrZ$ry&ClCgQBg6C zAuT;U{e^@?UE}_2pd4dKkY6x^!?PP{Ku&H|NJNQCYH@N=WKhlO#F@nvH#g*lHV9hnrO5Uja% zk&UUk>Q;}=Ze!KWD04*-_ba4#v z=uA$KU|q~$EpQ-V0h60+vN9_hn`*MNtBe}Q?v6IqC9Pc+j}00d*D^RwpZMC%xh0!t z!%1WA7me57mhEuae+JYD@<);T3K0RZ{#8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-right.png b/Resources/Textures/Objects/Tools/welder_experimental.rsi/off-inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..45628f9983c3d0f774a319fc02e07f58b68902c9 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|ei2$Dv*Z=?jtEs8YWJvS#_D)Yv zPh&_^R8)K+A+b$P{2ovZV@Z%-FoVOh8)-mJZdFJ`iA!p6a#3bMNoIZ?14G4};IM+C z((hk_3qF2*qUEitb?(gh;0>V$7mXi0(mC&=d6J>1r+0^iaggz4V=sj{k0u?N6rvEU zxpk3^sk-V`kIrsm)y*p;mh^WUuhlR#7d>M3Bq*%lYcb<&9)`ISrSsf54krLDZuWF> z4DskpPLN<-%)ra>Ks3zAEaZsR`4t&COAZ`(Afz>|=P=7dlZyi40*hJN&+4$cSWmjh zFnfh!(@C8kS2EaktG3V{v{aLpIMB4kk z_LQzLcYfZH^ntr%Rl4)Mg~5LrYWr*&Y`>~*s(v+1Goi~!e2;2tp5C3J)YCIe%GSTB z{S`1ShIgxczl597Q2%Vy91 zT~NFC=hcgMe-~M9%l!8DAqupWrJ{ifA%R^QhN$2(>Gn|16n`?ghk|0rHnd?DF?Jn!P`w>Bbw`#NH4JpPrfTlFtX zdeilP9|AU+q)%D0;&r|7?j5r)p3u}k@O+wlXaoQMk3TYQi_cTDJpJd!bBFzcllJak zmbY)$zZKURR``F(X1K!4m?WUUMk-P8YEIPr`ZI2;Cd^xLrz=Jb$*q z{j~6}JAY4mJ;VB&>Z+R3zcb$l&;M`s`E4vpgo3~=;lA2wMkAARp;9)wVKrV51 zqrU0hCqJ2dpZwo$J?ke^=Ii^nrC;4&`+oYWpG>dqentH>td8Yhxxeh+zQf7!^7Ycs zxJ@SR|IT5tyzW2O*Ux;VpBLX@HH?4o;g1H>t$%g@7k}#C%e#8V5s-<@ptS68+FKT_S?MwtNl(be)qHY^Lw#2_Gxp|9zQ6* zol~-R&r7@b*qiP8`D?GgZatbbap@lE(4Vh9n*Y*&ulFcP)#Uu=M>QAT-|n0nc}o2M zaewa5(Z-?ss{Z)zGu^i>D$zzRKlRto65)R*ZchJmroN$1JakemUrl|9igD=kKVD4t zWaPw(7kfFa{k-~I=zBNim&Y&edbXLZW2FhJqm_UH8)Fjb#3arSR`ZK8c2BzRAsYAX z)!u92Mzi+no$EVnqFw!S)gO_ap`Y2!gSC&(b7}bg^7Mz(Kll8I-+Xh+w7anl`+wX! z{e3UvdZ~}9A!o})em39#t<+^7^v!Z_{CnHq%jNz@>(@*FTv@!jXa63yT?>;I=^u)F z7^c^-dzyS`Lwj|9UFpM{YSuI5tM4VtAFTShhB4`fnhsf>5Kwp)$#jGH!=FFBuV21l z>@fb<%esMG;nI)bvImFd-ZQS4Hx#;x0+n&HvY^|}qV3==HYaZfQYryHA+84w9GEfV$B6_Wn(<>s z!Ve&skdW}>$B7?5egGvrBz~NjaoNPu7pR`GB*-tA!Qt7BG$5zCDkP%BCAB!YD6^m> zGe3`kp<+&OSV2+g_bJZhXNCOYs3r?@pfj{RT^vI!dXp0*SR)!HaB9VyFit&x&xm{K{oYgT nuRI)$FE(iLNwY3)n8(0yZvyiP_hmdaKy3`3u6{1-oD!M<(iwDq literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/welder_mini.rsi/icon.png b/Resources/Textures/Objects/Tools/welder_mini.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..87e788279279b5953112f922eb5ab60613d1ce7b GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvl>na**8>L*XlZI1n3}KFRn3tV zck>H~&B&Uxc76Nw8Cm5O^R$%g-8^23uYV6z&sY-V7tG-B>_!@plUEfIQR0$XoLrPy zP?DLS$G}iACpfI2sPy}n;DV1|pJ;jOYMncCK6pc@!A0W-k95xaXr5#!>gnBKVH{+9 z+1N{A&Z9|3CWR;jYnmJDZ?-X2SKaE-*=?-4d4+^V#)+dd!=}ub&6TLFz2n!;hO=x8 z4{pj>uVh(w8)&nKr;B5V#>C_ViGL0PooAOES+FESsX-usHG4~`%iETXc3=HNQx%d5Dx^E58Oa@O^KbLh* G2~7Z30C4gE literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/welder_mini.rsi/meta.json b/Resources/Textures/Objects/Tools/welder_mini.rsi/meta.json new file mode 100644 index 0000000000..0c308b9e1d --- /dev/null +++ b/Resources/Textures/Objects/Tools/welder_mini.rsi/meta.json @@ -0,0 +1,30 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/199fffd989d6f7fd6ea9c5188c875137df4f34b8", + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "welder_flame", + "directions": 1, + "delays": [ + [ + 0.2, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Tools/welder_mini.rsi/welder_flame.png b/Resources/Textures/Objects/Tools/welder_mini.rsi/welder_flame.png new file mode 100644 index 0000000000000000000000000000000000000000..f080d7bcaad99b2fb51d1e95017f7b288725fb12 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQYryHA+84w9GE%t|Cux(n)!cb z+J7LKmX`Ma|C#?l3>2C9-&3aL^t&jadd89=K{ci#X2 literal 0 HcmV?d00001 From 6e3cc9e78aa278d982615a334615b68ed29d9c3c Mon Sep 17 00:00:00 2001 From: Exp Date: Sun, 8 Nov 2020 13:43:13 +0100 Subject: [PATCH 34/41] PDA Pen Holder (#2519) * -Adds pens to pdas -Adds eject pen verb * Reviews: -Changed Container into ContainerSlot -Starting prototypes are now nullable -Removed double GetComp call * EjectPen Button --- .../Components/PDA/PDABoundUserInterface.cs | 26 ++- .../Components/PDA/PDAComponent.cs | 154 +++++++++++++++--- .../Components/PDA/SharedPDAComponent.cs | 24 ++- 3 files changed, 169 insertions(+), 35 deletions(-) diff --git a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs index b5ad84b435..1ba1ce1eea 100644 --- a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs @@ -23,7 +23,7 @@ namespace Content.Client.GameObjects.Components.PDA [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; private PDAMenu _menu; - private PDAMenuPopup failPopup; + private PDAMenuPopup _failPopup; public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) { @@ -47,6 +47,11 @@ namespace Content.Client.GameObjects.Components.PDA SendMessage(new PDAEjectIDMessage()); }; + _menu.EjectPenButton.OnPressed += args => + { + SendMessage(new PDAEjectPenMessage()); + }; + _menu.MasterTabContainer.OnTabChanged += i => { var tab = _menu.MasterTabContainer.GetChild(i); @@ -60,12 +65,12 @@ namespace Content.Client.GameObjects.Components.PDA { if (_menu.CurrentLoggedInAccount.DataBalance < listing.Price) { - failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!")); - _userInterfaceManager.ModalRoot.AddChild(failPopup); - failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24)); + _failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!")); + _userInterfaceManager.ModalRoot.AddChild(_failPopup); + _failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24)); _menu.OnClose += () => { - failPopup.Dispose(); + _failPopup.Dispose(); }; } @@ -106,6 +111,7 @@ namespace Content.Client.GameObjects.Components.PDA } _menu.EjectIDButton.Visible = msg.PDAOwnerInfo.IdOwner != null; + _menu.EjectPenButton.Visible = msg.HasPen; if (msg.Account != null) { _menu.CurrentLoggedInAccount = msg.Account; @@ -220,6 +226,7 @@ namespace Content.Client.GameObjects.Components.PDA public Button FlashLightToggleButton { get; } public Button EjectIDButton { get; } + public Button EjectPenButton { get; } public TabContainer MasterTabContainer; @@ -288,13 +295,20 @@ namespace Content.Client.GameObjects.Components.PDA SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter }; + EjectPenButton = new Button + { + Text = Loc.GetString("Eject Pen"), + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + SizeFlagsVertical = SizeFlags.ShrinkCenter + }; var innerHBoxContainer = new HBoxContainer { Children = { IDInfoLabel, - EjectIDButton + EjectIDButton, + EjectPenButton } }; diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs index 58bdc2a1b8..bfec94de05 100644 --- a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs +++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Paper; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Interfaces.PDA; @@ -39,13 +40,19 @@ namespace Content.Server.GameObjects.Components.PDA [Dependency] private readonly IPDAUplinkManager _uplinkManager = default!; [Dependency] private readonly IEntityManager _entityManager = default!; - [ViewVariables] private Container _idSlot = default!; + [ViewVariables] private ContainerSlot _idSlot = default!; + [ViewVariables] private ContainerSlot _penSlot = default!; + [ViewVariables] private bool _lightOn; - [ViewVariables] private string _startingIdCard = default!; - [ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1; + + [ViewVariables] private string? _startingIdCard = default!; + [ViewVariables] private string? _startingPen = default!; + [ViewVariables] public string? OwnerName { get; private set; } [ViewVariables] public IdCardComponent? ContainedID { get; private set; } + [ViewVariables] public bool IdSlotEmpty => _idSlot.ContainedEntity == null; + [ViewVariables] public bool PenSlotEmpty => _penSlot.ContainedEntity == null; [ViewVariables] private UplinkAccount? _syndicateUplinkAccount; @@ -62,22 +69,34 @@ namespace Content.Server.GameObjects.Components.PDA { base.ExposeData(serializer); serializer.DataField(ref _startingIdCard, "idCard", "AssistantIDCard"); + serializer.DataField(ref _startingPen, "pen", "Pen"); } public override void Initialize() { base.Initialize(); - _idSlot = ContainerManagerComponent.Ensure("pda_entity_container", Owner, out var existed); + _idSlot = ContainerManagerComponent.Ensure("pda_entity_container", Owner); + _penSlot = ContainerManagerComponent.Ensure("pda_pen_slot", Owner); if (UserInterface != null) { UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage; } - var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates); - var idCardComponent = idCard.GetComponent(); - _idSlot.Insert(idCardComponent.Owner); - ContainedID = idCardComponent; + if (!string.IsNullOrEmpty(_startingIdCard)) + { + var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.Coordinates); + var idCardComponent = idCard.GetComponent(); + _idSlot.Insert(idCardComponent.Owner); + ContainedID = idCardComponent; + } + + if (!string.IsNullOrEmpty(_startingPen)) + { + var pen = _entityManager.SpawnEntity(_startingPen, Owner.Transform.Coordinates); + _penSlot.Insert(pen); + } + UpdatePDAAppearance(); } @@ -85,23 +104,29 @@ namespace Content.Server.GameObjects.Components.PDA { switch (message.Message) { - case PDARequestUpdateInterfaceMessage msg: + case PDARequestUpdateInterfaceMessage _: { UpdatePDAUserInterface(); break; } - case PDAToggleFlashlightMessage msg: + case PDAToggleFlashlightMessage _: { ToggleLight(); break; } - case PDAEjectIDMessage msg: + case PDAEjectIDMessage _: { HandleIDEjection(message.Session.AttachedEntity!); break; } + case PDAEjectPenMessage _: + { + HandlePenEjection(message.Session.AttachedEntity!); + break; + } + case PDAUplinkBuyListingMessage buyMsg: { if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ItemId)) @@ -131,11 +156,11 @@ namespace Content.Server.GameObjects.Components.PDA var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder, _syndicateUplinkAccount.Balance); var listings = _uplinkManager.FetchListings.Values.ToArray(); - UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo, accData, listings)); + UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo, accData, listings)); } else { - UserInterface?.SetState(new PDAUpdateState(_lightOn, ownerInfo)); + UserInterface?.SetState(new PDAUpdateState(_lightOn, !PenSlotEmpty, ownerInfo)); } UpdatePDAAppearance(); @@ -150,14 +175,11 @@ namespace Content.Server.GameObjects.Components.PDA } } - public async Task InteractUsing(InteractUsingEventArgs eventArgs) + private bool TryInsertIdCard(InteractUsingEventArgs eventArgs, IdCardComponent idCardComponent) { var item = eventArgs.Using; - - if (!item.TryGetComponent(out var idCardComponent) || _idSlot.Contains(item)) - { + if (_idSlot.Contains(item)) return false; - } if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands)) { @@ -177,17 +199,70 @@ namespace Content.Server.GameObjects.Components.PDA return true; } - InsertIdCard(idCardComponent); - if (swap != null) { - eventArgs.User.GetComponent().PutInHand(swap.GetComponent()); + hands.PutInHand(swap.GetComponent()); } + InsertIdCard(idCardComponent); + UpdatePDAUserInterface(); return true; } + private bool TryInsertPen(InteractUsingEventArgs eventArgs) + { + var item = eventArgs.Using; + if (_penSlot.Contains(item)) + return false; + + if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands)) + { + Owner.PopupMessage(eventArgs.User, Loc.GetString("You have no hands!")); + return true; + } + + IEntity? swap = null; + if (!PenSlotEmpty) + { + // Swap + swap = _penSlot.ContainedEntities[0]; + } + + if (!hands.Drop(item)) + { + return true; + } + + if (swap != null) + { + hands.PutInHand(swap.GetComponent()); + } + + // Insert Pen + _penSlot.Insert(item); + + UpdatePDAUserInterface(); + return true; + } + + public async Task InteractUsing(InteractUsingEventArgs eventArgs) + { + var item = eventArgs.Using; + + if (item.TryGetComponent(out var idCardComponent)) + { + return TryInsertIdCard(eventArgs, idCardComponent); + } + + if (item.HasComponent()) + { + return TryInsertPen(eventArgs); + } + + return false; + } + void IActivate.Activate(ActivateEventArgs eventArgs) { if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) @@ -273,6 +348,21 @@ namespace Content.Server.GameObjects.Components.PDA UpdatePDAUserInterface(); } + private void HandlePenEjection(IEntity pdaUser) + { + if (PenSlotEmpty) + return; + + var pen = _penSlot.ContainedEntities[0]; + _penSlot.Remove(pen); + + var hands = pdaUser.GetComponent(); + var itemComponent = pen.GetComponent(); + hands.PutInHandOrDrop(itemComponent); + + UpdatePDAUserInterface(); + } + [Verb] public sealed class EjectIDVerb : Verb { @@ -294,6 +384,28 @@ namespace Content.Server.GameObjects.Components.PDA } } + [Verb] + public sealed class EjectPenVerb : Verb + { + protected override void GetData(IEntity user, PDAComponent component, VerbData data) + { + if (!ActionBlockerSystem.CanInteract(user)) + { + data.Visibility = VerbVisibility.Invisible; + return; + } + + data.Text = Loc.GetString("Eject Pen"); + data.Visibility = component.PenSlotEmpty ? VerbVisibility.Invisible : VerbVisibility.Visible; + } + + protected override void Activate(IEntity user, PDAComponent component) + { + component.HandlePenEjection(user); + } + } + + [Verb] public sealed class ToggleFlashlightVerb : Verb { protected override void GetData(IEntity user, PDAComponent component, VerbData data) diff --git a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs index c34d57ca9b..ceaabec258 100644 --- a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs +++ b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs @@ -30,6 +30,15 @@ namespace Content.Shared.GameObjects.Components.PDA } } + [Serializable, NetSerializable] + public sealed class PDAEjectPenMessage : BoundUserInterfaceMessage + { + public PDAEjectPenMessage() + { + + } + } + [Serializable, NetSerializable] public class PDAUBoundUserInterfaceState : BoundUserInterfaceState { @@ -40,28 +49,27 @@ namespace Content.Shared.GameObjects.Components.PDA public sealed class PDAUpdateState : PDAUBoundUserInterfaceState { public bool FlashlightEnabled; + public bool HasPen; public PDAIdInfoText PDAOwnerInfo; public UplinkAccountData Account; public UplinkListingData[] Listings; - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo) { FlashlightEnabled = isFlashlightOn; + HasPen = hasPen; PDAOwnerInfo = ownerInfo; } - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo, UplinkAccountData accountData) + : this(isFlashlightOn, hasPen, ownerInfo) { - FlashlightEnabled = isFlashlightOn; - PDAOwnerInfo = ownerInfo; Account = accountData; } - public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData, UplinkListingData[] listings) + public PDAUpdateState(bool isFlashlightOn, bool hasPen, PDAIdInfoText ownerInfo, UplinkAccountData accountData, UplinkListingData[] listings) + : this(isFlashlightOn, hasPen, ownerInfo, accountData) { - FlashlightEnabled = isFlashlightOn; - PDAOwnerInfo = ownerInfo; - Account = accountData; Listings = listings; } } From d45072495eedfc894253a7e6af7ac3318cc0aa3c Mon Sep 17 00:00:00 2001 From: Exp Date: Sun, 8 Nov 2020 13:44:04 +0100 Subject: [PATCH 35/41] Adds a live preview to the character customizer (#2523) * Preview * -Dispose Dummy -Unsubscribe from OnServerDataLoaded --- .../UserInterface/CharacterSetupGui.cs | 15 ++- .../UserInterface/HumanoidProfileEditor.cs | 121 ++++++++++++++++-- 2 files changed, 121 insertions(+), 15 deletions(-) diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index 631e5ad55a..d93c8b7a59 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -149,7 +149,7 @@ namespace Content.Client.UserInterface PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold}, CustomMinimumSize = (2, 0) }); - _humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager); + _humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager, entityManager); _humanoidProfileEditor.OnProfileChanged += newProfile => { UpdateUI(); }; hBox.AddChild(_humanoidProfileEditor); @@ -158,6 +158,15 @@ namespace Content.Client.UserInterface preferencesManager.OnServerDataLoaded += UpdateUI; } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _preferencesManager.OnServerDataLoaded -= UpdateUI; + } + public void Save() => _humanoidProfileEditor.Save(); private void UpdateUI() @@ -283,7 +292,9 @@ namespace Content.Client.UserInterface protected override void Dispose(bool disposing) { base.Dispose(disposing); - if (!disposing) return; + if (!disposing) + return; + _previewDummy.Delete(); _previewDummy = null; } diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index 8aa4d74254..b6aca525ae 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -1,22 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Content.Client.GameObjects.Components; +using Content.Client.GameObjects.Components; +using Content.Client.GameObjects.Components.Mobs; using Content.Client.Interfaces; -using Content.Shared; using Content.Shared.GameTicking; using Content.Shared.Preferences; using Content.Shared.Roles; +using Robust.Client.GameObjects; using Robust.Client.Graphics.Drawing; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.Utility; +using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; using Robust.Shared.Localization; +using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Prototypes; using Robust.Shared.Utility; +using System; +using System.Collections.Generic; +using System.Linq; namespace Content.Client.UserInterface { @@ -43,17 +46,25 @@ namespace Content.Client.UserInterface private readonly OptionButton _preferenceUnavailableButton; private readonly List _antagPreferences; + private readonly IEntity _previewDummy; + private readonly SpriteView _previewSprite; + private readonly SpriteView _previewSpriteSide; + private bool _isDirty; public int CharacterSlot; public HumanoidCharacterProfile Profile; public event Action OnProfileChanged; - public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager) + public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IPrototypeManager prototypeManager, IEntityManager entityManager) { _random = IoCManager.Resolve(); _preferencesManager = preferencesManager; + var hbox = new HBoxContainer(); + AddChild(hbox); + + #region Left var margin = new MarginContainer { MarginTopOverride = 10, @@ -61,7 +72,7 @@ namespace Content.Client.UserInterface MarginLeftOverride = 10, MarginRightOverride = 10 }; - AddChild(margin); + hbox.AddChild(margin); var vBox = new VBoxContainer(); margin.AddChild(vBox); @@ -98,7 +109,7 @@ namespace Content.Client.UserInterface { SizeFlagsVertical = SizeFlags.FillExpand }; - var nameLabel = new Label {Text = Loc.GetString("Name:")}; + var nameLabel = new Label { Text = Loc.GetString("Name:") }; _nameEdit = new LineEdit { CustomMinimumSize = (270, 0), @@ -119,7 +130,7 @@ namespace Content.Client.UserInterface #endregion Name - var tabContainer = new TabContainer {SizeFlagsVertical = SizeFlags.FillExpand}; + var tabContainer = new TabContainer { SizeFlagsVertical = SizeFlags.FillExpand }; vBox.AddChild(tabContainer); #region Appearance @@ -141,7 +152,7 @@ namespace Content.Client.UserInterface { var panel = HighlightedContainer(); var hBox = new HBoxContainer(); - var sexLabel = new Label {Text = Loc.GetString("Sex:")}; + var sexLabel = new Label { Text = Loc.GetString("Sex:") }; var sexButtonGroup = new ButtonGroup(); @@ -171,8 +182,8 @@ namespace Content.Client.UserInterface { var panel = HighlightedContainer(); var hBox = new HBoxContainer(); - var ageLabel = new Label {Text = Loc.GetString("Age:")}; - _ageEdit = new LineEdit {CustomMinimumSize = (40, 0)}; + var ageLabel = new Label { Text = Loc.GetString("Age:") }; + _ageEdit = new LineEdit { CustomMinimumSize = (40, 0) }; _ageEdit.OnTextChanged += args => { if (!int.TryParse(args.Text, out var newAge)) @@ -348,7 +359,7 @@ namespace Content.Client.UserInterface foreach (var antag in prototypeManager.EnumeratePrototypes().OrderBy(a => a.Name)) { - if(!antag.SetPreference) + if (!antag.SetPreference) { continue; } @@ -410,6 +421,71 @@ namespace Content.Client.UserInterface #endregion Save + #endregion + + #region Right + + margin = new MarginContainer + { + MarginTopOverride = 10, + MarginBottomOverride = 10, + MarginLeftOverride = 10, + MarginRightOverride = 10 + }; + hbox.AddChild(margin); + + vBox = new VBoxContainer() + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + }; + hbox.AddChild(vBox); + + #region Preview + + _previewDummy = entityManager.SpawnEntity("HumanMob_Dummy", MapCoordinates.Nullspace); + var sprite = _previewDummy.GetComponent(); + + // Front + var box = new Control() + { + SizeFlagsHorizontal = SizeFlags.Fill, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 1f, + }; + vBox.AddChild(box); + _previewSprite = new SpriteView + { + Sprite = sprite, + Scale = (6, 6), + OverrideDirection = Direction.South, + SizeFlagsVertical = SizeFlags.ShrinkCenter, + SizeFlagsStretchRatio = 1 + }; + box.AddChild(_previewSprite); + + // Side + box = new Control() + { + SizeFlagsHorizontal = SizeFlags.Fill, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 1f, + }; + vBox.AddChild(box); + _previewSpriteSide = new SpriteView + { + Sprite = sprite, + Scale = (6, 6), + OverrideDirection = Direction.East, + SizeFlagsVertical = SizeFlags.ShrinkCenter, + SizeFlagsStretchRatio = 1 + }; + box.AddChild(_previewSpriteSide); + + #endregion + + #endregion + if (preferencesManager.ServerDataLoaded) { LoadServerData(); @@ -420,6 +496,16 @@ namespace Content.Client.UserInterface IsDirty = false; } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _previewDummy.Delete(); + _preferencesManager.OnServerDataLoaded -= LoadServerData; + } + private void LoadServerData() { Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences.SelectedCharacter; @@ -458,6 +544,7 @@ namespace Content.Client.UserInterface set { _isDirty = value; + UpdatePreview(); UpdateSaveButton(); } } @@ -503,6 +590,12 @@ namespace Content.Client.UserInterface _saveButton.Disabled = Profile is null || !IsDirty; } + private void UpdatePreview() + { + _previewDummy.GetComponent().UpdateFromProfile(Profile); + LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, Profile); + } + public void UpdateControls() { if (Profile is null) return; @@ -514,6 +607,8 @@ namespace Content.Client.UserInterface UpdateJobPriorities(); UpdateAntagPreferences(); + UpdatePreview(); + _preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable); } From bdc4441a45400b610feda8b033a3f90cb45bbbcd Mon Sep 17 00:00:00 2001 From: Swept Date: Sun, 8 Nov 2020 19:24:17 +0000 Subject: [PATCH 36/41] Adds rainbow jumpsuit (#2149) * Initial * Fixes attribution * Fixed * Fixed * Update Resources/Textures/Clothing/Uniforms/rainbow.rsi/meta.json Co-authored-by: DrSmugleaf --- .../Entities/Clothing/Uniforms/color.yml | 13 +++ .../Clothing/Uniforms/color.rsi/meta.json | 6 +- .../rainbow.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 911 bytes .../Clothing/Uniforms/rainbow.rsi/icon.png | Bin 0 -> 382 bytes .../Uniforms/rainbow.rsi/inhand-left.png | Bin 0 -> 339 bytes .../Uniforms/rainbow.rsi/inhand-right.png | Bin 0 -> 339 bytes .../Clothing/Uniforms/rainbow.rsi/meta.json | 74 ++++++++++++++++++ 7 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Clothing/Uniforms/rainbow.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/Clothing/Uniforms/rainbow.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Uniforms/rainbow.rsi/meta.json diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/color.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/color.yml index 152f013169..d496a33015 100644 --- a/Resources/Prototypes/Entities/Clothing/Uniforms/color.yml +++ b/Resources/Prototypes/Entities/Clothing/Uniforms/color.yml @@ -460,3 +460,16 @@ ClothingPrefix: maroon_skirt femaleMask: UniformTop HeldPrefix: maroon + +# Rainbow +- type: entity + parent: UniformColorBase + id: UniformColorRainbow + name: rainbow jumpsuit + description: A multi-colored jumpsuit! + components: + - type: Sprite + sprite: Clothing/Uniforms/rainbow.rsi + state: icon + - type: Clothing + sprite: Clothing/Uniforms/rainbow.rsi diff --git a/Resources/Textures/Clothing/Uniforms/color.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/color.rsi/meta.json index 0b4f3ab7f8..b8827ee3b1 100644 --- a/Resources/Textures/Clothing/Uniforms/color.rsi/meta.json +++ b/Resources/Textures/Clothing/Uniforms/color.rsi/meta.json @@ -2,8 +2,10 @@ "version": 1, "size": { "x": 32, - "y": 32 - }, + "y": 32, + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/d836946e8e85910eaa4d132f70e21bdb9888c171", "states": [ { "name": "black-equipped-INNERCLOTHING", diff --git a/Resources/Textures/Clothing/Uniforms/rainbow.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/equipped-INNERCLOTHING.png new file mode 100644 index 0000000000000000000000000000000000000000..e89ff84ba52a8c411c9524ec2929bf2a92af10a2 GIT binary patch literal 911 zcmV;A191F_P)xh6cY3F^WGO1kwF0ehycJ+0E~=`Q&Urtc>u$q1pn>;YHDh-kqhwL z0BA1^N|^v+$N)@}09mg9KR-WMSXh97fI2!lXJ=V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DLt`LiHkEOv#1!Pg^M$-C^0t`#5UwoR&e!m z0UHVc_&ym==J=>s00068NklBh#9j!AYF9SU?;SLnM^Fpf)%T`ZDTr}icMW_ z+YVGawyh=@KsSx4VZyE=h|?|0maB?DXF@J@cQrm0hkO-y z`g=n9t^~L$pHP>Qx## zi=xO2F`vXqk_7O^h`&4;w8Q|XXTi!}1!t#-fBx;ecz&Ft9UM+TJ4n;?1YWd*c)eaH z@Z!I~*pe~)7qYx4vZBZ{%r7poEW0Q$UjQ;l;eaFlp940R<%Vp^%grZ!@MNGw0Y`jt z1saym`J+aS`g^*rj%TWCU3~?%22vd&Xuab&Izsg;q88lFoX%=`g8^=6J)>MX9ee;F z!Fi1VYR-YL0q|jnz&jYG3yuP6PMh1dy~6-^ZF}2LUZVg|w{61?19V}#?L-Rk@4KdH zw)zgX5b5p_KmG|yQ}%!X9$1=+40ij%WB`I80RyZ)64(K|IF1v>umecUSOSq9-r`PM ze<0xXggh2Ge)kGxd0sr~{372!=>Sjr9G@>FVE?QKJnyxDm)Ek_-o00S`TC*-y!E{f l(D!e8z|qSe0y@Bdsdu0ALab?XymbHo002ovPDHLkV1nFpi7WsB literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/rainbow.rsi/icon.png b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ed407d3fcc94ca043387fc1932064a6abc646455 GIT binary patch literal 382 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyT>(BJu0Wc>b23BXL58Fw3~B!v zIy)J*ZerNJh2iceZ*Onki41YfX^Dx6Nl8g*vdkG78Ch9b+1c6o43$MP{6+s6%F4>h zb^99(<}`7rHa9nSGEDC5?CkFDo~X$%(UD=Y$+js|rc6^7nO4LwgJH>BRk5|)h6jTg zjvP61!b$cKpVqr~@BTA<|KGvz|2EVA6U>i*j$teb@(X5gcy=QV$XVp+;usMwGZ zng8gA1mpV8HTHX293PY((3-R-D?WFsI_riN(}L`lOfhBDUYx7ED0eYWMP%fq$)}8( a_sdr>zt}0jsIkCb03496elF{r5}E+fE|ZP` literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-left.png b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..b587af45794e81544b99b2926c5d5ce2fa902f69 GIT binary patch literal 339 zcmV-Z0j&OsP)cky-x#Pp#2tFg5o2s67dNXijgk@Nk>PaUAF8Xs@GdZEp9tctI+4L9kEbfw(B@*!B zhCYtRG4{c5ueza}OOekMpt@lwhcX1y6A;&N9LFpE+k2qm-_^Fc;?1>XcOq>7!002ovPDHLkV1l8;k*NRx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-right.png b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..b587af45794e81544b99b2926c5d5ce2fa902f69 GIT binary patch literal 339 zcmV-Z0j&OsP)cky-x#Pp#2tFg5o2s67dNXijgk@Nk>PaUAF8Xs@GdZEp9tctI+4L9kEbfw(B@*!B zhCYtRG4{c5ueza}OOekMpt@lwhcX1y6A;&N9LFpE+k2qm-_^Fc;?1>XcOq>7!002ovPDHLkV1l8;k*NRx literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/rainbow.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/meta.json new file mode 100644 index 0000000000..082376bd38 --- /dev/null +++ b/Resources/Textures/Clothing/Uniforms/rainbow.rsi/meta.json @@ -0,0 +1,74 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32, + }, + "license": "CC BY-NC-SA 3.0", + "copyright": "Taken from goonstation at commit https://github.com/goonstation/goonstation/commit/4059e4be90832b02b1228b1bee3db342094e4f1e", + "states": [ + { + "name": "equipped-INNERCLOTHING", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + } + ] +} From af060b53661ba1801f81df7a41cc19121e0320e9 Mon Sep 17 00:00:00 2001 From: Swept Date: Mon, 9 Nov 2020 10:03:53 +0000 Subject: [PATCH 37/41] Replaces switches with cev-eris sprites. (#2526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial * Removed old AME shielding sprite * Update Resources/Textures/Constructible/Power/switch.rsi/meta.json Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> --- .../Entities/Constructible/Walls/linking.yml | 6 +- .../Constructible/Linking/switch.rsi/dead.png | Bin 137 -> 0 bytes .../Linking/switch.rsi/meta.json | 44 ------------ .../Constructible/Linking/switch.rsi/off.png | Bin 137 -> 0 bytes .../Constructible/Linking/switch.rsi/on.png | Bin 137 -> 0 bytes .../Power/ame_shielding_base.png | Bin 425 -> 0 bytes .../Constructible/Power/switch.rsi/dead.png | Bin 0 -> 666 bytes .../Constructible/Power/switch.rsi/meta.json | 65 ++++++++++++++++++ .../Constructible/Power/switch.rsi/off.png | Bin 0 -> 711 bytes .../Constructible/Power/switch.rsi/on.png | Bin 0 -> 695 bytes 10 files changed, 69 insertions(+), 46 deletions(-) delete mode 100644 Resources/Textures/Constructible/Linking/switch.rsi/dead.png delete mode 100644 Resources/Textures/Constructible/Linking/switch.rsi/meta.json delete mode 100644 Resources/Textures/Constructible/Linking/switch.rsi/off.png delete mode 100644 Resources/Textures/Constructible/Linking/switch.rsi/on.png delete mode 100644 Resources/Textures/Constructible/Power/ame_shielding_base.png create mode 100644 Resources/Textures/Constructible/Power/switch.rsi/dead.png create mode 100644 Resources/Textures/Constructible/Power/switch.rsi/meta.json create mode 100644 Resources/Textures/Constructible/Power/switch.rsi/off.png create mode 100644 Resources/Textures/Constructible/Power/switch.rsi/on.png diff --git a/Resources/Prototypes/Entities/Constructible/Walls/linking.yml b/Resources/Prototypes/Entities/Constructible/Walls/linking.yml index 3482f6d3eb..c853655bfe 100644 --- a/Resources/Prototypes/Entities/Constructible/Walls/linking.yml +++ b/Resources/Prototypes/Entities/Constructible/Walls/linking.yml @@ -6,9 +6,10 @@ - type: InteractionOutline - type: Physics - type: Sprite - sprite: Constructible/Linking/switch.rsi + sprite: Constructible/Power/switch.rsi state: on - type: SignalSwitch + - type: Rotatable - type: SignalTransmitter placement: snap: @@ -22,9 +23,10 @@ - type: InteractionOutline - type: Physics - type: Sprite - sprite: Constructible/Linking/switch.rsi + sprite: Constructible/Power/switch.rsi state: dead - type: SignalButton + - type: Rotatable - type: SignalTransmitter placement: snap: diff --git a/Resources/Textures/Constructible/Linking/switch.rsi/dead.png b/Resources/Textures/Constructible/Linking/switch.rsi/dead.png deleted file mode 100644 index 7b6a4689e3f84da5608030074a66d92fbe4928c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*tY5!ABqYS%-rmsA z5GY*miM)(IKOL2DPoF3B^; gjyL*tY5!ABqYS%-u^#> z@fik&uW$Ws17#UYg8YIR9G=}s19DV7T^vI+CMG9H{A&md5b$;Il=O9IUC^Mli(!}K inPbPESQlPkV)%TD@srfAReOLM7(8A5T-G@yGywo3=PUvM diff --git a/Resources/Textures/Constructible/Linking/switch.rsi/on.png b/Resources/Textures/Constructible/Linking/switch.rsi/on.png deleted file mode 100644 index 54f9cab6030686d15f34559ac4479ccca196b812..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*tY5!ABqYS%-ro4X zvGEyW`z5m!fwGJxL4Lsu4$p3+0XeFkE{-7@6O$7p{xt*!2>3d9O8PpqE@;r&#js2A h%&}untP3wNF?>G7_(|&5sy#pr44$rjF6*2UngHceD=q*4 diff --git a/Resources/Textures/Constructible/Power/ame_shielding_base.png b/Resources/Textures/Constructible/Power/ame_shielding_base.png deleted file mode 100644 index cd62067877c2ee374f373ca3c45efd999989fb10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 425 zcmV;a0apHrP)~Jx8!k6UYIkOBKjvyh9*WIu8&?liCXegmf+`7GYQ|Tx3a# zpzG*FXTq><;RC_XKkxm(&u``;2!d~nsLL_KCxEj6xccjc5W;E@rBolF3J=53N;u~n zLI@>97vNCT;lA%%0SLnoobzAr*}NZMy}pL{_yhnDLaYEZy_2t0y4GpJr{@=|p+nvs zfV2UOquWB~1M zKPiB%1*%fF2M&c)Hb*fbMC$<5qqyy@1bBUWm+IyyHj!!+x4o4Bj}Q08VY*UzcX}X6 zHubsg;-jl1*$i(;s@0HlZgop`^p>Uk3n--!LL6VTAfrub-wU=i`Y4_NMhEx-;AU_I ThOmbQ00000NkvXXu0mjfYzekS diff --git a/Resources/Textures/Constructible/Power/switch.rsi/dead.png b/Resources/Textures/Constructible/Power/switch.rsi/dead.png new file mode 100644 index 0000000000000000000000000000000000000000..f618c1521785c70bfdd704dcb00970afd1d7c152 GIT binary patch literal 666 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=B~>92B`&GO$wiq3C7Jno3=9=> zRF7Np9aa!vJuu7msPL7IkNkK0wulBku#RAwJ@t)6Q)tm&k(qfia-WTLJ{Vq5zpi$j zyJzL@$v?d=F&(p*pc(mX(SMUz)8<6}o89;BP4k&_>%fc?IiozY~@&YwYnuQh|BfP4dxZ>8Rknx zxNcVRKaMgGIO$bz^P5=NVpYS%WpQf%d_V7tooDf z!BE0rqQoG}(8~c7D(>Vv@burq!Y%RD_0?Wi{Spi1TBoo6>K3|x=e|u_*pnCh`e{ou5xkt^6~4;R0%Qt^Xoga-?4~Pi33ILCm&dPfyrmWOZ|o&UwsdYU6B7GbUjfZ zm2Yu(CuaiZ4By&oUD;gMOHY)}4f#7~cf+^3>`6bB0MIw`au1{FSi$f zT#v;=xP&skv-ZjQ-3VNA{c+U#qd+e%ySnA%XSGx3x6hqv7-%Q7?NfVu)WdbJFVqNT z%neE0e(c*z{;HkZPCqJ-JG^fBId*}Gn_|nj%8E_yO?NNt^i7%II^p-x{RL(W*W|)= zoj!hMtbEUuC?IJ)C3MBJ47uong)C1TUy3^lHt;pLu`FO-AjtTFA;X2iia`n_^i29_ XeLLsB+hwbPiH*V2)z4*}Q$iB}`g zRF7M8H5dr69(m&#X^2(@yYd&T{OWudp%!jA4(R?%JCyfs^$ z%;qo9Png5XEU135{6)~hZrQA^ixJi5egDj^+UMC{@%Jy!ceeAMmVM6cX9TSnqy!uI z8r)bGFfR~fe8G_6!eGTPE4hS0@4ET+w_k6a{`}W1S6uVl+7B5<(Jfbt#h+_FJu1;s zTPYvPxkh_Ign`rR>CZxEf7Uk0$X!_;BA&##;jP}+YQF_xtEO0bZ`24qHN|{W z=0<-%1SWOnRTl`Qp3GwLWRlX{nP^XG(vq zoyT_d`K-+0oi}Hu*^L#4hy|Ez8cCTeVm$dw0&)Q>UeG_Wop0 z;>w-=w&||S*LLMqJ1y6Eze&AxU$-c4afq4YJL%fTD;{zzdRo(Ttbj!@*x`oS7Atvy z@0t&GK0eX5N$9Ff?_& zRF7M8H5dr69zhQK*e;c^Rg z&oeMEF?qT;hE&XXJL_Q9AqRoB-CI}H5*>A z-E-&)%QY^IXR^6}uI=cU896>|g!2K6GZL@Y3W%r~W+K7PRB}P7{e%x4BwxF5OVuT4j2*=;p6e zr!8+r)H4WXo=*Lp@Vwz%LFD{!(<+v%x~nS=I!;pfe$0*Wy5ypOzntvv`7fw0{Q9q9 zOL=3Vh3^{8*DJafXXYGqPj!%*QzIk-3Vwup;LbkFAMVuM-{ju#0+ Date: Mon, 9 Nov 2020 18:36:45 +0100 Subject: [PATCH 38/41] Fix Exception when updating preview (#2533) --- Content.Client/UserInterface/HumanoidProfileEditor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index b6aca525ae..b6e36d23b7 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -592,6 +592,9 @@ namespace Content.Client.UserInterface private void UpdatePreview() { + if (Profile is null) + return; + _previewDummy.GetComponent().UpdateFromProfile(Profile); LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, Profile); } From 5f788c33189c64d218afca4f3bc8308800d5808a Mon Sep 17 00:00:00 2001 From: chairbender Date: Mon, 9 Nov 2020 20:22:19 -0800 Subject: [PATCH 39/41] Alerts System and UI (#2529) * #272 add bordered panel for effects bar * #272 avoid mouse overlapping tooltip when near edges, change tooltip colors to match mockups * #272 WIP defining status effect states as YML and sending them as encoded integers * #272 refactor to use new alert system * #272 refactor to use new alert system * #272 fix various bugs with new alert system and update alerts to have color * #272 WIP * #272 rename status effects to alerts * #272 WIP reworking alert internals to avoid code dup and eliminate enum * #272 refactor alerts to use categories and fix various bugs * #272 more alert bugfixes * #272 alert ordering * #272 callback-based approach for alert clicks * #272 add debug commands for alerts * #272 utilize new GridContainer capabilities for sizing of alerts tab * #272 scale alerts height based on window size * #272 fix tooltip flicker * #272 transparent alert panel * #272 adjust styles to match injazz mockups more, add cooldown info in tooltip * #272 adjust styles to match injazz mockups more, add cooldown info in tooltip * #272 alert prototype tests * #272 alert manager tests * #272 alert order tests * #272 simple unit test for alerts component * #272 integration test for alerts * #272 rework alerts to use enums instead of id / category * #272 various cleanups for PR * #272 use byte for more compact alert messages * #272 rename StatusEffects folder to Alerts, add missing NetSerializable --- Content.Client/ClientContentIoC.cs | 2 + Content.Client/EntryPoint.cs | 2 + .../Components/Mobs/AlertControl.cs | 93 +++++ .../Components/Mobs/ClientAlertsComponent.cs | 345 ++++++++++++++++++ .../Mobs/ClientStatusEffectsComponent.cs | 200 ---------- .../Components/Mobs/StatusControl.cs | 25 -- .../EntitySystems/AI/ClientAiDebugSystem.cs | 3 +- ...StatusEffectsSystem.cs => AlertsSystem.cs} | 6 +- Content.Client/UserInterface/AlertsUI.cs | 73 ++++ .../UserInterface/StatusEffectsUI.cs | 23 -- .../UserInterface/Stylesheets/StyleNano.cs | 53 ++- .../Components/Mobs/AlertsComponentTests.cs | 110 ++++++ .../Tests/Gravity/WeightlessStatusTests.cs | 11 +- Content.Server/Commands/CommandUtils.cs | 66 ++++ Content.Server/EntryPoint.cs | 2 + .../ActionBlocking/CuffableComponent.cs | 13 +- .../Components/Atmos/BarotraumaComponent.cs | 13 +- .../Components/Atmos/FlammableComponent.cs | 15 +- .../Components/Buckle/BuckleComponent.cs | 19 +- .../Components/Mobs/ServerAlertsComponent.cs | 166 +++++++++ .../Mobs/ServerStatusEffectsComponent.cs | 152 -------- .../Components/Mobs/State/CriticalState.cs | 6 +- .../Components/Mobs/State/DeadState.cs | 6 +- .../Components/Mobs/State/MobStateManager.cs | 5 +- .../Components/Mobs/State/NormalState.cs | 16 +- .../Components/Mobs/StunnableComponent.cs | 5 +- .../Movement/ShuttleControllerComponent.cs | 25 +- .../Components/Nutrition/HungerComponent.cs | 17 +- .../Components/Nutrition/ThirstComponent.cs | 17 +- .../Components/Strap/StrapComponent.cs | 9 +- .../Temperature/TemperatureComponent.cs | 17 +- .../EntitySystems/WeightlessSystem.cs | 31 +- Content.Server/ServerContentIoC.cs | 2 + Content.Shared/Alert/AlertManager.cs | 124 +++++++ Content.Shared/Alert/AlertOrderPrototype.cs | 81 ++++ Content.Shared/Alert/AlertPrototype.cs | 189 ++++++++++ Content.Shared/Alert/AlertType.cs | 52 +++ .../Components/Mobs/SharedAlertsComponent.cs | 279 ++++++++++++++ .../Mobs/SharedStatusEffectsComponent.cs | 76 ---- .../Mobs/SharedStunnableComponent.cs | 21 +- .../Pulling/SharedPullableComponent.cs | 30 +- Content.Shared/GameObjects/ContentNetIDs.cs | 2 +- .../Mobs/ServerAlertsComponentTests.cs | 71 ++++ .../Shared/Alert/AlertManagerTests.cs | 63 ++++ .../Shared/Alert/AlertOrderPrototypeTests.cs | 96 +++++ .../Shared/Alert/AlertPrototypeTests.cs | 62 ++++ Resources/Groups/groups.yml | 2 + Resources/Prototypes/Alerts/alerts.yml | 205 +++++++++++ .../Prototypes/Entities/Mobs/Player/human.yml | 2 +- .../Buckle/buckled.png | Bin .../{StatusEffects => Alerts}/Fire/fire.png | Bin .../Handcuffed/Handcuffed.png | Bin .../Human/human0.png | Bin .../Human/human1.png | Bin .../Human/human2.png | Bin .../Human/human3.png | Bin .../Human/human4.png | Bin .../Human/human5.png | Bin .../Human/human6.png | Bin .../Human/human7.png | Bin .../Human/humancrit-0.png | Bin .../Human/humancrit-1.png | Bin .../Human/humandead.png | Bin .../Hunger/Overfed.png | Bin .../Hunger/Peckish.png | Bin .../Hunger/Starving.png | Bin .../Pressure/highpressure1.png | Bin .../Pressure/highpressure2.png | Bin .../Pressure/lowpressure1.png | Bin .../Pressure/lowpressure2.png | Bin .../Pressure/meta.json | 0 .../{StatusEffects => Alerts}/Pull/pulled.png | Bin .../Pull/pulling.png | Bin .../Temperature/cold1.png | Bin .../Temperature/cold2.png | Bin .../Temperature/cold3.png | Bin .../Temperature/hot1.png | Bin .../Temperature/hot2.png | Bin .../Temperature/hot3.png | Bin .../Thirst/OverHydrated.png | Bin .../Thirst/Parched.png | Bin .../Thirst/Thirsty.png | Bin .../Weightless/weightless.png | Bin Resources/Textures/Interface/Nano/tooltip.png | Bin 133 -> 213 bytes ...transparent_window_background_bordered.png | Bin 0 -> 144 bytes .../Nano/window_background_bordered.png | Bin 0 -> 213 bytes 86 files changed, 2305 insertions(+), 598 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Mobs/AlertControl.cs create mode 100644 Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs delete mode 100644 Content.Client/GameObjects/Components/Mobs/ClientStatusEffectsComponent.cs delete mode 100644 Content.Client/GameObjects/Components/Mobs/StatusControl.cs rename Content.Client/GameObjects/EntitySystems/{StatusEffectsSystem.cs => AlertsSystem.cs} (67%) create mode 100644 Content.Client/UserInterface/AlertsUI.cs delete mode 100644 Content.Client/UserInterface/StatusEffectsUI.cs create mode 100644 Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs create mode 100644 Content.Server/Commands/CommandUtils.cs create mode 100644 Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs delete mode 100644 Content.Server/GameObjects/Components/Mobs/ServerStatusEffectsComponent.cs create mode 100644 Content.Shared/Alert/AlertManager.cs create mode 100644 Content.Shared/Alert/AlertOrderPrototype.cs create mode 100644 Content.Shared/Alert/AlertPrototype.cs create mode 100644 Content.Shared/Alert/AlertType.cs create mode 100644 Content.Shared/GameObjects/Components/Mobs/SharedAlertsComponent.cs delete mode 100644 Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs create mode 100644 Content.Tests/Server/GameObjects/Components/Mobs/ServerAlertsComponentTests.cs create mode 100644 Content.Tests/Shared/Alert/AlertManagerTests.cs create mode 100644 Content.Tests/Shared/Alert/AlertOrderPrototypeTests.cs create mode 100644 Content.Tests/Shared/Alert/AlertPrototypeTests.cs create mode 100644 Resources/Prototypes/Alerts/alerts.yml rename Resources/Textures/Interface/{StatusEffects => Alerts}/Buckle/buckled.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Fire/fire.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Handcuffed/Handcuffed.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human0.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human2.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human3.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human4.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human5.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human6.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/human7.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/humancrit-0.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/humancrit-1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Human/humandead.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Hunger/Overfed.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Hunger/Peckish.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Hunger/Starving.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pressure/highpressure1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pressure/highpressure2.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pressure/lowpressure1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pressure/lowpressure2.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pressure/meta.json (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pull/pulled.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Pull/pulling.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/cold1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/cold2.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/cold3.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/hot1.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/hot2.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Temperature/hot3.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Thirst/OverHydrated.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Thirst/Parched.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Thirst/Thirsty.png (100%) rename Resources/Textures/Interface/{StatusEffects => Alerts}/Weightless/weightless.png (100%) create mode 100644 Resources/Textures/Interface/Nano/transparent_window_background_bordered.png create mode 100644 Resources/Textures/Interface/Nano/window_background_bordered.png diff --git a/Content.Client/ClientContentIoC.cs b/Content.Client/ClientContentIoC.cs index e7d8d90841..7c338bd292 100644 --- a/Content.Client/ClientContentIoC.cs +++ b/Content.Client/ClientContentIoC.cs @@ -11,6 +11,7 @@ using Content.Client.UserInterface.AdminMenu; using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.Interfaces; +using Content.Shared.Alert; using Robust.Shared.IoC; namespace Content.Client @@ -35,6 +36,7 @@ namespace Content.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index ffa05119bc..f34124b893 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -22,6 +22,7 @@ using Content.Shared.GameObjects.Components.Power.AME; using Content.Shared.GameObjects.Components.Research; using Content.Shared.GameObjects.Components.VendingMachines; using Content.Shared.Kitchen; +using Content.Shared.Alert; using Robust.Client; using Robust.Client.Interfaces; using Robust.Client.Interfaces.Graphics.Overlays; @@ -150,6 +151,7 @@ namespace Content.Client IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); _baseClient.RunLevelChanged += (sender, args) => { diff --git a/Content.Client/GameObjects/Components/Mobs/AlertControl.cs b/Content.Client/GameObjects/Components/Mobs/AlertControl.cs new file mode 100644 index 0000000000..b1a60f5fc9 --- /dev/null +++ b/Content.Client/GameObjects/Components/Mobs/AlertControl.cs @@ -0,0 +1,93 @@ +#nullable enable +using System; +using Content.Client.UserInterface; +using Content.Client.Utility; +using Content.Shared.Alert; +using OpenToolkit.Mathematics; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.UserInterface.Controls; + +namespace Content.Client.GameObjects.Components.Mobs +{ + public class AlertControl : BaseButton + { + public AlertPrototype Alert { get; } + + /// + /// Total duration of the cooldown in seconds. Null if no duration / cooldown. + /// + public int? TotalDuration { get; set; } + + private short? _severity; + private readonly TextureRect _icon; + private CooldownGraphic _cooldownGraphic; + + private readonly IResourceCache _resourceCache; + + + /// + /// Creates an alert control reflecting the indicated alert + state + /// + /// alert to display + /// severity of alert, null if alert doesn't have severity levels + /// resourceCache to use to load alert icon textures + public AlertControl(AlertPrototype alert, short? severity, IResourceCache resourceCache) + { + _resourceCache = resourceCache; + Alert = alert; + _severity = severity; + var texture = _resourceCache.GetTexture(alert.GetIconPath(_severity)); + _icon = new TextureRect + { + TextureScale = (2, 2), + Texture = texture + }; + + Children.Add(_icon); + _cooldownGraphic = new CooldownGraphic(); + Children.Add(_cooldownGraphic); + + } + + /// + /// Change the alert severity, changing the displayed icon + /// + public void SetSeverity(short? severity) + { + if (_severity != severity) + { + _severity = severity; + _icon.Texture = _resourceCache.GetTexture(Alert.GetIconPath(_severity)); + } + } + + /// + /// Updates the displayed cooldown amount, doing nothing if alertCooldown is null + /// + /// cooldown start and end + /// current game time + public void UpdateCooldown((TimeSpan Start, TimeSpan End)? alertCooldown, in TimeSpan curTime) + { + if (!alertCooldown.HasValue) + { + _cooldownGraphic.Progress = 0; + _cooldownGraphic.Visible = false; + TotalDuration = null; + } + else + { + + var start = alertCooldown.Value.Start; + var end = alertCooldown.Value.End; + + var length = (end - start).TotalSeconds; + var progress = (curTime - start).TotalSeconds / length; + var ratio = (progress <= 1 ? (1 - progress) : (curTime - end).TotalSeconds * -5); + + TotalDuration = (int?) Math.Round(length); + _cooldownGraphic.Progress = MathHelper.Clamp((float)ratio, -1, 1); + _cooldownGraphic.Visible = ratio > -1f; + } + } + } +} diff --git a/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs b/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs new file mode 100644 index 0000000000..8dbbed08b5 --- /dev/null +++ b/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs @@ -0,0 +1,345 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; +using Content.Client.Utility; +using Content.Shared.Alert; +using Content.Shared.GameObjects.Components.Mobs; +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.Graphics; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.Interfaces.UserInterface; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.GameObjects; +using Robust.Shared.Input; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Timing; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; +using Serilog; + +namespace Content.Client.GameObjects.Components.Mobs +{ + /// + [RegisterComponent] + [ComponentReference(typeof(SharedAlertsComponent))] + public sealed class ClientAlertsComponent : SharedAlertsComponent + { + private static readonly float TooltipTextMaxWidth = 265; + + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IResourceCache _resourceCache = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + private AlertsUI _ui; + private PanelContainer _tooltip; + private RichTextLabel _stateName; + private RichTextLabel _stateDescription; + private RichTextLabel _stateCooldown; + private AlertOrderPrototype _alertOrder; + private bool _tooltipReady; + + [ViewVariables] + private Dictionary _alertControls + = new Dictionary(); + + /// + /// Allows calculating if we need to act due to this component being controlled by the current mob + /// TODO: should be revisited after space-wizards/RobustToolbox#1255 + /// + [ViewVariables] + private bool CurrentlyControlled => _playerManager.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity == Owner; + + protected override void Shutdown() + { + base.Shutdown(); + PlayerDetached(); + } + + public override void HandleMessage(ComponentMessage message, IComponent component) + { + base.HandleMessage(message, component); + switch (message) + { + case PlayerAttachedMsg _: + PlayerAttached(); + break; + case PlayerDetachedMsg _: + PlayerDetached(); + break; + } + } + + public override void HandleComponentState(ComponentState curState, ComponentState nextState) + { + base.HandleComponentState(curState, nextState); + + if (!(curState is AlertsComponentState state)) + { + return; + } + + // update the dict of states based on the array we got in the message + SetAlerts(state.Alerts); + + UpdateAlertsControls(); + } + + private void PlayerAttached() + { + if (!CurrentlyControlled || _ui != null) + { + return; + } + + _alertOrder = IoCManager.Resolve().EnumeratePrototypes().FirstOrDefault(); + if (_alertOrder == null) + { + Logger.ErrorS("alert", "no alertOrder prototype found, alerts will be in random order"); + } + + _ui = new AlertsUI(IoCManager.Resolve()); + var uiManager = IoCManager.Resolve(); + uiManager.StateRoot.AddChild(_ui); + + _tooltip = new PanelContainer + { + Visible = false, + StyleClasses = { StyleNano.StyleClassTooltipPanel } + }; + var tooltipVBox = new VBoxContainer + { + RectClipContent = true + }; + _tooltip.AddChild(tooltipVBox); + _stateName = new RichTextLabel + { + MaxWidth = TooltipTextMaxWidth, + StyleClasses = { StyleNano.StyleClassTooltipAlertTitle } + }; + tooltipVBox.AddChild(_stateName); + _stateDescription = new RichTextLabel + { + MaxWidth = TooltipTextMaxWidth, + StyleClasses = { StyleNano.StyleClassTooltipAlertDescription } + }; + tooltipVBox.AddChild(_stateDescription); + _stateCooldown = new RichTextLabel + { + MaxWidth = TooltipTextMaxWidth, + StyleClasses = { StyleNano.StyleClassTooltipAlertCooldown } + }; + tooltipVBox.AddChild(_stateCooldown); + + uiManager.PopupRoot.AddChild(_tooltip); + + UpdateAlertsControls(); + } + + private void PlayerDetached() + { + _ui?.Dispose(); + _ui = null; + _alertControls.Clear(); + } + + /// + /// Updates the displayed alerts based on current state of Alerts, performing + /// a diff to ensure we only change what's changed (this avoids active tooltips disappearing any + /// time state changes) + /// + private void UpdateAlertsControls() + { + if (!CurrentlyControlled || _ui == null) + { + return; + } + + // remove any controls with keys no longer present + var toRemove = new List(); + foreach (var existingKey in _alertControls.Keys) + { + if (!IsShowingAlert(existingKey)) + { + toRemove.Add(existingKey); + } + } + + foreach (var alertKeyToRemove in toRemove) + { + // remove and dispose the control + _alertControls.Remove(alertKeyToRemove, out var control); + control?.Dispose(); + } + + // now we know that alertControls contains alerts that should still exist but + // may need to updated, + // also there may be some new alerts we need to show. + // further, we need to ensure they are ordered w.r.t their configured order + foreach (var alertStatus in EnumerateAlertStates()) + { + if (!AlertManager.TryDecode(alertStatus.AlertEncoded, out var newAlert)) + { + Logger.ErrorS("alert", "Unable to decode alert {0}", alertStatus.AlertEncoded); + continue; + } + + if (_alertControls.TryGetValue(newAlert.AlertKey, out var existingAlertControl) && + existingAlertControl.Alert.AlertType == newAlert.AlertType) + { + // id is the same, simply update the existing control severity + existingAlertControl.SetSeverity(alertStatus.Severity); + } + else + { + existingAlertControl?.Dispose(); + + // this is a new alert + alert key or just a different alert with the same + // key, create the control and add it in the appropriate order + var newAlertControl = CreateAlertControl(newAlert, alertStatus); + if (_alertOrder != null) + { + var added = false; + foreach (var alertControl in _ui.Grid.Children) + { + if (_alertOrder.Compare(newAlert, ((AlertControl) alertControl).Alert) < 0) + { + var idx = alertControl.GetPositionInParent(); + _ui.Grid.Children.Add(newAlertControl); + newAlertControl.SetPositionInParent(idx); + added = true; + break; + } + } + + if (!added) + { + _ui.Grid.Children.Add(newAlertControl); + } + } + else + { + _ui.Grid.Children.Add(newAlertControl); + } + + _alertControls[newAlert.AlertKey] = newAlertControl; + } + } + } + + private AlertControl CreateAlertControl(AlertPrototype alert, AlertState alertState) + { + + var alertControl = new AlertControl(alert, alertState.Severity, _resourceCache); + // show custom tooltip for the status control + alertControl.OnShowTooltip += AlertOnOnShowTooltip; + alertControl.OnHideTooltip += AlertOnOnHideTooltip; + + alertControl.OnPressed += AlertControlOnPressed; + + return alertControl; + } + + private void AlertControlOnPressed(BaseButton.ButtonEventArgs args) + { + AlertPressed(args, args.Button as AlertControl); + } + + private void AlertOnOnHideTooltip(object sender, EventArgs e) + { + _tooltipReady = false; + _tooltip.Visible = false; + } + + private void AlertOnOnShowTooltip(object sender, EventArgs e) + { + var alertControl = (AlertControl) sender; + _stateName.SetMessage(alertControl.Alert.Name); + _stateDescription.SetMessage(alertControl.Alert.Description); + // check for a cooldown + if (alertControl.TotalDuration != null && alertControl.TotalDuration > 0) + { + _stateCooldown.SetMessage(FormattedMessage.FromMarkup("[color=#776a6a]" + + alertControl.TotalDuration + + " sec cooldown[/color]")); + _stateCooldown.Visible = true; + } + else + { + _stateCooldown.Visible = false; + } + // TODO: Text display of cooldown + Tooltips.PositionTooltip(_tooltip); + // if we set it visible here the size of the previous tooltip will flicker for a frame, + // so instead we wait until FrameUpdate to make it visible + _tooltipReady = true; + } + + private void AlertPressed(BaseButton.ButtonEventArgs args, AlertControl alert) + { + if (args.Event.Function != EngineKeyFunctions.UIClick) + { + return; + } + + if (AlertManager.TryEncode(alert.Alert, out var encoded)) + { + SendNetworkMessage(new ClickAlertMessage(encoded)); + } + else + { + Logger.ErrorS("alert", "unable to encode alert {0}", alert.Alert.AlertType); + } + + } + + public void FrameUpdate(float frameTime) + { + if (_tooltipReady) + { + _tooltipReady = false; + _tooltip.Visible = true; + } + foreach (var (alertKey, alertControl) in _alertControls) + { + // reconcile all alert controls with their current cooldowns + if (TryGetAlertState(alertKey, out var alertState)) + { + alertControl.UpdateCooldown(alertState.Cooldown, _gameTiming.CurTime); + } + else + { + Logger.WarningS("alert", "coding error - no alert state for alert {0} " + + "even though we had an AlertControl for it, this" + + " should never happen", alertControl.Alert.AlertType); + } + + } + } + + protected override void AfterClearAlert() + { + UpdateAlertsControls(); + } + + public override void OnRemove() + { + base.OnRemove(); + + foreach (var alertControl in _alertControls.Values) + { + alertControl.OnShowTooltip -= AlertOnOnShowTooltip; + alertControl.OnHideTooltip -= AlertOnOnHideTooltip; + alertControl.OnPressed -= AlertControlOnPressed; + } + + } + } +} diff --git a/Content.Client/GameObjects/Components/Mobs/ClientStatusEffectsComponent.cs b/Content.Client/GameObjects/Components/Mobs/ClientStatusEffectsComponent.cs deleted file mode 100644 index bd292db23f..0000000000 --- a/Content.Client/GameObjects/Components/Mobs/ClientStatusEffectsComponent.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Content.Client.UserInterface; -using Content.Client.Utility; -using Content.Shared.GameObjects.Components.Mobs; -using Robust.Client.GameObjects; -using Robust.Client.Interfaces.ResourceManagement; -using Robust.Client.Interfaces.UserInterface; -using Robust.Client.Player; -using Robust.Client.UserInterface.Controls; -using Robust.Shared.GameObjects; -using Robust.Shared.Input; -using Robust.Shared.Interfaces.GameObjects; -using Robust.Shared.Interfaces.Timing; -using Robust.Shared.IoC; -using Robust.Shared.Maths; -using Robust.Shared.ViewVariables; - -namespace Content.Client.GameObjects.Components.Mobs -{ - /// - [RegisterComponent] - [ComponentReference(typeof(SharedStatusEffectsComponent))] - public sealed class ClientStatusEffectsComponent : SharedStatusEffectsComponent - { - [Dependency] private readonly IPlayerManager _playerManager = default!; - [Dependency] private readonly IResourceCache _resourceCache = default!; - [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; - - private StatusEffectsUI _ui; - [ViewVariables] - private Dictionary _status = new Dictionary(); - [ViewVariables] - private Dictionary _cooldown = new Dictionary(); - - public override IReadOnlyDictionary Statuses => _status; - - /// - /// Allows calculating if we need to act due to this component being controlled by the current mob - /// - [ViewVariables] - private bool CurrentlyControlled => _playerManager.LocalPlayer != null && _playerManager.LocalPlayer.ControlledEntity == Owner; - - protected override void Shutdown() - { - base.Shutdown(); - PlayerDetached(); - } - - public override void HandleMessage(ComponentMessage message, IComponent component) - { - base.HandleMessage(message, component); - switch (message) - { - case PlayerAttachedMsg _: - PlayerAttached(); - break; - case PlayerDetachedMsg _: - PlayerDetached(); - break; - } - } - - public override void HandleComponentState(ComponentState curState, ComponentState nextState) - { - base.HandleComponentState(curState, nextState); - - if (!(curState is StatusEffectComponentState state) || _status == state.StatusEffects) - { - return; - } - - _status = state.StatusEffects; - UpdateStatusEffects(); - } - - private void PlayerAttached() - { - if (!CurrentlyControlled || _ui != null) - { - return; - } - _ui = new StatusEffectsUI(); - _userInterfaceManager.StateRoot.AddChild(_ui); - UpdateStatusEffects(); - } - - private void PlayerDetached() - { - _ui?.Dispose(); - _ui = null; - _cooldown.Clear(); - } - - public override void ChangeStatusEffectIcon(StatusEffect effect, string icon) - { - if (_status.TryGetValue(effect, out var value) && - value.Icon == icon) - { - return; - } - - _status[effect] = new StatusEffectStatus - { - Icon = icon, - Cooldown = value.Cooldown - }; - - Dirty(); - } - - public void UpdateStatusEffects() - { - if (!CurrentlyControlled || _ui == null) - { - return; - } - _cooldown.Clear(); - _ui.VBox.DisposeAllChildren(); - - foreach (var (key, effect) in _status.OrderBy(x => (int) x.Key)) - { - var texture = _resourceCache.GetTexture(effect.Icon); - var status = new StatusControl(key, texture) - { - ToolTip = key.ToString() - }; - - if (effect.Cooldown.HasValue) - { - var cooldown = new CooldownGraphic(); - status.Children.Add(cooldown); - _cooldown[key] = cooldown; - } - - status.OnPressed += args => StatusPressed(args, status); - - _ui.VBox.AddChild(status); - } - } - - private void StatusPressed(BaseButton.ButtonEventArgs args, StatusControl status) - { - if (args.Event.Function != EngineKeyFunctions.UIClick) - { - return; - } - - SendNetworkMessage(new ClickStatusMessage(status.Effect)); - } - - public override void RemoveStatusEffect(StatusEffect effect) - { - if (!_status.Remove(effect)) - { - return; - } - - UpdateStatusEffects(); - Dirty(); - } - - public void FrameUpdate(float frameTime) - { - foreach (var (effect, cooldownGraphic) in _cooldown) - { - var status = _status[effect]; - if (!status.Cooldown.HasValue) - { - cooldownGraphic.Progress = 0; - cooldownGraphic.Visible = false; - continue; - } - - var start = status.Cooldown.Value.Item1; - var end = status.Cooldown.Value.Item2; - - var length = (end - start).TotalSeconds; - var progress = (_gameTiming.CurTime - start).TotalSeconds / length; - var ratio = (progress <= 1 ? (1 - progress) : (_gameTiming.CurTime - end).TotalSeconds * -5); - - cooldownGraphic.Progress = MathHelper.Clamp((float)ratio, -1, 1); - cooldownGraphic.Visible = ratio > -1f; - } - } - - public override void ChangeStatusEffect(StatusEffect effect, string icon, (TimeSpan, TimeSpan)? cooldown) - { - _status[effect] = new StatusEffectStatus() - { - Icon = icon, - Cooldown = cooldown - }; - - Dirty(); - } - } -} diff --git a/Content.Client/GameObjects/Components/Mobs/StatusControl.cs b/Content.Client/GameObjects/Components/Mobs/StatusControl.cs deleted file mode 100644 index 7df0225a90..0000000000 --- a/Content.Client/GameObjects/Components/Mobs/StatusControl.cs +++ /dev/null @@ -1,25 +0,0 @@ -#nullable enable -using Content.Shared.GameObjects.Components.Mobs; -using Robust.Client.Graphics; -using Robust.Client.UserInterface.Controls; - -namespace Content.Client.GameObjects.Components.Mobs -{ - public class StatusControl : BaseButton - { - public readonly StatusEffect Effect; - - public StatusControl(StatusEffect effect, Texture? texture) - { - Effect = effect; - - var item = new TextureRect - { - TextureScale = (2, 2), - Texture = texture - }; - - Children.Add(item); - } - } -} diff --git a/Content.Client/GameObjects/EntitySystems/AI/ClientAiDebugSystem.cs b/Content.Client/GameObjects/EntitySystems/AI/ClientAiDebugSystem.cs index 70ab6690bb..943a057714 100644 --- a/Content.Client/GameObjects/EntitySystems/AI/ClientAiDebugSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/AI/ClientAiDebugSystem.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Content.Client.UserInterface.Stylesheets; using Content.Shared.AI; using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.Interfaces.UserInterface; @@ -178,7 +179,7 @@ namespace Content.Client.GameObjects.EntitySystems.AI var panel = new PanelContainer { - StyleClasses = {"tooltipBox"}, + StyleClasses = { StyleNano.StyleClassTooltipPanel }, Children = {vBox}, MouseFilter = Control.MouseFilterMode.Ignore, ModulateSelfOverride = Color.White.WithAlpha(0.75f), diff --git a/Content.Client/GameObjects/EntitySystems/StatusEffectsSystem.cs b/Content.Client/GameObjects/EntitySystems/AlertsSystem.cs similarity index 67% rename from Content.Client/GameObjects/EntitySystems/StatusEffectsSystem.cs rename to Content.Client/GameObjects/EntitySystems/AlertsSystem.cs index f7a2388368..107451f9ea 100644 --- a/Content.Client/GameObjects/EntitySystems/StatusEffectsSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/AlertsSystem.cs @@ -5,7 +5,7 @@ using Robust.Shared.IoC; namespace Content.Client.GameObjects.EntitySystems { - public class StatusEffectsSystem : EntitySystem + public class AlertsSystem : EntitySystem { [Dependency] private readonly IGameTiming _gameTiming = default!; @@ -16,9 +16,9 @@ namespace Content.Client.GameObjects.EntitySystems if (!_gameTiming.IsFirstTimePredicted) return; - foreach (var clientStatusEffectsComponent in EntityManager.ComponentManager.EntityQuery()) + foreach (var clientAlertsComponent in EntityManager.ComponentManager.EntityQuery()) { - clientStatusEffectsComponent.FrameUpdate(frameTime); + clientAlertsComponent.FrameUpdate(frameTime); } } } diff --git a/Content.Client/UserInterface/AlertsUI.cs b/Content.Client/UserInterface/AlertsUI.cs new file mode 100644 index 0000000000..f4c7effac9 --- /dev/null +++ b/Content.Client/UserInterface/AlertsUI.cs @@ -0,0 +1,73 @@ +using System; +using Content.Client.UserInterface.Stylesheets; +using Robust.Client.Graphics.Drawing; +using Robust.Client.Interfaces.Graphics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Maths; + +namespace Content.Client.UserInterface +{ + /// + /// The status effects display on the right side of the screen. + /// + public sealed class AlertsUI : Control + { + public GridContainer Grid { get; } + + private readonly IClyde _clyde; + + public AlertsUI(IClyde clyde) + { + _clyde = clyde; + var panelContainer = new PanelContainer + { + StyleClasses = {StyleNano.StyleClassTransparentBorderedWindowPanel}, + SizeFlagsVertical = SizeFlags.FillExpand, + }; + AddChild(panelContainer); + + Grid = new GridContainer + { + MaxHeight = CalcMaxHeight(clyde.ScreenSize), + ExpandBackwards = true + }; + panelContainer.AddChild(Grid); + clyde.OnWindowResized += ClydeOnOnWindowResized; + + LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin); + LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10); + LayoutContainer.SetMarginTop(this, 250); + } + + protected override void UIScaleChanged() + { + Grid.MaxHeight = CalcMaxHeight(_clyde.ScreenSize); + base.UIScaleChanged(); + } + + private void ClydeOnOnWindowResized(WindowResizedEventArgs obj) + { + // TODO: Can rework this once https://github.com/space-wizards/RobustToolbox/issues/1392 is done, + // this is here because there isn't currently a good way to allow the grid to adjust its height based + // on constraints, otherwise we would use anchors to lay it out + Grid.MaxHeight = CalcMaxHeight(obj.NewSize);; + } + + private float CalcMaxHeight(Vector2i screenSize) + { + return Math.Max(((screenSize.Y) / UIScale) - 420, 1); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _clyde.OnWindowResized -= ClydeOnOnWindowResized; + } + } + } +} diff --git a/Content.Client/UserInterface/StatusEffectsUI.cs b/Content.Client/UserInterface/StatusEffectsUI.cs deleted file mode 100644 index baaade0028..0000000000 --- a/Content.Client/UserInterface/StatusEffectsUI.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; - -namespace Content.Client.UserInterface -{ - /// - /// The status effects display on the right side of the screen. - /// - public sealed class StatusEffectsUI : Control - { - public VBoxContainer VBox { get; } - - public StatusEffectsUI() - { - VBox = new VBoxContainer(); - AddChild(VBox); - - LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin); - LayoutContainer.SetAnchorAndMarginPreset(this, LayoutContainer.LayoutPreset.TopRight, margin: 10); - LayoutContainer.SetMarginTop(this, 250); - } - } -} diff --git a/Content.Client/UserInterface/Stylesheets/StyleNano.cs b/Content.Client/UserInterface/Stylesheets/StyleNano.cs index 092cb2c12f..a29b687b72 100644 --- a/Content.Client/UserInterface/Stylesheets/StyleNano.cs +++ b/Content.Client/UserInterface/Stylesheets/StyleNano.cs @@ -13,6 +13,13 @@ namespace Content.Client.UserInterface.Stylesheets { public sealed class StyleNano : StyleBase { + public const string StyleClassBorderedWindowPanel = "BorderedWindowPanel"; + public const string StyleClassTransparentBorderedWindowPanel = "TransparentBorderedWindowPanel"; + public const string StyleClassTooltipPanel = "tooltipBox"; + public const string StyleClassTooltipAlertTitle = "tooltipAlertTitle"; + public const string StyleClassTooltipAlertDescription = "tooltipAlertDesc"; + public const string StyleClassTooltipAlertCooldown = "tooltipAlertCooldown"; + public const string StyleClassSliderRed = "Red"; public const string StyleClassSliderGreen = "Green"; public const string StyleClassSliderBlue = "Blue"; @@ -55,6 +62,7 @@ namespace Content.Client.UserInterface.Stylesheets var notoSansDisplayBold14 = resCache.GetFont("/Fonts/NotoSansDisplay/NotoSansDisplay-Bold.ttf", 14); var notoSans16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 16); var notoSansBold16 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 16); + var notoSansBold18 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 18); var notoSansBold20 = resCache.GetFont("/Fonts/NotoSans/NotoSans-Bold.ttf", 20); var textureCloseButton = resCache.GetTexture("/Textures/Interface/Nano/cross.svg.png"); var windowHeaderTex = resCache.GetTexture("/Textures/Interface/Nano/window_header.png"); @@ -73,6 +81,20 @@ namespace Content.Client.UserInterface.Stylesheets windowBackground.SetPatchMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2); windowBackground.SetExpandMargin(StyleBox.Margin.Horizontal | StyleBox.Margin.Bottom, 2); + var borderedWindowBackgroundTex = resCache.GetTexture("/Textures/Interface/Nano/window_background_bordered.png"); + var borderedWindowBackground = new StyleBoxTexture + { + Texture = borderedWindowBackgroundTex, + }; + borderedWindowBackground.SetPatchMargin(StyleBox.Margin.All, 2); + + var borderedTransparentWindowBackgroundTex = resCache.GetTexture("/Textures/Interface/Nano/transparent_window_background_bordered.png"); + var borderedTransparentWindowBackground = new StyleBoxTexture + { + Texture = borderedTransparentWindowBackgroundTex, + }; + borderedTransparentWindowBackground.SetPatchMargin(StyleBox.Margin.All, 2); + var textureInvertedTriangle = resCache.GetTexture("/Textures/Interface/Nano/inverted_triangle.svg.png"); var lineEditTex = resCache.GetTexture("/Textures/Interface/Nano/lineedit.png"); @@ -147,7 +169,7 @@ namespace Content.Client.UserInterface.Stylesheets Texture = tooltipTexture, }; tooltipBox.SetPatchMargin(StyleBox.Margin.All, 2); - tooltipBox.SetContentMarginOverride(StyleBox.Margin.Horizontal, 5); + tooltipBox.SetContentMarginOverride(StyleBox.Margin.Horizontal, 7); // Placeholder var placeholderTexture = resCache.GetTexture("/Textures/Interface/Nano/placeholder.png"); @@ -245,6 +267,19 @@ namespace Content.Client.UserInterface.Stylesheets { new StyleProperty(PanelContainer.StylePropertyPanel, windowBackground), }), + // bordered window background + new StyleRule( + new SelectorElement(null, new[] {StyleClassBorderedWindowPanel}, null, null), + new[] + { + new StyleProperty(PanelContainer.StylePropertyPanel, borderedWindowBackground), + }), + new StyleRule( + new SelectorElement(null, new[] {StyleClassTransparentBorderedWindowPanel}, null, null), + new[] + { + new StyleProperty(PanelContainer.StylePropertyPanel, borderedTransparentWindowBackground), + }), // Window header. new StyleRule( new SelectorElement(typeof(PanelContainer), new[] {SS14Window.StyleClassWindowHeader}, null, null), @@ -464,7 +499,7 @@ namespace Content.Client.UserInterface.Stylesheets new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox) }), - new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {"tooltipBox"}, null, null), new[] + new StyleRule(new SelectorElement(typeof(PanelContainer), new [] { StyleClassTooltipPanel }, null, null), new[] { new StyleProperty(PanelContainer.StylePropertyPanel, tooltipBox) }), @@ -482,6 +517,20 @@ namespace Content.Client.UserInterface.Stylesheets new StyleProperty("font", notoSansItalic12), }), + // alert tooltip + new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertTitle}, null, null), new[] + { + new StyleProperty("font", notoSansBold18) + }), + new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertDescription}, null, null), new[] + { + new StyleProperty("font", notoSans16) + }), + new StyleRule(new SelectorElement(typeof(RichTextLabel), new[] {StyleClassTooltipAlertCooldown}, null, null), new[] + { + new StyleProperty("font", notoSans16) + }), + // Entity tooltip new StyleRule( new SelectorElement(typeof(PanelContainer), new[] {ExamineSystem.StyleClassEntityTooltip}, null, diff --git a/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs b/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs new file mode 100644 index 0000000000..e48a18daac --- /dev/null +++ b/Content.IntegrationTests/Tests/GameObjects/Components/Mobs/AlertsComponentTests.cs @@ -0,0 +1,110 @@ +using System.Linq; +using System.Threading.Tasks; +using Content.Client.GameObjects.Components.Mobs; +using Content.Client.UserInterface; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; +using NUnit.Framework; +using Robust.Client.Interfaces.UserInterface; +using Robust.Client.Player; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.IoC; +using Robust.Shared.Map; + +namespace Content.IntegrationTests.Tests.GameObjects.Components.Mobs +{ + [TestFixture] + [TestOf(typeof(ClientAlertsComponent))] + [TestOf(typeof(ServerAlertsComponent))] + public class AlertsComponentTests : ContentIntegrationTest + { + + [Test] + public async Task AlertsTest() + { + var (client, server) = await StartConnectedServerClientPair(); + + await server.WaitIdleAsync(); + await client.WaitIdleAsync(); + + var serverPlayerManager = server.ResolveDependency(); + + await server.WaitAssertion(() => + { + var player = serverPlayerManager.GetAllPlayers().Single(); + var playerEnt = player.AttachedEntity; + Assert.NotNull(playerEnt); + var alertsComponent = playerEnt.GetComponent(); + Assert.NotNull(alertsComponent); + + // show 2 alerts + alertsComponent.ShowAlert(AlertType.Debug1); + alertsComponent.ShowAlert(AlertType.Debug2); + }); + + await server.WaitRunTicks(5); + await client.WaitRunTicks(5); + + var clientPlayerMgr = client.ResolveDependency(); + var clientUIMgr = client.ResolveDependency(); + await client.WaitAssertion(() => + { + + var local = clientPlayerMgr.LocalPlayer; + Assert.NotNull(local); + var controlled = local.ControlledEntity; + Assert.NotNull(controlled); + var alertsComponent = controlled.GetComponent(); + Assert.NotNull(alertsComponent); + + // find the alertsui + var alertsUI = + clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is AlertsUI) as AlertsUI; + Assert.NotNull(alertsUI); + + // we should be seeing 3 alerts - our health, and the 2 debug alerts, in a specific order. + Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(3)); + var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl); + var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray(); + var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug1, AlertType.Debug2}; + Assert.That(alertIDs, Is.EqualTo(expectedIDs)); + }); + + await server.WaitAssertion(() => + { + var player = serverPlayerManager.GetAllPlayers().Single(); + var playerEnt = player.AttachedEntity; + Assert.NotNull(playerEnt); + var alertsComponent = playerEnt.GetComponent(); + Assert.NotNull(alertsComponent); + + alertsComponent.ClearAlert(AlertType.Debug1); + }); + await server.WaitRunTicks(5); + await client.WaitRunTicks(5); + + await client.WaitAssertion(() => + { + + var local = clientPlayerMgr.LocalPlayer; + Assert.NotNull(local); + var controlled = local.ControlledEntity; + Assert.NotNull(controlled); + var alertsComponent = controlled.GetComponent(); + Assert.NotNull(alertsComponent); + + // find the alertsui + var alertsUI = + clientUIMgr.StateRoot.Children.FirstOrDefault(c => c is AlertsUI) as AlertsUI; + Assert.NotNull(alertsUI); + + // we should be seeing only 2 alerts now because one was cleared + Assert.That(alertsUI.Grid.ChildCount, Is.EqualTo(2)); + var alertControls = alertsUI.Grid.Children.Select(c => c as AlertControl); + var alertIDs = alertControls.Select(ac => ac.Alert.AlertType).ToArray(); + var expectedIDs = new [] {AlertType.HumanHealth, AlertType.Debug2}; + Assert.That(alertIDs, Is.EqualTo(expectedIDs)); + }); + } + } +} diff --git a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs index 3e128bceee..5e0574c321 100644 --- a/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs +++ b/Content.IntegrationTests/Tests/Gravity/WeightlessStatusTests.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Content.Server.GameObjects.Components.Gravity; using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Gravity; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; @@ -32,7 +33,7 @@ namespace Content.IntegrationTests.Tests.Gravity var tileDefinitionManager = server.ResolveDependency(); IEntity human = null; - SharedStatusEffectsComponent statusEffects = null; + SharedAlertsComponent alerts = null; await server.WaitAssertion(() => { @@ -57,7 +58,7 @@ namespace Content.IntegrationTests.Tests.Gravity human = entityManager.SpawnEntity("HumanMob_Content", coordinates); - Assert.True(human.TryGetComponent(out statusEffects)); + Assert.True(human.TryGetComponent(out alerts)); }); // Let WeightlessSystem and GravitySystem tick @@ -68,7 +69,7 @@ namespace Content.IntegrationTests.Tests.Gravity await server.WaitAssertion(() => { // No gravity without a gravity generator - Assert.True(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless)); + Assert.True(alerts.IsShowingAlert(AlertType.Weightless)); gravityGenerator = human.EnsureComponent(); }); @@ -78,7 +79,7 @@ namespace Content.IntegrationTests.Tests.Gravity await server.WaitAssertion(() => { - Assert.False(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless)); + Assert.False(alerts.IsShowingAlert(AlertType.Weightless)); // Disable the gravity generator var args = new BreakageEventArgs {Owner = human}; @@ -89,7 +90,7 @@ namespace Content.IntegrationTests.Tests.Gravity await server.WaitAssertion(() => { - Assert.False(statusEffects.Statuses.ContainsKey(StatusEffect.Weightless)); + Assert.False(alerts.IsShowingAlert(AlertType.Weightless)); }); } } diff --git a/Content.Server/Commands/CommandUtils.cs b/Content.Server/Commands/CommandUtils.cs new file mode 100644 index 0000000000..b6535dc7d3 --- /dev/null +++ b/Content.Server/Commands/CommandUtils.cs @@ -0,0 +1,66 @@ +using System; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Network; + +namespace Content.Server.Commands +{ + /// + /// Utilities for writing commands + /// + public static class CommandUtils + { + /// + /// Gets the player session for the player with the indicated id, + /// sending a failure to the performer if unable to. + /// + public static bool TryGetSessionByUsernameOrId(IConsoleShell shell, + string usernameOrId, IPlayerSession performer, out IPlayerSession session) + { + var plyMgr = IoCManager.Resolve(); + if (plyMgr.TryGetSessionByUsername(usernameOrId, out session)) return true; + if (Guid.TryParse(usernameOrId, out var targetGuid)) + { + if (plyMgr.TryGetSessionById(new NetUserId(targetGuid), out session)) return true; + shell.SendText(performer, "Unable to find user with that name/id."); + return false; + } + + shell.SendText(performer, "Unable to find user with that name/id."); + return false; + } + + /// + /// Gets the attached entity for the player session with the indicated id, + /// sending a failure to the performer if unable to. + /// + public static bool TryGetAttachedEntityByUsernameOrId(IConsoleShell shell, + string usernameOrId, IPlayerSession performer, out IEntity attachedEntity) + { + attachedEntity = null; + if (!TryGetSessionByUsernameOrId(shell, usernameOrId, performer, out var session)) return false; + if (session.AttachedEntity == null) + { + shell.SendText(performer, "User has no attached entity."); + return false; + } + + attachedEntity = session.AttachedEntity; + return true; + } + + /// + /// Checks if attached entity is null, returning false and sending a message + /// to performer if not. + /// + public static bool ValidateAttachedEntity(IConsoleShell shell, IPlayerSession performer, IEntity attachedEntity) + { + if (attachedEntity != null) return true; + shell.SendText(performer, "User has no attached entity."); + return false; + } + + } +} diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 9542e2b36a..ca684623f4 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -9,6 +9,7 @@ using Content.Server.Interfaces.GameTicking; using Content.Server.Interfaces.PDA; using Content.Server.Sandbox; using Content.Shared.Kitchen; +using Content.Shared.Alert; using Robust.Server.Interfaces.Player; using Robust.Shared.ContentPack; using Robust.Shared.Interfaces.GameObjects; @@ -74,6 +75,7 @@ namespace Content.Server _gameTicker.Initialize(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); diff --git a/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs b/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs index 35c1263cf0..510715b1e8 100644 --- a/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs +++ b/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.ActionBlocking; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; @@ -115,7 +116,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking CanStillInteract = _hands.Hands.Count() > CuffedHandCount; OnCuffedStateChanged.Invoke(); - UpdateStatusEffect(); + UpdateAlert(); UpdateHeldItems(); Dirty(); } @@ -181,17 +182,17 @@ namespace Content.Server.GameObjects.Components.ActionBlocking /// /// Updates the status effect indicator on the HUD. /// - private void UpdateStatusEffect() + private void UpdateAlert() { - if (Owner.TryGetComponent(out ServerStatusEffectsComponent status)) + if (Owner.TryGetComponent(out ServerAlertsComponent status)) { if (CanStillInteract) { - status.RemoveStatusEffect(StatusEffect.Cuffed); + status.ClearAlert(AlertType.Handcuffed); } else { - status.ChangeStatusEffectIcon(StatusEffect.Cuffed, "/Textures/Interface/StatusEffects/Handcuffed/Handcuffed.png"); + status.ShowAlert(AlertType.Handcuffed); } } } @@ -282,7 +283,7 @@ namespace Content.Server.GameObjects.Components.ActionBlocking CanStillInteract = _hands.Hands.Count() > CuffedHandCount; OnCuffedStateChanged.Invoke(); - UpdateStatusEffect(); + UpdateAlert(); Dirty(); if (CuffedHandCount == 0) diff --git a/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs b/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs index 6710298441..f595aa4b13 100644 --- a/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/BarotraumaComponent.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using Content.Server.GameObjects.Components.Mobs; using Content.Server.Interfaces.GameObjects; +using Content.Shared.Alert; using Content.Shared.Atmos; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; @@ -22,7 +23,7 @@ namespace Content.Server.GameObjects.Components.Atmos public void Update(float airPressure) { if (!Owner.TryGetComponent(out IDamageableComponent damageable)) return; - Owner.TryGetComponent(out ServerStatusEffectsComponent status); + Owner.TryGetComponent(out ServerAlertsComponent status); var highPressureMultiplier = 1f; var lowPressureMultiplier = 1f; @@ -50,11 +51,11 @@ namespace Content.Server.GameObjects.Components.Atmos if (pressure <= Atmospherics.HazardLowPressure) { - status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/lowpressure2.png", null); + status.ShowAlert(AlertType.LowPressure, 2); break; } - status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/lowpressure1.png", null); + status.ShowAlert(AlertType.LowPressure, 1); break; // High pressure. @@ -72,16 +73,16 @@ namespace Content.Server.GameObjects.Components.Atmos if (pressure >= Atmospherics.HazardHighPressure) { - status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/highpressure2.png", null); + status.ShowAlert(AlertType.HighPressure, 2); break; } - status.ChangeStatusEffect(StatusEffect.Pressure, "/Textures/Interface/StatusEffects/Pressure/highpressure1.png", null); + status.ShowAlert(AlertType.HighPressure, 1); break; // Normal pressure. default: - status?.RemoveStatusEffect(StatusEffect.Pressure); + status?.ClearAlertCategory(AlertCategory.Pressure); break; } diff --git a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs index 6ca1388d84..137725f25d 100644 --- a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs @@ -4,6 +4,7 @@ using Content.Server.Atmos; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Temperature; using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.Atmos; using Content.Shared.Chemistry; using Content.Shared.Damage; @@ -93,15 +94,15 @@ namespace Content.Server.GameObjects.Components.Atmos FireStacks = MathF.Min(0, FireStacks + 1); } - Owner.TryGetComponent(out ServerStatusEffectsComponent status); + Owner.TryGetComponent(out ServerAlertsComponent status); if (!OnFire) { - status?.RemoveStatusEffect(StatusEffect.Fire); + status?.ClearAlert(AlertType.Fire); return; } - status?.ChangeStatusEffect(StatusEffect.Fire, "/Textures/Interface/StatusEffects/Fire/fire.png", null); + status.ShowAlert(AlertType.Fire, onClickAlert: OnClickAlert); if (FireStacks > 0) { @@ -153,6 +154,14 @@ namespace Content.Server.GameObjects.Components.Atmos } } + private void OnClickAlert(ClickAlertEventArgs args) + { + if (args.Player.TryGetComponent(out FlammableComponent flammable)) + { + flammable.Resist(); + } + } + public void CollideWith(IEntity collidedWith) { if (!collidedWith.TryGetComponent(out FlammableComponent otherFlammable)) diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 0eb0ffebea..1c4c0f55f8 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -7,6 +7,7 @@ using Content.Server.GameObjects.Components.Mobs.State; using Content.Server.GameObjects.Components.Pulling; using Content.Server.GameObjects.Components.Strap; using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Buckle; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Strap; @@ -37,7 +38,7 @@ namespace Content.Server.GameObjects.Components.Buckle [Dependency] private readonly IGameTiming _gameTiming = default!; [ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null; - [ComponentDependency] private readonly ServerStatusEffectsComponent? _serverStatusEffectsComponent = null; + [ComponentDependency] private readonly ServerAlertsComponent? _serverAlertsComponent = null; [ComponentDependency] private readonly StunnableComponent? _stunnableComponent = null; [ComponentDependency] private readonly MobStateManagerComponent? _mobStateManagerComponent = null; @@ -100,21 +101,31 @@ namespace Content.Server.GameObjects.Components.Buckle /// private void UpdateBuckleStatus() { - if (_serverStatusEffectsComponent == null) + if (_serverAlertsComponent == null) { return; } if (Buckled) { - _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon); + _serverAlertsComponent.ShowAlert(BuckledTo != null ? BuckledTo.BuckledAlertType : AlertType.Buckled, + onClickAlert: OnClickAlert); } else { - _serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled); + _serverAlertsComponent.ClearAlertCategory(AlertCategory.Buckled); } } + private void OnClickAlert(ClickAlertEventArgs args) + { + if (args.Player.TryGetComponent(out BuckleComponent? buckle)) + { + buckle.TryUnbuckle(args.Player); + } + } + + /// /// Reattaches this entity to the strap, modifying its position and rotation. /// diff --git a/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs b/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs new file mode 100644 index 0000000000..2587b491e4 --- /dev/null +++ b/Content.Server/GameObjects/Components/Mobs/ServerAlertsComponent.cs @@ -0,0 +1,166 @@ +using System; +using Content.Server.Commands; +using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; +using Content.Shared.GameObjects.Components.Mobs; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Players; + +namespace Content.Server.GameObjects.Components.Mobs +{ + [RegisterComponent] + [ComponentReference(typeof(SharedAlertsComponent))] + public sealed class ServerAlertsComponent : SharedAlertsComponent + { + + protected override void Startup() + { + base.Startup(); + + if (EntitySystem.TryGet(out var weightlessSystem)) + { + weightlessSystem.AddAlert(this); + } + else + { + Logger.WarningS("alert", "weightlesssystem not found"); + } + } + + public override void OnRemove() + { + if (EntitySystem.TryGet(out var weightlessSystem)) + { + weightlessSystem.RemoveAlert(this); + } + else + { + Logger.WarningS("alert", "weightlesssystem not found"); + } + + base.OnRemove(); + } + + public override ComponentState GetComponentState() + { + return new AlertsComponentState(CreateAlertStatesArray()); + } + + public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null) + { + base.HandleNetworkMessage(message, netChannel, session); + + if (session == null) + { + throw new ArgumentNullException(nameof(session)); + } + + switch (message) + { + case ClickAlertMessage msg: + { + var player = session.AttachedEntity; + + if (player != Owner) + { + break; + } + + // TODO: Implement clicking other status effects in the HUD + if (AlertManager.TryDecode(msg.EncodedAlert, out var alert)) + { + PerformAlertClickCallback(alert, player); + } + else + { + Logger.WarningS("alert", "unrecognized encoded alert {0}", msg.EncodedAlert); + } + + break; + } + } + } + } + + public sealed class ShowAlert : IClientCommand + { + public string Command => "showalert"; + public string Description => "Shows an alert for a player, defaulting to current player"; + public string Help => "showalert "; + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var attachedEntity = player.AttachedEntity; + if (args.Length > 2) + { + var target = args[2]; + if (!Commands.CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; + } + + if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return; + + + if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent)) + { + shell.SendText(player, "user has no alerts component"); + return; + } + + var alertType = args[0]; + var severity = args[1]; + var alertMgr = IoCManager.Resolve(); + if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) + { + shell.SendText(player, "unrecognized alertType " + alertType); + return; + } + if (!short.TryParse(severity, out var sevint)) + { + shell.SendText(player, "invalid severity " + sevint); + return; + } + alertsComponent.ShowAlert(alert.AlertType, sevint == -1 ? (short?) null : sevint); + + } + } + + public sealed class ClearAlert : IClientCommand + { + public string Command => "clearalert"; + public string Description => "Clears an alert for a player, defaulting to current player"; + public string Help => "clearalert "; + + public void Execute(IConsoleShell shell, IPlayerSession player, string[] args) + { + var attachedEntity = player.AttachedEntity; + if (args.Length > 1) + { + var target = args[1]; + if (!CommandUtils.TryGetAttachedEntityByUsernameOrId(shell, target, player, out attachedEntity)) return; + } + + if (!CommandUtils.ValidateAttachedEntity(shell, player, attachedEntity)) return; + + if (!attachedEntity.TryGetComponent(out ServerAlertsComponent alertsComponent)) + { + shell.SendText(player, "user has no alerts component"); + return; + } + + var alertType = args[0]; + var alertMgr = IoCManager.Resolve(); + if (!alertMgr.TryGet(Enum.Parse(alertType), out var alert)) + { + shell.SendText(player, "unrecognized alertType " + alertType); + return; + } + + alertsComponent.ClearAlert(alert.AlertType); + } + } +} diff --git a/Content.Server/GameObjects/Components/Mobs/ServerStatusEffectsComponent.cs b/Content.Server/GameObjects/Components/Mobs/ServerStatusEffectsComponent.cs deleted file mode 100644 index 8715fdb3d7..0000000000 --- a/Content.Server/GameObjects/Components/Mobs/ServerStatusEffectsComponent.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using Content.Server.GameObjects.Components.Atmos; -using Content.Server.GameObjects.Components.Buckle; -using Content.Server.GameObjects.Components.Movement; -using Content.Server.GameObjects.EntitySystems; -using Content.Shared.GameObjects.Components.Mobs; -using Content.Shared.GameObjects.Components.Pulling; -using Content.Shared.GameObjects.EntitySystems; -using Content.Shared.Interfaces; -using Robust.Shared.GameObjects; -using Robust.Shared.GameObjects.Systems; -using Robust.Shared.Interfaces.Network; -using Robust.Shared.Players; -using Robust.Shared.ViewVariables; - -namespace Content.Server.GameObjects.Components.Mobs -{ - [RegisterComponent] - [ComponentReference(typeof(SharedStatusEffectsComponent))] - public sealed class ServerStatusEffectsComponent : SharedStatusEffectsComponent - { - [ViewVariables] - private readonly Dictionary _statusEffects = new Dictionary(); - - public override IReadOnlyDictionary Statuses => _statusEffects; - - protected override void Startup() - { - base.Startup(); - - EntitySystem.Get().AddStatus(this); - } - - public override void OnRemove() - { - EntitySystem.Get().RemoveStatus(this); - - base.OnRemove(); - } - - public override ComponentState GetComponentState() - { - return new StatusEffectComponentState(_statusEffects); - } - - public override void ChangeStatusEffectIcon(StatusEffect effect, string icon) - { - if (_statusEffects.TryGetValue(effect, out var value) && value.Icon == icon) - { - return; - } - - _statusEffects[effect] = new StatusEffectStatus() - {Icon = icon, Cooldown = value.Cooldown}; - Dirty(); - } - - public void ChangeStatusEffectCooldown(StatusEffect effect, ValueTuple cooldown) - { - if (_statusEffects.TryGetValue(effect, out var value) - && value.Cooldown == cooldown) - { - return; - } - - _statusEffects[effect] = new StatusEffectStatus() - { - Icon = value.Icon, Cooldown = cooldown - }; - Dirty(); - } - - public override void ChangeStatusEffect(StatusEffect effect, string icon, ValueTuple? cooldown) - { - _statusEffects[effect] = new StatusEffectStatus() - {Icon = icon, Cooldown = cooldown}; - - Dirty(); - } - - public override void RemoveStatusEffect(StatusEffect effect) - { - if (!_statusEffects.Remove(effect)) - { - return; - } - - Dirty(); - } - - public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null) - { - base.HandleNetworkMessage(message, netChannel, session); - - if (session == null) - { - throw new ArgumentNullException(nameof(session)); - } - - switch (message) - { - case ClickStatusMessage msg: - { - var player = session.AttachedEntity; - - if (player != Owner) - { - break; - } - - // TODO: Implement clicking other status effects in the HUD - switch (msg.Effect) - { - case StatusEffect.Buckled: - if (!player.TryGetComponent(out BuckleComponent buckle)) - break; - - buckle.TryUnbuckle(player); - break; - case StatusEffect.Piloting: - if (!player.TryGetComponent(out ShuttleControllerComponent controller)) - break; - - controller.RemoveController(); - break; - case StatusEffect.Pulling: - EntitySystem - .Get() - .GetPulled(player)? - .GetComponentOrNull()? - .TryStopPull(); - - break; - case StatusEffect.Fire: - if (!player.TryGetComponent(out FlammableComponent flammable)) - break; - - flammable.Resist(); - break; - default: - player.PopupMessage(msg.Effect.ToString()); - break; - } - - break; - } - } - } - } - -} diff --git a/Content.Server/GameObjects/Components/Mobs/State/CriticalState.cs b/Content.Server/GameObjects/Components/Mobs/State/CriticalState.cs index 0adea20dde..9e6d92a0e0 100644 --- a/Content.Server/GameObjects/Components/Mobs/State/CriticalState.cs +++ b/Content.Server/GameObjects/Components/Mobs/State/CriticalState.cs @@ -1,4 +1,5 @@ using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; @@ -17,10 +18,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State appearance.SetData(DamageStateVisuals.State, DamageState.Critical); } - if (entity.TryGetComponent(out ServerStatusEffectsComponent status)) + if (entity.TryGetComponent(out ServerAlertsComponent status)) { - status.ChangeStatusEffectIcon(StatusEffect.Health, - "/Textures/Interface/StatusEffects/Human/humancrit-0.png"); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it + status.ShowAlert(AlertType.HumanCrit); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it } if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay)) diff --git a/Content.Server/GameObjects/Components/Mobs/State/DeadState.cs b/Content.Server/GameObjects/Components/Mobs/State/DeadState.cs index 9fc2428975..cdd4673510 100644 --- a/Content.Server/GameObjects/Components/Mobs/State/DeadState.cs +++ b/Content.Server/GameObjects/Components/Mobs/State/DeadState.cs @@ -1,4 +1,5 @@ using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; @@ -18,10 +19,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State appearance.SetData(DamageStateVisuals.State, DamageState.Dead); } - if (entity.TryGetComponent(out ServerStatusEffectsComponent status)) + if (entity.TryGetComponent(out ServerAlertsComponent status)) { - status.ChangeStatusEffectIcon(StatusEffect.Health, - "/Textures/Interface/StatusEffects/Human/humandead.png"); + status.ShowAlert(AlertType.HumanDead); } if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlayComponent)) diff --git a/Content.Server/GameObjects/Components/Mobs/State/MobStateManager.cs b/Content.Server/GameObjects/Components/Mobs/State/MobStateManager.cs index c0e90dd9fa..d315ed1b0e 100644 --- a/Content.Server/GameObjects/Components/Mobs/State/MobStateManager.cs +++ b/Content.Server/GameObjects/Components/Mobs/State/MobStateManager.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; @@ -51,9 +52,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State // TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used base.OnRemove(); - if (Owner.TryGetComponent(out ServerStatusEffectsComponent status)) + if (Owner.TryGetComponent(out ServerAlertsComponent status)) { - status.RemoveStatusEffect(StatusEffect.Health); + status.ClearAlert(AlertType.HumanHealth); } if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay)) diff --git a/Content.Server/GameObjects/Components/Mobs/State/NormalState.cs b/Content.Server/GameObjects/Components/Mobs/State/NormalState.cs index 6b8eb4aab3..5915ccebbe 100644 --- a/Content.Server/GameObjects/Components/Mobs/State/NormalState.cs +++ b/Content.Server/GameObjects/Components/Mobs/State/NormalState.cs @@ -1,5 +1,6 @@ using Content.Server.GameObjects.Components.Damage; using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; @@ -27,15 +28,14 @@ namespace Content.Server.GameObjects.Components.Mobs.State public override void UpdateState(IEntity entity) { - if (!entity.TryGetComponent(out ServerStatusEffectsComponent status)) + if (!entity.TryGetComponent(out ServerAlertsComponent status)) { return; } if (!entity.TryGetComponent(out IDamageableComponent damageable)) { - status.ChangeStatusEffectIcon(StatusEffect.Health, - "/Textures/Interface/StatusEffects/Human/human0.png"); + status.ShowAlert(AlertType.HumanHealth, 0); return; } @@ -49,10 +49,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State return; } - var modifier = (int) (ruinable.TotalDamage / (threshold / 7f)); + var modifier = (short) (ruinable.TotalDamage / (threshold / 7f)); - status.ChangeStatusEffectIcon(StatusEffect.Health, - "/Textures/Interface/StatusEffects/Human/human" + modifier + ".png"); + status.ShowAlert(AlertType.HumanHealth, modifier); break; } @@ -63,10 +62,9 @@ namespace Content.Server.GameObjects.Components.Mobs.State return; } - var modifier = (int) (damageable.TotalDamage / (threshold / 7f)); + var modifier = (short) (damageable.TotalDamage / (threshold / 7f)); - status.ChangeStatusEffectIcon(StatusEffect.Health, - "/Textures/Interface/StatusEffects/Human/human" + modifier + ".png"); + status.ShowAlert(AlertType.HumanHealth, modifier); break; } } diff --git a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs index 1af15ecce2..9f3ec4def6 100644 --- a/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/StunnableComponent.cs @@ -1,4 +1,5 @@ using Content.Server.GameObjects.EntitySystems; +using Content.Shared.Alert; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Movement; @@ -89,7 +90,7 @@ namespace Content.Server.GameObjects.Components.Mobs } if (!StunStart.HasValue || !StunEnd.HasValue || - !Owner.TryGetComponent(out ServerStatusEffectsComponent status)) + !Owner.TryGetComponent(out ServerAlertsComponent status)) { return; } @@ -102,7 +103,7 @@ namespace Content.Server.GameObjects.Components.Mobs if (progress >= length) { - Owner.SpawnTimer(250, () => status.RemoveStatusEffect(StatusEffect.Stun), StatusRemoveCancellation.Token); + Owner.SpawnTimer(250, () => status.ClearAlert(AlertType.Stun), StatusRemoveCancellation.Token); LastStun = null; } } diff --git a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs index 2def6aac43..db25892f5b 100644 --- a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs @@ -1,6 +1,7 @@ #nullable enable using Content.Server.GameObjects.Components.Buckle; using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.Components.Strap; @@ -31,9 +32,9 @@ namespace Content.Server.GameObjects.Components.Movement private bool _movingRight; /// - /// The icon to be displayed when piloting from this chair. + /// ID of the alert to show when piloting /// - private string _pilotingIcon = default!; + private AlertType _pilotingAlertType; /// /// The entity that's currently controlling this component. @@ -137,7 +138,7 @@ namespace Content.Server.GameObjects.Components.Movement if (_controller != null || !entity.TryGetComponent(out MindComponent? mind) || mind.Mind == null || - !Owner.TryGetComponent(out ServerStatusEffectsComponent? status)) + !Owner.TryGetComponent(out ServerAlertsComponent? status)) { return; } @@ -145,7 +146,15 @@ namespace Content.Server.GameObjects.Components.Movement mind.Mind.Visit(Owner); _controller = entity; - status.ChangeStatusEffectIcon(StatusEffect.Piloting, _pilotingIcon); + status.ShowAlert(_pilotingAlertType, onClickAlert: OnClickAlert); + } + + private void OnClickAlert(ClickAlertEventArgs args) + { + if (args.Player.TryGetComponent(out ShuttleControllerComponent? controller)) + { + controller.RemoveController(); + } } /// @@ -177,9 +186,9 @@ namespace Content.Server.GameObjects.Components.Movement /// The entity to update private void UpdateRemovedEntity(IEntity entity) { - if (Owner.TryGetComponent(out ServerStatusEffectsComponent? status)) + if (Owner.TryGetComponent(out ServerAlertsComponent? status)) { - status.RemoveStatusEffect(StatusEffect.Piloting); + status.ClearAlert(_pilotingAlertType); } if (entity.TryGetComponent(out MindComponent? mind)) @@ -211,13 +220,13 @@ namespace Content.Server.GameObjects.Components.Movement { base.ExposeData(serializer); - serializer.DataField(ref _pilotingIcon, "pilotingIcon", "/Textures/Interface/StatusEffects/Buckle/buckled.png"); + serializer.DataField(ref _pilotingAlertType, "pilotingAlertType", AlertType.PilotingShuttle); } public override void Initialize() { base.Initialize(); - Owner.EnsureComponent(); + Owner.EnsureComponent(); } /// diff --git a/Content.Server/GameObjects/Components/Nutrition/HungerComponent.cs b/Content.Server/GameObjects/Components/Nutrition/HungerComponent.cs index 9ea95624cc..32e13a360a 100644 --- a/Content.Server/GameObjects/Components/Nutrition/HungerComponent.cs +++ b/Content.Server/GameObjects/Components/Nutrition/HungerComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; @@ -70,11 +71,11 @@ namespace Content.Server.GameObjects.Components.Nutrition } - public static readonly Dictionary HungerThresholdImages = new Dictionary + public static readonly Dictionary HungerThresholdAlertTypes = new Dictionary { - { HungerThreshold.Overfed, "/Textures/Interface/StatusEffects/Hunger/Overfed.png" }, - { HungerThreshold.Peckish, "/Textures/Interface/StatusEffects/Hunger/Peckish.png" }, - { HungerThreshold.Starving, "/Textures/Interface/StatusEffects/Hunger/Starving.png" }, + { HungerThreshold.Overfed, AlertType.Overfed }, + { HungerThreshold.Peckish, AlertType.Peckish }, + { HungerThreshold.Starving, AlertType.Starving }, }; public void HungerThresholdEffect(bool force = false) @@ -89,15 +90,15 @@ namespace Content.Server.GameObjects.Components.Nutrition } // Update UI - Owner.TryGetComponent(out ServerStatusEffectsComponent statusEffectsComponent); + Owner.TryGetComponent(out ServerAlertsComponent alertsComponent); - if (HungerThresholdImages.TryGetValue(_currentHungerThreshold, out var statusTexture)) + if (HungerThresholdAlertTypes.TryGetValue(_currentHungerThreshold, out var alertId)) { - statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Hunger, statusTexture); + alertsComponent?.ShowAlert(alertId); } else { - statusEffectsComponent?.RemoveStatusEffect(StatusEffect.Hunger); + alertsComponent?.ClearAlertCategory(AlertCategory.Hunger); } switch (_currentHungerThreshold) diff --git a/Content.Server/GameObjects/Components/Nutrition/ThirstComponent.cs b/Content.Server/GameObjects/Components/Nutrition/ThirstComponent.cs index 2d294e8db6..6462141610 100644 --- a/Content.Server/GameObjects/Components/Nutrition/ThirstComponent.cs +++ b/Content.Server/GameObjects/Components/Nutrition/ThirstComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; @@ -62,11 +63,11 @@ namespace Content.Server.GameObjects.Components.Nutrition {ThirstThreshold.Dead, 0.0f}, }; - public static readonly Dictionary ThirstThresholdImages = new Dictionary + public static readonly Dictionary ThirstThresholdAlertTypes = new Dictionary { - {ThirstThreshold.OverHydrated, "/Textures/Interface/StatusEffects/Thirst/OverHydrated.png"}, - {ThirstThreshold.Thirsty, "/Textures/Interface/StatusEffects/Thirst/Thirsty.png"}, - {ThirstThreshold.Parched, "/Textures/Interface/StatusEffects/Thirst/Parched.png"}, + {ThirstThreshold.OverHydrated, AlertType.Overhydrated}, + {ThirstThreshold.Thirsty, AlertType.Thirsty}, + {ThirstThreshold.Parched, AlertType.Parched}, }; public override void ExposeData(ObjectSerializer serializer) @@ -87,15 +88,15 @@ namespace Content.Server.GameObjects.Components.Nutrition } // Update UI - Owner.TryGetComponent(out ServerStatusEffectsComponent statusEffectsComponent); + Owner.TryGetComponent(out ServerAlertsComponent alertsComponent); - if (ThirstThresholdImages.TryGetValue(_currentThirstThreshold, out var statusTexture)) + if (ThirstThresholdAlertTypes.TryGetValue(_currentThirstThreshold, out var alertId)) { - statusEffectsComponent?.ChangeStatusEffectIcon(StatusEffect.Thirst, statusTexture); + alertsComponent?.ShowAlert(alertId); } else { - statusEffectsComponent?.RemoveStatusEffect(StatusEffect.Thirst); + alertsComponent?.ClearAlertCategory(AlertCategory.Thirst); } switch (_currentThirstThreshold) diff --git a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs index 3bd7b5c4cb..a6ad9585b5 100644 --- a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs +++ b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components.Buckle; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; @@ -27,7 +28,7 @@ namespace Content.Server.GameObjects.Components.Strap private StrapPosition _position; private string _buckleSound = null!; private string _unbuckleSound = null!; - private string _buckledIcon = null!; + private AlertType _buckledAlertType; /// /// The angle in degrees to rotate the player by when they get strapped @@ -65,10 +66,10 @@ namespace Content.Server.GameObjects.Components.Strap public string UnbuckleSound => _unbuckleSound; /// - /// The icon to be displayed as a status when buckled + /// ID of the alert to show when buckled /// [ViewVariables] - public string BuckledIcon => _buckledIcon; + public AlertType BuckledAlertType => _buckledAlertType; /// /// The sum of the sizes of all the buckled entities in this strap @@ -137,7 +138,7 @@ namespace Content.Server.GameObjects.Components.Strap serializer.DataField(ref _position, "position", StrapPosition.None); serializer.DataField(ref _buckleSound, "buckleSound", "/Audio/Effects/buckle.ogg"); serializer.DataField(ref _unbuckleSound, "unbuckleSound", "/Audio/Effects/unbuckle.ogg"); - serializer.DataField(ref _buckledIcon, "buckledIcon", "/Textures/Interface/StatusEffects/Buckle/buckled.png"); + serializer.DataField(ref _buckledAlertType, "buckledAlertType", AlertType.Buckled); serializer.DataField(ref _rotation, "rotation", 0); var defaultSize = 100; diff --git a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs index 72c318091b..8b59293975 100644 --- a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs +++ b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; using Content.Shared.Atmos; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; @@ -74,43 +75,43 @@ namespace Content.Server.GameObjects.Components.Temperature damageType = DamageType.Cold; } - if (Owner.TryGetComponent(out ServerStatusEffectsComponent status)) + if (Owner.TryGetComponent(out ServerAlertsComponent status)) { switch(CurrentTemperature) { // Cold strong. case var t when t <= 260: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold3.png", null); + status.ShowAlert(AlertType.Cold, 3); break; // Cold mild. case var t when t <= 280 && t > 260: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold2.png", null); + status.ShowAlert(AlertType.Cold, 2); break; // Cold weak. case var t when t <= 292 && t > 280: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/cold1.png", null); + status.ShowAlert(AlertType.Cold, 1); break; // Safe. case var t when t <= 327 && t > 292: - status.RemoveStatusEffect(StatusEffect.Temperature); + status.ClearAlertCategory(AlertCategory.Temperature); break; // Heat weak. case var t when t <= 335 && t > 327: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot1.png", null); + status.ShowAlert(AlertType.Hot, 1); break; // Heat mild. case var t when t <= 345 && t > 335: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot2.png", null); + status.ShowAlert(AlertType.Hot, 2); break; // Heat strong. case var t when t > 345: - status.ChangeStatusEffect(StatusEffect.Temperature, "/Textures/Interface/StatusEffects/Temperature/hot3.png", null); + status.ShowAlert(AlertType.Hot, 3); break; } } diff --git a/Content.Server/GameObjects/EntitySystems/WeightlessSystem.cs b/Content.Server/GameObjects/EntitySystems/WeightlessSystem.cs index 1ceec26a0a..c18fb5c8a6 100644 --- a/Content.Server/GameObjects/EntitySystems/WeightlessSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/WeightlessSystem.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystemMessages.Gravity; using Content.Shared.GameTicking; @@ -19,7 +20,7 @@ namespace Content.Server.GameObjects.EntitySystems { [Dependency] private readonly IMapManager _mapManager = default!; - private readonly Dictionary> _statuses = new Dictionary>(); + private readonly Dictionary> _alerts = new Dictionary>(); public override void Initialize() { @@ -31,15 +32,15 @@ namespace Content.Server.GameObjects.EntitySystems public void Reset() { - _statuses.Clear(); + _alerts.Clear(); } - public void AddStatus(ServerStatusEffectsComponent status) + public void AddAlert(ServerAlertsComponent status) { var gridId = status.Owner.Transform.GridID; - var statuses = _statuses.GetOrNew(gridId); + var alerts = _alerts.GetOrNew(gridId); - statuses.Add(status); + alerts.Add(status); if (_mapManager.TryGetGrid(status.Owner.Transform.GridID, out var grid)) { @@ -54,10 +55,10 @@ namespace Content.Server.GameObjects.EntitySystems } } - public void RemoveStatus(ServerStatusEffectsComponent status) + public void RemoveAlert(ServerAlertsComponent status) { var grid = status.Owner.Transform.GridID; - if (!_statuses.TryGetValue(grid, out var statuses)) + if (!_alerts.TryGetValue(grid, out var statuses)) { return; } @@ -67,7 +68,7 @@ namespace Content.Server.GameObjects.EntitySystems private void GravityChanged(GravityChangedMessage ev) { - if (!_statuses.TryGetValue(ev.Grid.Index, out var statuses)) + if (!_alerts.TryGetValue(ev.Grid.Index, out var statuses)) { return; } @@ -88,19 +89,19 @@ namespace Content.Server.GameObjects.EntitySystems } } - private void AddWeightless(ServerStatusEffectsComponent status) + private void AddWeightless(ServerAlertsComponent status) { - status.ChangeStatusEffect(StatusEffect.Weightless, "/Textures/Interface/StatusEffects/Weightless/weightless.png", null); + status.ShowAlert(AlertType.Weightless); } - private void RemoveWeightless(ServerStatusEffectsComponent status) + private void RemoveWeightless(ServerAlertsComponent status) { - status.RemoveStatusEffect(StatusEffect.Weightless); + status.ClearAlert(AlertType.Weightless); } private void EntParentChanged(EntParentChangedMessage ev) { - if (!ev.Entity.TryGetComponent(out ServerStatusEffectsComponent status)) + if (!ev.Entity.TryGetComponent(out ServerAlertsComponent status)) { return; } @@ -110,14 +111,14 @@ namespace Content.Server.GameObjects.EntitySystems { var oldGrid = mapGrid.GridIndex; - if (_statuses.TryGetValue(oldGrid, out var oldStatuses)) + if (_alerts.TryGetValue(oldGrid, out var oldStatuses)) { oldStatuses.Remove(status); } } var newGrid = ev.Entity.Transform.GridID; - var newStatuses = _statuses.GetOrNew(newGrid); + var newStatuses = _alerts.GetOrNew(newGrid); newStatuses.Add(status); } diff --git a/Content.Server/ServerContentIoC.cs b/Content.Server/ServerContentIoC.cs index f9c86be44d..362b7ebe56 100644 --- a/Content.Server/ServerContentIoC.cs +++ b/Content.Server/ServerContentIoC.cs @@ -18,6 +18,7 @@ using Content.Server.Sandbox; using Content.Server.Utility; using Content.Shared.Interfaces; using Content.Shared.Kitchen; +using Content.Shared.Alert; using Robust.Shared.IoC; namespace Content.Server @@ -37,6 +38,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); diff --git a/Content.Shared/Alert/AlertManager.cs b/Content.Shared/Alert/AlertManager.cs new file mode 100644 index 0000000000..392b731a83 --- /dev/null +++ b/Content.Shared/Alert/AlertManager.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using System.Linq; +using Content.Shared.Prototypes.Kitchen; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Alert +{ + /// + /// Provides access to all configured alerts. Ability to encode/decode a given state + /// to an int. + /// + public class AlertManager + { + [Dependency] + private readonly IPrototypeManager _prototypeManager = default!; + + private AlertPrototype[] _orderedAlerts; + private Dictionary _typeToIndex; + + public void Initialize() + { + // order by type value so we can map between the id and an integer index and use + // the index for compact alert change messages + _orderedAlerts = + _prototypeManager.EnumeratePrototypes() + .OrderBy(prototype => prototype.AlertType).ToArray(); + _typeToIndex = new Dictionary(); + + for (var i = 0; i < _orderedAlerts.Length; i++) + { + if (i > byte.MaxValue) + { + Logger.ErrorS("alert", "too many alerts for byte encoding ({0})! encoding will need" + + " to be changed to use a ushort rather than byte", _typeToIndex.Count); + break; + } + if (!_typeToIndex.TryAdd(_orderedAlerts[i].AlertType, (byte) i)) + { + Logger.ErrorS("alert", + "Found alert with duplicate id {0}", _orderedAlerts[i].AlertType); + } + } + + } + + /// + /// Tries to get the alert of the indicated type + /// + /// true if found + public bool TryGet(AlertType alertType, out AlertPrototype alert) + { + if (_typeToIndex.TryGetValue(alertType, out var idx)) + { + alert = _orderedAlerts[idx]; + return true; + } + + alert = null; + return false; + } + + /// + /// Tries to get the alert of the indicated type along with its encoding + /// + /// true if found + public bool TryGetWithEncoded(AlertType alertType, out AlertPrototype alert, out byte encoded) + { + if (_typeToIndex.TryGetValue(alertType, out var idx)) + { + alert = _orderedAlerts[idx]; + encoded = (byte) idx; + return true; + } + + alert = null; + encoded = 0; + return false; + } + + /// + /// Tries to get the compact encoded representation of this alert + /// + /// true if successful + public bool TryEncode(AlertPrototype alert, out byte encoded) + { + return TryEncode(alert.AlertType, out encoded); + } + + /// + /// Tries to get the compact encoded representation of the alert with + /// the indicated id + /// + /// true if successful + public bool TryEncode(AlertType alertType, out byte encoded) + { + if (_typeToIndex.TryGetValue(alertType, out var idx)) + { + encoded = idx; + return true; + } + + encoded = 0; + return false; + } + + /// + /// Tries to get the alert from the encoded representation + /// + /// true if successful + public bool TryDecode(byte encodedAlert, out AlertPrototype alert) + { + if (encodedAlert >= _orderedAlerts.Length) + { + alert = null; + return false; + } + + alert = _orderedAlerts[encodedAlert]; + return true; + } + } +} diff --git a/Content.Shared/Alert/AlertOrderPrototype.cs b/Content.Shared/Alert/AlertOrderPrototype.cs new file mode 100644 index 0000000000..0fd5ee35c3 --- /dev/null +++ b/Content.Shared/Alert/AlertOrderPrototype.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using YamlDotNet.RepresentationModel; + +namespace Content.Shared.Alert +{ + /// + /// Defines the order of alerts so they show up in a consistent order. + /// + [Prototype("alertOrder")] + public class AlertOrderPrototype : IPrototype, IComparer + { + private Dictionary _typeToIdx = new Dictionary(); + private Dictionary _categoryToIdx = new Dictionary(); + + public void LoadFrom(YamlMappingNode mapping) + { + if (!mapping.TryGetNode("order", out YamlSequenceNode orderMapping)) return; + + int i = 0; + foreach (var entryYaml in orderMapping) + { + var orderEntry = (YamlMappingNode) entryYaml; + var serializer = YamlObjectSerializer.NewReader(orderEntry); + if (serializer.TryReadDataField("category", out AlertCategory alertCategory)) + { + _categoryToIdx[alertCategory] = i++; + } + else if (serializer.TryReadDataField("alertType", out AlertType alertType)) + { + _typeToIdx[alertType] = i++; + } + } + } + + private int GetOrderIndex(AlertPrototype alert) + { + if (_typeToIdx.TryGetValue(alert.AlertType, out var idx)) + { + return idx; + } + if (alert.Category != null && + _categoryToIdx.TryGetValue((AlertCategory) alert.Category, out idx)) + { + return idx; + } + + return -1; + } + + public int Compare(AlertPrototype x, AlertPrototype y) + { + if ((x == null) && (y == null)) return 0; + if (x == null) return 1; + if (y == null) return -1; + var idx = GetOrderIndex(x); + var idy = GetOrderIndex(y); + if (idx == -1 && idy == -1) + { + // break ties by type value + return x.AlertType - y.AlertType; + } + + if (idx == -1) return 1; + if (idy == -1) return -1; + var result = idx - idy; + // not strictly necessary (we don't care about ones that go at the same index) + // but it makes the sort stable + if (result == 0) + { + // break ties by type value + return x.AlertType - y.AlertType; + } + + return result; + } + } +} diff --git a/Content.Shared/Alert/AlertPrototype.cs b/Content.Shared/Alert/AlertPrototype.cs new file mode 100644 index 0000000000..431e0b6f3d --- /dev/null +++ b/Content.Shared/Alert/AlertPrototype.cs @@ -0,0 +1,189 @@ +using System; +using Robust.Shared.Log; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; +using YamlDotNet.RepresentationModel; + +namespace Content.Shared.Alert +{ + /// + /// An alert popup with associated icon, tooltip, and other data. + /// + [Prototype("alert")] + public class AlertPrototype : IPrototype + { + /// + /// Type of alert, no 2 alert prototypes should have the same one. + /// + public AlertType AlertType { get; private set; } + + /// + /// Path to the icon (png) to show in alert bar. If severity levels are supported, + /// this should be the path to the icon without the severity number + /// (i.e. hot.png if there is hot1.png and hot2.png). Use + /// to get the correct icon path for a particular severity level. + /// + [ViewVariables] + public string IconPath { get; private set; } + + /// + /// Name to show in tooltip window. Accepts formatting. + /// + public FormattedMessage Name { get; private set; } + + /// + /// Description to show in tooltip window. Accepts formatting. + /// + public FormattedMessage Description { get; private set; } + + /// + /// Category the alert belongs to. Only one alert of a given category + /// can be shown at a time. If one is shown while another is already being shown, + /// it will be replaced. This can be useful for categories of alerts which should naturally + /// replace each other and are mutually exclusive, for example lowpressure / highpressure, + /// hot / cold. If left unspecified, the alert will not replace or be replaced by any other alerts. + /// + public AlertCategory? Category { get; private set; } + + /// + /// Key which is unique w.r.t category semantics (alerts with same category have equal keys, + /// alerts with no category have different keys). + /// + public AlertKey AlertKey { get; private set; } + + /// + /// -1 (no effect) unless MaxSeverity is specified. Defaults to 1. Minimum severity level supported by this state. + /// + public short MinSeverity => MaxSeverity == -1 ? (short) -1 : _minSeverity; + private short _minSeverity; + + /// + /// Maximum severity level supported by this state. -1 (default) indicates + /// no severity levels are supported by the state. + /// + public short MaxSeverity { get; private set; } + + /// + /// Indicates whether this state support severity levels + /// + public bool SupportsSeverity => MaxSeverity != -1; + + public void LoadFrom(YamlMappingNode mapping) + { + var serializer = YamlObjectSerializer.NewReader(mapping); + + serializer.DataField(this, x => x.IconPath, "icon", string.Empty); + serializer.DataField(this, x => x.MaxSeverity, "maxSeverity", (short) -1); + serializer.DataField(ref _minSeverity, "minSeverity", (short) 1); + + serializer.DataReadFunction("name", string.Empty, + s => Name = FormattedMessage.FromMarkup(s)); + serializer.DataReadFunction("description", string.Empty, + s => Description = FormattedMessage.FromMarkup(s)); + + serializer.DataField(this, x => x.AlertType, "alertType", AlertType.Error); + if (AlertType == AlertType.Error) + { + Logger.ErrorS("alert", "missing or invalid alertType for alert with name {0}", Name); + } + + if (serializer.TryReadDataField("category", out AlertCategory alertCategory)) + { + Category = alertCategory; + } + AlertKey = new AlertKey(AlertType, Category); + } + + /// severity level, if supported by this alert + /// the icon path to the texture for the provided severity level + public string GetIconPath(short? severity = null) + { + if (!SupportsSeverity && severity != null) + { + Logger.WarningS("alert", "attempted to get icon path for severity level for alert {0}, but" + + " this alert does not support severity levels", AlertType); + } + if (!SupportsSeverity) return IconPath; + if (severity == null) + { + Logger.WarningS("alert", "attempted to get icon path without severity level for alert {0}," + + " but this alert requires a severity level. Using lowest" + + " valid severity level instead...", AlertType); + severity = MinSeverity; + } + + if (severity < MinSeverity) + { + Logger.WarningS("alert", "attempted to get icon path with severity level {0} for alert {1}," + + " but the minimum severity level for this alert is {2}. Using" + + " lowest valid severity level instead...", severity, AlertType, MinSeverity); + severity = MinSeverity; + } + if (severity > MaxSeverity) + { + Logger.WarningS("alert", "attempted to get icon path with severity level {0} for alert {1}," + + " but the max severity level for this alert is {2}. Using" + + " highest valid severity level instead...", severity, AlertType, MaxSeverity); + severity = MaxSeverity; + } + + // split and add the severity number to the path + var ext = IconPath.LastIndexOf('.'); + return IconPath.Substring(0, ext) + severity + IconPath.Substring(ext, IconPath.Length - ext); + } + } + + /// + /// Key for an alert which is unique (for equality and hashcode purposes) w.r.t category semantics. + /// I.e., entirely defined by the category, if a category was specified, otherwise + /// falls back to the id. + /// + [Serializable, NetSerializable] + public struct AlertKey + { + private readonly AlertType? _alertType; + private readonly AlertCategory? _alertCategory; + + /// NOTE: if the alert has a category you must pass the category for this to work + /// properly as a key. I.e. if the alert has a category and you pass only the ID, and you + /// compare this to another AlertKey that has both the category and the same ID, it will not consider them equal. + public AlertKey(AlertType? alertType, AlertCategory? alertCategory) + { + // if there is a category, ignore the alerttype. + if (alertCategory != null) + { + _alertCategory = alertCategory; + _alertType = null; + } + else + { + _alertCategory = null; + _alertType = alertType; + } + } + + public bool Equals(AlertKey other) + { + return _alertType == other._alertType && _alertCategory == other._alertCategory; + } + + public override bool Equals(object obj) + { + return obj is AlertKey other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(_alertType, _alertCategory); + } + + /// alert category, must not be null + /// An alert key for the provided alert category + public static AlertKey ForCategory(AlertCategory category) + { + return new AlertKey(null, category); + } + } +} diff --git a/Content.Shared/Alert/AlertType.cs b/Content.Shared/Alert/AlertType.cs new file mode 100644 index 0000000000..b4a3866e0c --- /dev/null +++ b/Content.Shared/Alert/AlertType.cs @@ -0,0 +1,52 @@ +namespace Content.Shared.Alert +{ + /// + /// Every category of alert. Corresponds to category field in alert prototypes defined in YML + /// + public enum AlertCategory + { + Pressure, + Temperature, + Buckled, + Health, + Piloting, + Hunger, + Thirst + } + + /// + /// Every kind of alert. Corresponds to alertType field in alert prototypes defined in YML + /// + public enum AlertType + { + Error, + LowPressure, + HighPressure, + Fire, + Cold, + Hot, + Weightless, + Stun, + Handcuffed, + Buckled, + HumanCrit, + HumanDead, + HumanHealth, + PilotingShuttle, + Overfed, + Peckish, + Starving, + Overhydrated, + Thirsty, + Parched, + Pulled, + Pulling, + Debug1, + Debug2, + Debug3, + Debug4, + Debug5, + Debug6 + } + +} diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedAlertsComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedAlertsComponent.cs new file mode 100644 index 0000000000..dff93e22b7 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Mobs/SharedAlertsComponent.cs @@ -0,0 +1,279 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Content.Shared.Alert; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Serialization; +using Robust.Shared.Utility; +using Robust.Shared.ViewVariables; + +namespace Content.Shared.GameObjects.Components.Mobs +{ + /// + /// Handles the icons on the right side of the screen. + /// Should only be used for player-controlled entities. + /// + public abstract class SharedAlertsComponent : Component + { + private static readonly AlertState[] NO_ALERTS = new AlertState[0]; + + [Dependency] + protected readonly AlertManager AlertManager = default!; + + public override string Name => "AlertsUI"; + public override uint? NetID => ContentNetIDs.ALERTS; + + [ViewVariables] + private Dictionary _alerts = new Dictionary(); + + /// true iff an alert of the indicated alert category is currently showing + public bool IsShowingAlertCategory(AlertCategory alertCategory) + { + return IsShowingAlert(AlertKey.ForCategory(alertCategory)); + } + + /// true iff an alert of the indicated id is currently showing + public bool IsShowingAlert(AlertType alertType) + { + if (AlertManager.TryGet(alertType, out var alert)) + { + return IsShowingAlert(alert.AlertKey); + } + Logger.DebugS("alert", "unknown alert type {0}", alertType); + return false; + + } + + /// true iff an alert of the indicated key is currently showing + protected bool IsShowingAlert(AlertKey alertKey) + { + return _alerts.ContainsKey(alertKey); + } + + protected IEnumerable EnumerateAlertStates() + { + return _alerts.Values.Select(alertData => alertData.AlertState); + } + + /// + /// Invokes the alert's specified callback if there is one. + /// Not intended to be used on clientside. + /// + protected void PerformAlertClickCallback(AlertPrototype alert, IEntity owner) + { + if (_alerts.TryGetValue(alert.AlertKey, out var alertStateCallback)) + { + alertStateCallback.OnClickAlert?.Invoke(new ClickAlertEventArgs(owner, alert)); + } + else + { + Logger.DebugS("alert", "player {0} attempted to invoke" + + " alert click for {1} but that alert is not currently" + + " showing", owner.Name, alert.AlertType); + } + } + + /// + /// Creates a new array containing all of the current alert states. + /// + /// + protected AlertState[] CreateAlertStatesArray() + { + if (_alerts.Count == 0) return NO_ALERTS; + var states = new AlertState[_alerts.Count]; + // because I don't trust LINQ + var idx = 0; + foreach (var alertData in _alerts.Values) + { + states[idx++] = alertData.AlertState; + } + + return states; + } + + protected bool TryGetAlertState(AlertKey key, out AlertState alertState) + { + if (_alerts.TryGetValue(key, out var alertData)) + { + alertState = alertData.AlertState; + return true; + } + + alertState = default; + return false; + } + + /// + /// Replace the current active alerts with the specified alerts. Any + /// OnClickAlert callbacks on the active alerts will be erased. + /// + protected void SetAlerts(AlertState[] alerts) + { + var newAlerts = new Dictionary(); + foreach (var alertState in alerts) + { + if (AlertManager.TryDecode(alertState.AlertEncoded, out var alert)) + { + newAlerts[alert.AlertKey] = new ClickableAlertState + { + AlertState = alertState + }; + } + else + { + Logger.ErrorS("alert", "unrecognized encoded alert {0}", alertState.AlertEncoded); + } + } + + _alerts = newAlerts; + } + + /// + /// Shows the alert. If the alert or another alert of the same category is already showing, + /// it will be updated / replaced with the specified values. + /// + /// type of the alert to set + /// callback to invoke when ClickAlertMessage is received by the server + /// after being clicked by client. Has no effect when specified on the clientside. + /// severity, if supported by the alert + /// cooldown start and end, if null there will be no cooldown (and it will + /// be erased if there is currently a cooldown for the alert) + public void ShowAlert(AlertType alertType, short? severity = null, OnClickAlert onClickAlert = null, + ValueTuple? cooldown = null) + { + if (AlertManager.TryGetWithEncoded(alertType, out var alert, out var encoded)) + { + if (_alerts.TryGetValue(alert.AlertKey, out var alertStateCallback) && + alertStateCallback.AlertState.AlertEncoded == encoded && + alertStateCallback.AlertState.Severity == severity && alertStateCallback.AlertState.Cooldown == cooldown) + { + alertStateCallback.OnClickAlert = onClickAlert; + return; + } + + _alerts[alert.AlertKey] = new ClickableAlertState + { + AlertState = new AlertState + {Cooldown = cooldown, AlertEncoded = encoded, Severity = severity}, + OnClickAlert = onClickAlert + }; + + Dirty(); + + } + else + { + Logger.ErrorS("alert", "Unable to show alert {0}, please ensure this alertType has" + + " a corresponding YML alert prototype", + alertType); + } + } + + /// + /// Clear the alert with the given category, if one is currently showing. + /// + public void ClearAlertCategory(AlertCategory category) + { + var key = AlertKey.ForCategory(category); + if (!_alerts.Remove(key)) + { + return; + } + + AfterClearAlert(); + + Dirty(); + } + + /// + /// Clear the alert of the given type if it is currently showing. + /// + public void ClearAlert(AlertType alertType) + { + if (AlertManager.TryGet(alertType, out var alert)) + { + if (!_alerts.Remove(alert.AlertKey)) + { + return; + } + + AfterClearAlert(); + + Dirty(); + } + else + { + Logger.ErrorS("alert", "unable to clear alert, unknown alertType {0}", alertType); + } + + } + + /// + /// Invoked after clearing an alert prior to dirtying the control + /// + protected virtual void AfterClearAlert() { } + } + + [Serializable, NetSerializable] + public class AlertsComponentState : ComponentState + { + public AlertState[] Alerts; + + public AlertsComponentState(AlertState[] alerts) : base(ContentNetIDs.ALERTS) + { + Alerts = alerts; + } + } + + /// + /// A message that calls the click interaction on a alert + /// + [Serializable, NetSerializable] + public class ClickAlertMessage : ComponentMessage + { + public readonly byte EncodedAlert; + + public ClickAlertMessage(byte encodedAlert) + { + Directed = true; + EncodedAlert = encodedAlert; + } + } + + [Serializable, NetSerializable] + public struct AlertState + { + public byte AlertEncoded; + public short? Severity; + public ValueTuple? Cooldown; + } + + public struct ClickableAlertState + { + public AlertState AlertState; + public OnClickAlert OnClickAlert; + } + + public delegate void OnClickAlert(ClickAlertEventArgs args); + + public class ClickAlertEventArgs : EventArgs + { + /// + /// Player clicking the alert + /// + public readonly IEntity Player; + /// + /// Alert that was clicked + /// + public readonly AlertPrototype Alert; + + public ClickAlertEventArgs(IEntity player, AlertPrototype alert) + { + Player = player; + Alert = alert; + } + } +} diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs deleted file mode 100644 index 2c1cffeadd..0000000000 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStatusEffectsComponent.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization; - -namespace Content.Shared.GameObjects.Components.Mobs -{ - /// - /// Handles the icons on the right side of the screen. - /// Should only be used for player-controlled entities - /// - public abstract class SharedStatusEffectsComponent : Component - { - public override string Name => "StatusEffectsUI"; - public override uint? NetID => ContentNetIDs.STATUSEFFECTS; - - public abstract IReadOnlyDictionary Statuses { get; } - - public abstract void ChangeStatusEffectIcon(StatusEffect effect, string icon); - - public abstract void ChangeStatusEffect(StatusEffect effect, string icon, ValueTuple? cooldown); - - public abstract void RemoveStatusEffect(StatusEffect effect); - } - - [Serializable, NetSerializable] - public class StatusEffectComponentState : ComponentState - { - public Dictionary StatusEffects; - - public StatusEffectComponentState(Dictionary statusEffects) : base(ContentNetIDs.STATUSEFFECTS) - { - StatusEffects = statusEffects; - } - } - - /// - /// A message that calls the click interaction on a status effect - /// - [Serializable, NetSerializable] - public class ClickStatusMessage : ComponentMessage - { - public readonly StatusEffect Effect; - - public ClickStatusMessage(StatusEffect effect) - { - Directed = true; - Effect = effect; - } - } - - [Serializable, NetSerializable] - public struct StatusEffectStatus - { - public string Icon; - public ValueTuple? Cooldown; - } - - // Each status effect is assumed to be unique - public enum StatusEffect - { - Health, - Hunger, - Thirst, - Pressure, - Fire, - Temperature, - Stun, - Cuffed, - Buckled, - Piloting, - Pulling, - Pulled, - Weightless - } -} diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs index a347dbbccf..c168a9056e 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs @@ -1,5 +1,6 @@ using System; using System.Threading; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Interfaces.GameObjects.Components; @@ -41,7 +42,7 @@ namespace Content.Shared.GameObjects.Components.Mobs protected float KnockdownTimer; protected float SlowdownTimer; - private string _stunTexture; + private string _stunAlertId; protected CancellationTokenSource StatusRemoveCancellation = new CancellationTokenSource(); @@ -117,7 +118,7 @@ namespace Content.Shared.GameObjects.Components.Mobs StunnedTimer = seconds; LastStun = _gameTiming.CurTime; - SetStatusEffect(); + SetAlert(); OnStun(); Dirty(); @@ -144,7 +145,7 @@ namespace Content.Shared.GameObjects.Components.Mobs KnockdownTimer = seconds; LastStun = _gameTiming.CurTime; - SetStatusEffect(); + SetAlert(); OnKnockdown(); Dirty(); @@ -186,18 +187,18 @@ namespace Content.Shared.GameObjects.Components.Mobs if (Owner.TryGetComponent(out MovementSpeedModifierComponent movement)) movement.RefreshMovementSpeedModifiers(); - SetStatusEffect(); + SetAlert(); Dirty(); } - private void SetStatusEffect() + private void SetAlert() { - if (!Owner.TryGetComponent(out SharedStatusEffectsComponent status)) + if (!Owner.TryGetComponent(out SharedAlertsComponent status)) { return; } - status.ChangeStatusEffect(StatusEffect.Stun, _stunTexture, + status.ShowAlert(AlertType.Stun, cooldown: (StunStart == null || StunEnd == null) ? default : (StunStart.Value, StunEnd.Value)); StatusRemoveCancellation.Cancel(); StatusRemoveCancellation = new CancellationTokenSource(); @@ -212,8 +213,8 @@ namespace Content.Shared.GameObjects.Components.Mobs serializer.DataField(ref _slowdownCap, "slowdownCap", 20f); serializer.DataField(ref _helpInterval, "helpInterval", 1f); serializer.DataField(ref _helpKnockdownRemove, "helpKnockdownRemove", 1f); - serializer.DataField(ref _stunTexture, "stunTexture", - "/Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png"); + serializer.DataField(ref _stunAlertId, "stunAlertId", + "stun"); } protected virtual void OnInteractHand() { } @@ -230,7 +231,7 @@ namespace Content.Shared.GameObjects.Components.Mobs KnockdownTimer -= _helpKnockdownRemove; - SetStatusEffect(); + SetAlert(); Dirty(); return true; diff --git a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs index 1a76e085e3..114a7428e9 100644 --- a/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs +++ b/Content.Shared/GameObjects/Components/Pulling/SharedPullableComponent.cs @@ -1,12 +1,15 @@ #nullable enable using System; +using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Mobs; +using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Physics; using Content.Shared.Physics.Pull; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.ComponentDependencies; using Robust.Shared.GameObjects.Components; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Map; using Robust.Shared.Physics; @@ -204,29 +207,36 @@ namespace Content.Shared.GameObjects.Components.Pulling private void AddPullingStatuses(IEntity puller) { - if (Owner.TryGetComponent(out SharedStatusEffectsComponent? pulledStatus)) + if (Owner.TryGetComponent(out SharedAlertsComponent? pulledStatus)) { - pulledStatus.ChangeStatusEffectIcon(StatusEffect.Pulled, - "/Textures/Interface/StatusEffects/Pull/pulled.png"); + pulledStatus.ShowAlert(AlertType.Pulled); } - if (puller.TryGetComponent(out SharedStatusEffectsComponent? ownerStatus)) + if (puller.TryGetComponent(out SharedAlertsComponent? ownerStatus)) { - ownerStatus.ChangeStatusEffectIcon(StatusEffect.Pulling, - "/Textures/Interface/StatusEffects/Pull/pulling.png"); + ownerStatus.ShowAlert(AlertType.Pulling, onClickAlert: OnClickAlert); } } + private void OnClickAlert(ClickAlertEventArgs args) + { + EntitySystem + .Get() + .GetPulled(args.Player)? + .GetComponentOrNull()? + .TryStopPull(); + } + private void RemovePullingStatuses(IEntity puller) { - if (Owner.TryGetComponent(out SharedStatusEffectsComponent? pulledStatus)) + if (Owner.TryGetComponent(out SharedAlertsComponent? pulledStatus)) { - pulledStatus.RemoveStatusEffect(StatusEffect.Pulled); + pulledStatus.ClearAlert(AlertType.Pulled); } - if (puller.TryGetComponent(out SharedStatusEffectsComponent? ownerStatus)) + if (puller.TryGetComponent(out SharedAlertsComponent? ownerStatus)) { - ownerStatus.RemoveStatusEffect(StatusEffect.Pulling); + ownerStatus.ClearAlert(AlertType.Pulling); } } diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index 8769dd85d4..a2d20277d0 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -29,7 +29,7 @@ public const uint RESEARCH_CONSOLE = 1023; public const uint WIRES = 1024; public const uint COMBATMODE = 1025; - public const uint STATUSEFFECTS = 1026; + public const uint ALERTS = 1026; public const uint OVERLAYEFFECTS = 1027; public const uint STOMACH = 1028; public const uint ITEMCOOLDOWN = 1029; diff --git a/Content.Tests/Server/GameObjects/Components/Mobs/ServerAlertsComponentTests.cs b/Content.Tests/Server/GameObjects/Components/Mobs/ServerAlertsComponentTests.cs new file mode 100644 index 0000000000..48062b1e62 --- /dev/null +++ b/Content.Tests/Server/GameObjects/Components/Mobs/ServerAlertsComponentTests.cs @@ -0,0 +1,71 @@ +using System.IO; +using System.Linq; +using Content.Server.GameObjects.Components.Mobs; +using Content.Shared.Alert; +using Content.Shared.GameObjects.Components.Mobs; +using Content.Shared.Utility; +using NUnit.Framework; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.Tests.Server.GameObjects.Components.Mobs +{ + [TestFixture] + [TestOf(typeof(ServerAlertsComponent))] + public class ServerAlertsComponentTests : ContentUnitTest + { + const string PROTOTYPES = @" +- type: alert + alertType: LowPressure + category: Pressure + icon: /Textures/Interface/Alerts/Pressure/lowpressure.png + +- type: alert + alertType: HighPressure + category: Pressure + icon: /Textures/Interface/Alerts/Pressure/highpressure.png +"; + + [Test] + public void ShowAlerts() + { + // this is kind of unnecessary because there's integration test coverage of Alert components + // but wanted to keep it anyway to see what's possible w.r.t. testing components + // in a unit test + + var prototypeManager = IoCManager.Resolve(); + prototypeManager.RegisterType(typeof(AlertPrototype)); + var factory = IoCManager.Resolve(); + factory.Register(); + prototypeManager.LoadFromStream(new StringReader(PROTOTYPES)); + prototypeManager.Resync(); + var alertManager = IoCManager.Resolve(); + alertManager.Initialize(); + + + var alertsComponent = new ServerAlertsComponent(); + alertsComponent = IoCManager.InjectDependencies(alertsComponent); + + Assert.That(alertManager.TryGetWithEncoded(AlertType.LowPressure, out var lowpressure, out var lpencoded)); + Assert.That(alertManager.TryGetWithEncoded(AlertType.HighPressure, out var highpressure, out var hpencoded)); + + alertsComponent.ShowAlert(AlertType.LowPressure); + var alertState = alertsComponent.GetComponentState() as AlertsComponentState; + Assert.NotNull(alertState); + Assert.That(alertState.Alerts.Length, Is.EqualTo(1)); + Assert.That(alertState.Alerts[0], Is.EqualTo(new AlertState{AlertEncoded = lpencoded})); + + alertsComponent.ShowAlert(AlertType.HighPressure); + alertState = alertsComponent.GetComponentState() as AlertsComponentState; + Assert.That(alertState.Alerts.Length, Is.EqualTo(1)); + Assert.That(alertState.Alerts[0], Is.EqualTo(new AlertState{AlertEncoded = hpencoded})); + + alertsComponent.ClearAlertCategory(AlertCategory.Pressure); + alertState = alertsComponent.GetComponentState() as AlertsComponentState; + Assert.That(alertState.Alerts.Length, Is.EqualTo(0)); + } + } +} diff --git a/Content.Tests/Shared/Alert/AlertManagerTests.cs b/Content.Tests/Shared/Alert/AlertManagerTests.cs new file mode 100644 index 0000000000..7601b04eb9 --- /dev/null +++ b/Content.Tests/Shared/Alert/AlertManagerTests.cs @@ -0,0 +1,63 @@ +using System.IO; +using Content.Shared.Alert; +using NUnit.Framework; +using Robust.Shared.Interfaces.Log; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; +using Robust.UnitTesting; +using YamlDotNet.RepresentationModel; + +namespace Content.Tests.Shared.Alert +{ + [TestFixture, TestOf(typeof(AlertManager))] + public class AlertManagerTests : RobustUnitTest + { + const string PROTOTYPES = @" +- type: alert + alertType: LowPressure + icon: /Textures/Interface/Alerts/Pressure/lowpressure.png + +- type: alert + alertType: HighPressure + icon: /Textures/Interface/Alerts/Pressure/highpressure.png +"; + + [Test] + public void TestAlertManager() + { + var prototypeManager = IoCManager.Resolve(); + prototypeManager.RegisterType(typeof(AlertPrototype)); + prototypeManager.LoadFromStream(new StringReader(PROTOTYPES)); + IoCManager.RegisterInstance(new AlertManager()); + var alertManager = IoCManager.Resolve(); + alertManager.Initialize(); + + Assert.That(alertManager.TryGet(AlertType.LowPressure, out var lowPressure)); + Assert.That(lowPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/lowpressure.png")); + Assert.That(alertManager.TryGet(AlertType.HighPressure, out var highPressure)); + Assert.That(highPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/highpressure.png")); + + Assert.That(alertManager.TryGetWithEncoded(AlertType.LowPressure, out lowPressure, out var encodedLowPressure)); + Assert.That(lowPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/lowpressure.png")); + Assert.That(alertManager.TryGetWithEncoded(AlertType.HighPressure, out highPressure, out var encodedHighPressure)); + Assert.That(highPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/highpressure.png")); + + Assert.That(alertManager.TryEncode(lowPressure, out var encodedLowPressure2)); + Assert.That(encodedLowPressure2, Is.EqualTo(encodedLowPressure)); + Assert.That(alertManager.TryEncode(highPressure, out var encodedHighPressure2)); + Assert.That(encodedHighPressure2, Is.EqualTo(encodedHighPressure)); + Assert.That(encodedLowPressure, Is.Not.EqualTo(encodedHighPressure)); + + Assert.That(alertManager.TryDecode(encodedLowPressure, out var decodedLowPressure)); + Assert.That(decodedLowPressure, Is.EqualTo(lowPressure)); + Assert.That(alertManager.TryDecode(encodedHighPressure, out var decodedHighPressure)); + Assert.That(decodedHighPressure, Is.EqualTo(highPressure)); + + Assert.False(alertManager.TryEncode(AlertType.Debug1, out _)); + Assert.False(alertManager.TryGetWithEncoded(AlertType.Debug1, out _, out _)); + + } + } +} diff --git a/Content.Tests/Shared/Alert/AlertOrderPrototypeTests.cs b/Content.Tests/Shared/Alert/AlertOrderPrototypeTests.cs new file mode 100644 index 0000000000..f67914ef6b --- /dev/null +++ b/Content.Tests/Shared/Alert/AlertOrderPrototypeTests.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Content.Shared.Alert; +using NUnit.Framework; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; +using Robust.UnitTesting; + +namespace Content.Tests.Shared.Alert +{ + [TestFixture, TestOf(typeof(AlertOrderPrototype))] + public class AlertOrderPrototypeTests : RobustUnitTest + { + const string PROTOTYPES = @" +- type: alertOrder + order: + - alertType: Handcuffed + - category: Pressure + - category: Hunger + - alertType: Hot + - alertType: Stun + - alertType: LowPressure + - category: Temperature + +- type: alert + category: Pressure + alertType: LowPressure + +- type: alert + category: Hunger + alertType: Overfed + +- type: alert + category: Pressure + alertType: HighPressure + +- type: alert + category: Hunger + alertType: Peckish + +- type: alert + alertType: Stun + +- type: alert + alertType: Handcuffed + +- type: alert + category: Temperature + alertType: Hot + +- type: alert + category: Temperature + alertType: Cold + +- type: alert + alertType: Weightless + +- type: alert + alertType: PilotingShuttle +"; + + [Test] + public void TestAlertOrderPrototype() + { + var prototypeManager = IoCManager.Resolve(); + prototypeManager.RegisterType(typeof(AlertPrototype)); + prototypeManager.RegisterType(typeof(AlertOrderPrototype)); + prototypeManager.LoadFromStream(new StringReader(PROTOTYPES)); + + var alertOrder = prototypeManager.EnumeratePrototypes().FirstOrDefault(); + + var alerts = prototypeManager.EnumeratePrototypes(); + + // ensure they sort according to our expected criteria + var expectedOrder = new List(); + expectedOrder.Add(AlertType.Handcuffed); + expectedOrder.Add(AlertType.HighPressure); + // stuff with only category + same category ordered by enum value + expectedOrder.Add(AlertType.Overfed); + expectedOrder.Add(AlertType.Peckish); + expectedOrder.Add(AlertType.Hot); + expectedOrder.Add(AlertType.Stun); + expectedOrder.Add(AlertType.LowPressure); + expectedOrder.Add(AlertType.Cold); + // stuff at end of list ordered by enum value + expectedOrder.Add(AlertType.Weightless); + expectedOrder.Add(AlertType.PilotingShuttle); + + var actual = alerts.ToList(); + actual.Sort(alertOrder); + + Assert.That(actual.Select(a => a.AlertType).ToList(), Is.EqualTo(expectedOrder)); + } + } +} diff --git a/Content.Tests/Shared/Alert/AlertPrototypeTests.cs b/Content.Tests/Shared/Alert/AlertPrototypeTests.cs new file mode 100644 index 0000000000..d4104a568f --- /dev/null +++ b/Content.Tests/Shared/Alert/AlertPrototypeTests.cs @@ -0,0 +1,62 @@ +using System.IO; +using Content.Shared.Alert; +using NUnit.Framework; +using Robust.Shared.Interfaces.Log; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Utility; +using Robust.UnitTesting; +using YamlDotNet.RepresentationModel; + +namespace Content.Tests.Shared.Alert +{ + [TestFixture, TestOf(typeof(AlertPrototype))] + public class AlertPrototypeTests : RobustUnitTest + { + private const string PROTOTYPE = @"- type: alert + alertType: HumanHealth + category: Health + icon: /Textures/Interface/Alerts/Human/human.rsi/human.png + name: Health + description: ""[color=green]Green[/color] good. [color=red]Red[/color] bad."" + minSeverity: 0 + maxSeverity: 6"; + + + [Test] + public void TestAlertKey() + { + Assert.That(new AlertKey(AlertType.HumanHealth, null), Is.Not.EqualTo(AlertKey.ForCategory(AlertCategory.Health))); + Assert.That((new AlertKey(null, AlertCategory.Health)), Is.EqualTo(AlertKey.ForCategory(AlertCategory.Health))); + Assert.That((new AlertKey(AlertType.Buckled, AlertCategory.Health)), Is.EqualTo(AlertKey.ForCategory(AlertCategory.Health))); + } + + + [TestCase(0, "/Textures/Interface/Alerts/Human/human.rsi/human0.png")] + [TestCase(null, "/Textures/Interface/Alerts/Human/human.rsi/human0.png")] + [TestCase(1, "/Textures/Interface/Alerts/Human/human.rsi/human1.png")] + [TestCase(6, "/Textures/Interface/Alerts/Human/human.rsi/human6.png")] + [TestCase(7, "/Textures/Interface/Alerts/Human/human.rsi/human6.png")] + public void GetsIconPath(short? severity, string expected) + { + + var alert = GetTestPrototype(); + Assert.That(alert.GetIconPath(severity), Is.EqualTo(expected)); + } + + private AlertPrototype GetTestPrototype() + { + using (TextReader stream = new StringReader(PROTOTYPE)) + { + var yamlStream = new YamlStream(); + yamlStream.Load(stream); + var document = yamlStream.Documents[0]; + var rootNode = (YamlSequenceNode) document.RootNode; + var proto = (YamlMappingNode) rootNode[0]; + var newReagent = new AlertPrototype(); + newReagent.LoadFrom(proto); + return newReagent; + } + } + } +} diff --git a/Resources/Groups/groups.yml b/Resources/Groups/groups.yml index b9f90c5639..640345c72d 100644 --- a/Resources/Groups/groups.yml +++ b/Resources/Groups/groups.yml @@ -232,6 +232,8 @@ - attachtogrid - attachtograndparent - inrangeunoccluded + - showalert + - clearalert - hungry CanViewVar: true CanAdminPlace: true diff --git a/Resources/Prototypes/Alerts/alerts.yml b/Resources/Prototypes/Alerts/alerts.yml new file mode 100644 index 0000000000..52e0d5a655 --- /dev/null +++ b/Resources/Prototypes/Alerts/alerts.yml @@ -0,0 +1,205 @@ +- type: alertOrder + # Defines ordering in alert tab, higher up = higher in tab. + # List below can contain alert type or category, if both are present the id will take precedence. + # If item is not in list it will go at the bottom (ties broken by alert type enum value) + order: + - category: Health + - alertType: Fire + - alertType: Handcuffed + - category: Buckled + - alertType: Pulling + - category: Piloting + - alertType: Stun + - category: Pressure + - category: Temperature + - category: Hunger + - category: Thirst + + + +- type: alert + alertType: LowPressure + category: Pressure + icon: /Textures/Interface/Alerts/Pressure/lowpressure.png + maxSeverity: 2 + name: "[color=red]Low Pressure[/color]" + description: "The air around you is [color=red]hazardously thin[/color]. A [color=green]space suit[/color] would protect you." + +- type: alert + alertType: HighPressure + category: Pressure + icon: /Textures/Interface/Alerts/Pressure/highpressure.png + maxSeverity: 2 + name: "[color=red]High Pressure[/color]" + description: "The air around you is [color=red]hazardously thick[/color]. A [color=green]fire suit[/color] would protect you." + +- type: alert + alertType: Fire + icon: /Textures/Interface/Alerts/Fire/fire.png + name: "[color=red]On Fire[/color]" + description: "You're [color=red]on fire[/color]. Click the alert to stop, drop and roll to put the fire out or move to a vacuum area." + +- type: alert + alertType: Cold + category: Temperature + icon: /Textures/Interface/Alerts/Temperature/cold.png + maxSeverity: 3 + name: "[color=cyan]Too Cold[/color]" + description: "You're [color=cyan]freezing cold![/color] Get somewhere warmer and take off any insulating clothing like a space suit." + +- type: alert + alertType: Hot + category: Temperature + icon: /Textures/Interface/Alerts/Temperature/hot.png + maxSeverity: 3 + name: "[color=red]Too Hot[/color]" + description: "It's [color=red]too hot![/color] Flee to space or at least away from the flames. Standing on weeds will heal you." + +- type: alert + alertType: Weightless + icon: /Textures/Interface/Alerts/Weightless/weightless.png + name: Weightless + description: >- + Gravity has ceased affecting you, and you're floating around aimlessly. You'll need something large and heavy, like a + wall or lattice, to push yourself off if you want to move. A jetpack would enable free range of motion. A pair of + magboots would let you walk around normally on the floor. Barring those, you can throw things, use a fire extinguisher, + or shoot a gun to move around via Newton's 3rd Law of Motion. + +- type: alert + alertType: Stun + icon: /Textures/Objects/Weapons/Melee/stunbaton.rsi/stunbaton_off.png + name: "[color=yellow]Stunned[/color]" + description: "You're [color=yellow]stunned[/color]! Wait for it to wear off." + +- type: alert + alertType: Handcuffed + icon: /Textures/Interface/Alerts/Handcuffed/Handcuffed.png + name: "[color=yellow]Handcuffed[/color]" + description: "You're [color=yellow]handcuffed[/color] and can't act. If anyone drags you, you won't be able to move.." + +- type: alert + alertType: Buckled + category: Buckled + icon: /Textures/Interface/Alerts/Buckle/buckled.png + name: "[color=yellow]Buckled[/color]" + description: "You've been [color=yellow]buckled[/color] to something. Click the alert to unbuckle unless you're [color=yellow]handcuffed.[/color]" + +- type: alert + alertType: HumanCrit + category: Health + icon: /Textures/Interface/Alerts/Human/humancrit-0.png + name: "[color=red]Critical Condition[/color]" + description: "You're severely injured and unconscious." + +- type: alert + alertType: HumanDead + category: Health + icon: /Textures/Interface/Alerts/Human/humandead.png + name: Dead + description: You're dead. + +- type: alert + alertType: HumanHealth + category: Health + icon: /Textures/Interface/Alerts/Human/human.png + name: Health + description: "[color=green]Green[/color] good. [color=red]Red[/color] bad." + minSeverity: 0 + maxSeverity: 6 + +- type: alert + alertType: PilotingShuttle + category: Piloting + icon: /Textures/Interface/Alerts/Buckle/buckled.png + name: Piloting Shuttle + description: You are piloting a shuttle. Click the alert to stop. + +- type: alert + alertType: Overfed + category: Hunger + icon: /Textures/Interface/Alerts/Hunger/Overfed.png + name: "[color=yellow]Overfed[/color]" + description: You ate too much food, lardass. Run around the station and lose some weight. + +- type: alert + alertType: Peckish + category: Hunger + icon: /Textures/Interface/Alerts/Hunger/Peckish.png + name: "[color=yellow]Peckish[/color]" + description: Some food would be good right about now. + +- type: alert + alertType: Starving + category: Hunger + icon: /Textures/Interface/Alerts/Hunger/Starving.png + name: "[color=red]Starving[/color]" + description: You're severely malnourished. The hunger pains make moving around a chore. + +- type: alert + alertType: Overhydrated + category: Thirst + icon: /Textures/Interface/Alerts/Thirst/OverHydrated.png + name: "[color=yellow]Overhydrated[/color]" + description: You drank too much. + +- type: alert + alertType: Thirsty + category: Thirst + icon: /Textures/Interface/Alerts/Thirst/Thirsty.png + name: "[color=yellow]Thirsty[/color]" + description: Something to drink would be good right about now. + +- type: alert + alertType: Parched + category: Thirst + icon: /Textures/Interface/Alerts/Thirst/Parched.png + name: "[color=red]Parched[/color]" + description: You're severely thirsty. The thirst makes moving around a chore. + +- type: alert + alertType: Pulled + icon: /Textures/Interface/Alerts/Pull/pulled.png + name: Pulled + description: You're being pulled. Move to break free. + +- type: alert + alertType: Pulling + icon: /Textures/Interface/Alerts/Pull/pulling.png + name: Pulling + description: You're pulling something. Click the alert to stop. + +- type: alert + alertType: Debug1 + icon: /Textures/Interface/Alerts/Human/human1.png + name: Debug + description: Debug + +- type: alert + alertType: Debug2 + icon: /Textures/Interface/Alerts/Human/human2.png + name: Debug + description: Debug + +- type: alert + alertType: Debug3 + icon: /Textures/Interface/Alerts/Human/human3.png + name: Debug + description: Debug + +- type: alert + alertType: Debug4 + icon: /Textures/Interface/Alerts/Human/human4.png + name: Debug + description: Debug + +- type: alert + alertType: Debug5 + icon: /Textures/Interface/Alerts/Human/human5.png + name: Debug + description: Debug + +- type: alert + alertType: Debug6 + icon: /Textures/Interface/Alerts/Human/human6.png + name: Debug + description: Debug diff --git a/Resources/Prototypes/Entities/Mobs/Player/human.yml b/Resources/Prototypes/Entities/Mobs/Player/human.yml index 7a5ddd085c..f6a5733558 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/human.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/human.yml @@ -10,7 +10,7 @@ show_examine_info: true - type: Input context: "human" - - type: StatusEffectsUI + - type: AlertsUI - type: OverlayEffectsUI - type: Eye zoom: 0.5, 0.5 diff --git a/Resources/Textures/Interface/StatusEffects/Buckle/buckled.png b/Resources/Textures/Interface/Alerts/Buckle/buckled.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Buckle/buckled.png rename to Resources/Textures/Interface/Alerts/Buckle/buckled.png diff --git a/Resources/Textures/Interface/StatusEffects/Fire/fire.png b/Resources/Textures/Interface/Alerts/Fire/fire.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Fire/fire.png rename to Resources/Textures/Interface/Alerts/Fire/fire.png diff --git a/Resources/Textures/Interface/StatusEffects/Handcuffed/Handcuffed.png b/Resources/Textures/Interface/Alerts/Handcuffed/Handcuffed.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Handcuffed/Handcuffed.png rename to Resources/Textures/Interface/Alerts/Handcuffed/Handcuffed.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human0.png b/Resources/Textures/Interface/Alerts/Human/human0.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human0.png rename to Resources/Textures/Interface/Alerts/Human/human0.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human1.png b/Resources/Textures/Interface/Alerts/Human/human1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human1.png rename to Resources/Textures/Interface/Alerts/Human/human1.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human2.png b/Resources/Textures/Interface/Alerts/Human/human2.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human2.png rename to Resources/Textures/Interface/Alerts/Human/human2.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human3.png b/Resources/Textures/Interface/Alerts/Human/human3.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human3.png rename to Resources/Textures/Interface/Alerts/Human/human3.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human4.png b/Resources/Textures/Interface/Alerts/Human/human4.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human4.png rename to Resources/Textures/Interface/Alerts/Human/human4.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human5.png b/Resources/Textures/Interface/Alerts/Human/human5.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human5.png rename to Resources/Textures/Interface/Alerts/Human/human5.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human6.png b/Resources/Textures/Interface/Alerts/Human/human6.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human6.png rename to Resources/Textures/Interface/Alerts/Human/human6.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/human7.png b/Resources/Textures/Interface/Alerts/Human/human7.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/human7.png rename to Resources/Textures/Interface/Alerts/Human/human7.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/humancrit-0.png b/Resources/Textures/Interface/Alerts/Human/humancrit-0.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/humancrit-0.png rename to Resources/Textures/Interface/Alerts/Human/humancrit-0.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/humancrit-1.png b/Resources/Textures/Interface/Alerts/Human/humancrit-1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/humancrit-1.png rename to Resources/Textures/Interface/Alerts/Human/humancrit-1.png diff --git a/Resources/Textures/Interface/StatusEffects/Human/humandead.png b/Resources/Textures/Interface/Alerts/Human/humandead.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Human/humandead.png rename to Resources/Textures/Interface/Alerts/Human/humandead.png diff --git a/Resources/Textures/Interface/StatusEffects/Hunger/Overfed.png b/Resources/Textures/Interface/Alerts/Hunger/Overfed.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Hunger/Overfed.png rename to Resources/Textures/Interface/Alerts/Hunger/Overfed.png diff --git a/Resources/Textures/Interface/StatusEffects/Hunger/Peckish.png b/Resources/Textures/Interface/Alerts/Hunger/Peckish.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Hunger/Peckish.png rename to Resources/Textures/Interface/Alerts/Hunger/Peckish.png diff --git a/Resources/Textures/Interface/StatusEffects/Hunger/Starving.png b/Resources/Textures/Interface/Alerts/Hunger/Starving.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Hunger/Starving.png rename to Resources/Textures/Interface/Alerts/Hunger/Starving.png diff --git a/Resources/Textures/Interface/StatusEffects/Pressure/highpressure1.png b/Resources/Textures/Interface/Alerts/Pressure/highpressure1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pressure/highpressure1.png rename to Resources/Textures/Interface/Alerts/Pressure/highpressure1.png diff --git a/Resources/Textures/Interface/StatusEffects/Pressure/highpressure2.png b/Resources/Textures/Interface/Alerts/Pressure/highpressure2.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pressure/highpressure2.png rename to Resources/Textures/Interface/Alerts/Pressure/highpressure2.png diff --git a/Resources/Textures/Interface/StatusEffects/Pressure/lowpressure1.png b/Resources/Textures/Interface/Alerts/Pressure/lowpressure1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pressure/lowpressure1.png rename to Resources/Textures/Interface/Alerts/Pressure/lowpressure1.png diff --git a/Resources/Textures/Interface/StatusEffects/Pressure/lowpressure2.png b/Resources/Textures/Interface/Alerts/Pressure/lowpressure2.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pressure/lowpressure2.png rename to Resources/Textures/Interface/Alerts/Pressure/lowpressure2.png diff --git a/Resources/Textures/Interface/StatusEffects/Pressure/meta.json b/Resources/Textures/Interface/Alerts/Pressure/meta.json similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pressure/meta.json rename to Resources/Textures/Interface/Alerts/Pressure/meta.json diff --git a/Resources/Textures/Interface/StatusEffects/Pull/pulled.png b/Resources/Textures/Interface/Alerts/Pull/pulled.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pull/pulled.png rename to Resources/Textures/Interface/Alerts/Pull/pulled.png diff --git a/Resources/Textures/Interface/StatusEffects/Pull/pulling.png b/Resources/Textures/Interface/Alerts/Pull/pulling.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Pull/pulling.png rename to Resources/Textures/Interface/Alerts/Pull/pulling.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/cold1.png b/Resources/Textures/Interface/Alerts/Temperature/cold1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/cold1.png rename to Resources/Textures/Interface/Alerts/Temperature/cold1.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/cold2.png b/Resources/Textures/Interface/Alerts/Temperature/cold2.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/cold2.png rename to Resources/Textures/Interface/Alerts/Temperature/cold2.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/cold3.png b/Resources/Textures/Interface/Alerts/Temperature/cold3.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/cold3.png rename to Resources/Textures/Interface/Alerts/Temperature/cold3.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/hot1.png b/Resources/Textures/Interface/Alerts/Temperature/hot1.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/hot1.png rename to Resources/Textures/Interface/Alerts/Temperature/hot1.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/hot2.png b/Resources/Textures/Interface/Alerts/Temperature/hot2.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/hot2.png rename to Resources/Textures/Interface/Alerts/Temperature/hot2.png diff --git a/Resources/Textures/Interface/StatusEffects/Temperature/hot3.png b/Resources/Textures/Interface/Alerts/Temperature/hot3.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Temperature/hot3.png rename to Resources/Textures/Interface/Alerts/Temperature/hot3.png diff --git a/Resources/Textures/Interface/StatusEffects/Thirst/OverHydrated.png b/Resources/Textures/Interface/Alerts/Thirst/OverHydrated.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Thirst/OverHydrated.png rename to Resources/Textures/Interface/Alerts/Thirst/OverHydrated.png diff --git a/Resources/Textures/Interface/StatusEffects/Thirst/Parched.png b/Resources/Textures/Interface/Alerts/Thirst/Parched.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Thirst/Parched.png rename to Resources/Textures/Interface/Alerts/Thirst/Parched.png diff --git a/Resources/Textures/Interface/StatusEffects/Thirst/Thirsty.png b/Resources/Textures/Interface/Alerts/Thirst/Thirsty.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Thirst/Thirsty.png rename to Resources/Textures/Interface/Alerts/Thirst/Thirsty.png diff --git a/Resources/Textures/Interface/StatusEffects/Weightless/weightless.png b/Resources/Textures/Interface/Alerts/Weightless/weightless.png similarity index 100% rename from Resources/Textures/Interface/StatusEffects/Weightless/weightless.png rename to Resources/Textures/Interface/Alerts/Weightless/weightless.png diff --git a/Resources/Textures/Interface/Nano/tooltip.png b/Resources/Textures/Interface/Nano/tooltip.png index eadfc72e3706f5728295421c251b941938b3b48a..bd6cefaa24c1fc62b5b48df3f2af06b5a876238b 100644 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=&H|6fVg?31We{epSZZGe6l5>) z^mS!_!p+1et-$ZpeHtiK;_2cT!Xe9;$uR9dBaqKvZt3?QM1#P|6kp&>a3=B*# m#*;@EVN8UejGR7P5UZJ+cJmxvus!i0NR_9npUXO@geCyc86{T$ delta 83 zcmcc0*vdG;(#PD>#W95Adh(zD|LvP+%=l8zrcv?rm8SCI6)UdP^YQVq3HgTe~DWM4fq@y1k diff --git a/Resources/Textures/Interface/Nano/transparent_window_background_bordered.png b/Resources/Textures/Interface/Nano/transparent_window_background_bordered.png new file mode 100644 index 0000000000000000000000000000000000000000..987ad4cba61570fa3677a329b451e88e2a9f4554 GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=&H|6fVg?31We{epSZZGe6l5>) z^mS!_!p*^AAYe8(r4cBk@9E+g!f`!0B_ScfVEdQf=NVYl`}31hT*Mj})g&IjeZ8CA lfTh)Ss%%1zTTU7i!=sP9N5fS4CIGcEc)I$ztaD0e0szuoCD#A| literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Nano/window_background_bordered.png b/Resources/Textures/Interface/Nano/window_background_bordered.png new file mode 100644 index 0000000000000000000000000000000000000000..461fbf31141db0b468bfe830aa8f6f729eb3a60d GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=&H|6fVg?31We{epSZZGe6l5>) z^mS!_!p+3Uz*bUubPZ6b#M8wwghQ4wlVRF_Mj)TT+|utqhz5a^$2T!DA`3u-85o#g njJL1v!k7p_VNsy1P=M9Ut%f{DBbQ#908-=W>gTe~DWM4f4^bsK literal 0 HcmV?d00001 From 294985a7c6f0959e4ac960ac921bdbf9b29cc618 Mon Sep 17 00:00:00 2001 From: Metal Gear Sloth Date: Tue, 10 Nov 2020 15:23:07 +1100 Subject: [PATCH 40/41] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index fd93fcb89c..ee381804ec 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit fd93fcb89ca1a9dc8a640eb2a10a74e18e0a7106 +Subproject commit ee381804ec3b880ee63a610289de3fb28f4d3f60 From e567e9fec109bdd3402892684299fb0c1cbcc179 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Tue, 10 Nov 2020 00:30:19 -0800 Subject: [PATCH 41/41] Fix signallink command not working (#2534) The InteractionSystem always returns true, so this change runs the SignalLinkerSystem CommandBind before InteractionSystem --- Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs index 57406584c7..30979a3e5d 100644 --- a/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/SignalLinkerSystem.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Content.Server.GameObjects.Components.MachineLinking; +using Content.Server.GameObjects.EntitySystems.Click; using Robust.Server.Interfaces.Console; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; @@ -42,7 +43,7 @@ namespace Content.Server.GameObjects.EntitySystems if (_transmitters.Count == 0) { CommandBinds.Builder - .Bind(EngineKeyFunctions.Use, new PointerInputCmdHandler(HandleUse)) + .BindBefore(EngineKeyFunctions.Use, new PointerInputCmdHandler(HandleUse), typeof(InteractionSystem)) .Register(); }