diff --git a/Content.Client/Administration/Managers/ClientAdminManager.cs b/Content.Client/Administration/Managers/ClientAdminManager.cs index 0f740c8104..3f072691de 100644 --- a/Content.Client/Administration/Managers/ClientAdminManager.cs +++ b/Content.Client/Administration/Managers/ClientAdminManager.cs @@ -15,6 +15,7 @@ namespace Content.Client.Administration.Managers [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IClientNetManager _netMgr = default!; [Dependency] private readonly IClientConGroupController _conGroup = default!; + [Dependency] private readonly IClientConsoleHost _host = default!; [Dependency] private readonly IResourceManager _res = default!; [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly IUserInterfaceManager _userInterface = default!; @@ -86,12 +87,12 @@ namespace Content.Client.Administration.Managers private void UpdateMessageRx(MsgUpdateAdminStatus message) { _availableCommands.Clear(); - var host = IoCManager.Resolve(); // Anything marked as Any we'll just add even if the server doesn't know about it. - foreach (var (command, instance) in host.AvailableCommands) + foreach (var (command, instance) in _host.AvailableCommands) { - if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null) continue; + if (Attribute.GetCustomAttribute(instance.GetType(), typeof(AnyCommandAttribute)) == null) + continue; _availableCommands.Add(command); } diff --git a/Content.Client/Audio/AmbientSoundSystem.cs b/Content.Client/Audio/AmbientSoundSystem.cs index e6ea94c3a6..9929751b22 100644 --- a/Content.Client/Audio/AmbientSoundSystem.cs +++ b/Content.Client/Audio/AmbientSoundSystem.cs @@ -3,17 +3,13 @@ using Content.Shared.CCVar; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Shared.Audio; -using Robust.Shared.Log; using Robust.Shared.Configuration; -using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Random; using Robust.Shared.Timing; using Robust.Shared.Utility; using System.Linq; using System.Numerics; -using Robust.Client.GameObjects; -using Robust.Shared.Audio.Effects; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; @@ -31,6 +27,7 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem [Dependency] private readonly SharedTransformSystem _xformSystem = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly IOverlayManager _overlayManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -65,18 +62,19 @@ public sealed class AmbientSoundSystem : SharedAmbientSoundSystem get => _overlayEnabled; set { - if (_overlayEnabled == value) return; + if (_overlayEnabled == value) + return; + _overlayEnabled = value; - var overlayManager = IoCManager.Resolve(); if (_overlayEnabled) { _overlay = new AmbientSoundOverlay(EntityManager, this, EntityManager.System()); - overlayManager.AddOverlay(_overlay); + _overlayManager.AddOverlay(_overlay); } else { - overlayManager.RemoveOverlay(_overlay!); + _overlayManager.RemoveOverlay(_overlay!); _overlay = null; } } diff --git a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs index bf7ab26cba..d82f6b07fb 100644 --- a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs +++ b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs @@ -3,11 +3,8 @@ using Content.Client.Gameplay; using Content.Shared.Audio; using Content.Shared.CCVar; using Content.Shared.GameTicking; -using Content.Shared.Random; using Content.Shared.Random.Rules; -using Robust.Client.GameObjects; using Robust.Client.Player; -using Robust.Client.ResourceManagement; using Robust.Client.State; using Robust.Shared.Audio; using Robust.Shared.Audio.Components; @@ -25,6 +22,7 @@ public sealed partial class ContentAudioSystem { [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly IRobustRandom _random = default!; @@ -61,7 +59,7 @@ public sealed partial class ContentAudioSystem private void InitializeAmbientMusic() { Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChanged, true); - _sawmill = IoCManager.Resolve().GetSawmill("audio.ambience"); + _sawmill = _logManager.GetSawmill("audio.ambience"); // Reset audio _nextAudio = TimeSpan.MaxValue; diff --git a/Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs b/Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs new file mode 100644 index 0000000000..348cfee0f8 --- /dev/null +++ b/Content.Client/Changeling/Systems/ChangelingIdentitySystem.cs @@ -0,0 +1,30 @@ +using Content.Shared.Changeling.Components; +using Content.Shared.Changeling.Systems; +using Robust.Client.GameObjects; + +namespace Content.Client.Changeling.Systems; + +public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem +{ + [Dependency] private readonly UserInterfaceSystem _ui = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAfterAutoHandleState); + } + + private void OnAfterAutoHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + UpdateUi(ent); + } + + public void UpdateUi(EntityUid uid) + { + if (_ui.TryGetOpenUi(uid, ChangelingTransformUiKey.Key, out var bui)) + { + bui.Update(); + } + } +} diff --git a/Content.Client/Changeling/Transform/ChangelingTransformBoundUserInterface.cs b/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs similarity index 72% rename from Content.Client/Changeling/Transform/ChangelingTransformBoundUserInterface.cs rename to Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs index 9401231303..8220e18708 100644 --- a/Content.Client/Changeling/Transform/ChangelingTransformBoundUserInterface.cs +++ b/Content.Client/Changeling/UI/ChangelingTransformBoundUserInterface.cs @@ -2,7 +2,7 @@ using JetBrains.Annotations; using Robust.Client.UserInterface; -namespace Content.Client.Changeling.Transform; +namespace Content.Client.Changeling.UI; [UsedImplicitly] public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey) @@ -16,16 +16,16 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne _window = this.CreateWindow(); _window.OnIdentitySelect += SendIdentitySelect; + + _window.Update(Owner); } - protected override void UpdateState(BoundUserInterfaceState state) + public override void Update() { - base.UpdateState(state); - - if (state is not ChangelingTransformBoundUserInterfaceState current) + if (_window == null) return; - _window?.UpdateState(current); + _window.Update(Owner); } public void SendIdentitySelect(NetEntity identityId) diff --git a/Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml b/Content.Client/Changeling/UI/ChangelingTransformMenu.xaml similarity index 100% rename from Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml rename to Content.Client/Changeling/UI/ChangelingTransformMenu.xaml diff --git a/Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml.cs b/Content.Client/Changeling/UI/ChangelingTransformMenu.xaml.cs similarity index 80% rename from Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml.cs rename to Content.Client/Changeling/UI/ChangelingTransformMenu.xaml.cs index fa2deaf431..ebd4e90440 100644 --- a/Content.Client/Changeling/Transform/ChangelingTransformMenu.xaml.cs +++ b/Content.Client/Changeling/UI/ChangelingTransformMenu.xaml.cs @@ -1,11 +1,11 @@ using System.Numerics; using Content.Client.UserInterface.Controls; -using Content.Shared.Changeling.Systems; +using Content.Shared.Changeling.Components; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; -namespace Content.Client.Changeling.Transform; +namespace Content.Client.Changeling.UI; [GenerateTypedNameReferences] public sealed partial class ChangelingTransformMenu : RadialMenu @@ -19,13 +19,15 @@ public sealed partial class ChangelingTransformMenu : RadialMenu IoCManager.InjectDependencies(this); } - public void UpdateState(ChangelingTransformBoundUserInterfaceState state) + public void Update(EntityUid uid) { Main.DisposeAllChildren(); - foreach (var identity in state.Identites) - { - var identityUid = _entity.GetEntity(identity); + if (!_entity.TryGetComponent(uid, out var identityComp)) + return; + + foreach (var identityUid in identityComp.ConsumedIdentities) + { if (!_entity.TryGetComponent(identityUid, out var metadata)) continue; @@ -48,7 +50,7 @@ public sealed partial class ChangelingTransformMenu : RadialMenu entView.SetEntity(identityUid); button.OnButtonUp += _ => { - OnIdentitySelect?.Invoke(identity); + OnIdentitySelect?.Invoke(_entity.GetNetEntity(identityUid)); Close(); }; button.AddChild(entView); diff --git a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs index 4ddde885fa..75b1704b0d 100644 --- a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs +++ b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs @@ -30,6 +30,10 @@ namespace Content.Client.Lathe.UI { SendMessage(new LatheQueueRecipeMessage(recipe, amount)); }; + _menu.QueueDeleteAction += index => SendMessage(new LatheDeleteRequestMessage(index)); + _menu.QueueMoveUpAction += index => SendMessage(new LatheMoveRequestMessage(index, -1)); + _menu.QueueMoveDownAction += index => SendMessage(new LatheMoveRequestMessage(index, 1)); + _menu.DeleteFabricatingAction += () => SendMessage(new LatheAbortFabricationMessage()); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Lathe/UI/LatheMenu.xaml b/Content.Client/Lathe/UI/LatheMenu.xaml index 28b79254c0..a5c8f6a85c 100644 --- a/Content.Client/Lathe/UI/LatheMenu.xaml +++ b/Content.Client/Lathe/UI/LatheMenu.xaml @@ -1,6 +1,7 @@ + diff --git a/Content.Client/Lathe/UI/LatheMenu.xaml.cs b/Content.Client/Lathe/UI/LatheMenu.xaml.cs index 66d875b0f2..ce190464d2 100644 --- a/Content.Client/Lathe/UI/LatheMenu.xaml.cs +++ b/Content.Client/Lathe/UI/LatheMenu.xaml.cs @@ -26,6 +26,10 @@ public sealed partial class LatheMenu : DefaultWindow public event Action? OnServerListButtonPressed; public event Action? RecipeQueueAction; + public event Action? QueueDeleteAction; + public event Action? QueueMoveUpAction; + public event Action? QueueMoveDownAction; + public event Action? DeleteFabricatingAction; public List> Recipes = new(); @@ -50,12 +54,21 @@ public sealed partial class LatheMenu : DefaultWindow }; AmountLineEdit.OnTextChanged += _ => { + if (int.TryParse(AmountLineEdit.Text, out var amount)) + { + if (amount > LatheSystem.MaxItemsPerRequest) + AmountLineEdit.Text = LatheSystem.MaxItemsPerRequest.ToString(); + else if (amount < 0) + AmountLineEdit.Text = "0"; + } + PopulateRecipes(); }; FilterOption.OnItemSelected += OnItemSelected; ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a); + DeleteFabricating.OnPressed += _ => DeleteFabricatingAction?.Invoke(); } public void SetEntity(EntityUid uid) @@ -223,22 +236,27 @@ public sealed partial class LatheMenu : DefaultWindow /// Populates the build queue list with all queued items /// /// - public void PopulateQueueList(IReadOnlyCollection> queue) + public void PopulateQueueList(IReadOnlyCollection queue) { QueueList.DisposeAllChildren(); var idx = 1; - foreach (var recipeProto in queue) + foreach (var batch in queue) { - var recipe = _prototypeManager.Index(recipeProto); - var queuedRecipeBox = new BoxContainer(); - queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal; + var recipe = _prototypeManager.Index(batch.Recipe); - queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe)); + var itemName = _lathe.GetRecipeName(batch.Recipe); + string displayText; + if (batch.ItemsRequested > 1) + displayText = Loc.GetString("lathe-menu-item-batch", ("index", idx), ("name", itemName), ("printed", batch.ItemsPrinted), ("total", batch.ItemsRequested)); + else + displayText = Loc.GetString("lathe-menu-item-single", ("index", idx), ("name", itemName)); + + var queuedRecipeBox = new QueuedRecipeControl(displayText, idx - 1, GetRecipeDisplayControl(recipe)); + queuedRecipeBox.OnDeletePressed += s => QueueDeleteAction?.Invoke(s); + queuedRecipeBox.OnMoveUpPressed += s => QueueMoveUpAction?.Invoke(s); + queuedRecipeBox.OnMoveDownPressed += s => QueueMoveDownAction?.Invoke(s); - var queuedRecipeLabel = new Label(); - queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}"; - queuedRecipeBox.AddChild(queuedRecipeLabel); QueueList.AddChild(queuedRecipeBox); idx++; } diff --git a/Content.Client/Lathe/UI/QueuedRecipeControl.xaml b/Content.Client/Lathe/UI/QueuedRecipeControl.xaml new file mode 100644 index 0000000000..b1d4b496a1 --- /dev/null +++ b/Content.Client/Lathe/UI/QueuedRecipeControl.xaml @@ -0,0 +1,35 @@ + + + + + diff --git a/Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs b/Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs new file mode 100644 index 0000000000..c4ba9803b0 --- /dev/null +++ b/Content.Client/Lathe/UI/QueuedRecipeControl.xaml.cs @@ -0,0 +1,36 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Lathe.UI; + +[GenerateTypedNameReferences] +public sealed partial class QueuedRecipeControl : Control +{ + public Action? OnDeletePressed; + public Action? OnMoveUpPressed; + public Action? OnMoveDownPressed; + + public QueuedRecipeControl(string displayText, int index, Control displayControl) + { + RobustXamlLoader.Load(this); + + RecipeName.Text = displayText; + RecipeDisplayContainer.AddChild(displayControl); + + MoveUp.OnPressed += (_) => + { + OnMoveUpPressed?.Invoke(index); + }; + + MoveDown.OnPressed += (_) => + { + OnMoveDownPressed?.Invoke(index); + }; + + Delete.OnPressed += (_) => + { + OnDeletePressed?.Invoke(index); + }; + } +} diff --git a/Content.Client/NPC/PathfindingSystem.cs b/Content.Client/NPC/PathfindingSystem.cs index 0c72a8f99f..dc8fd98433 100644 --- a/Content.Client/NPC/PathfindingSystem.cs +++ b/Content.Client/NPC/PathfindingSystem.cs @@ -20,6 +20,7 @@ namespace Content.Client.NPC [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IOverlayManager _overlayManager = default!; [Dependency] private readonly IResourceCache _cache = default!; [Dependency] private readonly NPCSteeringSystem _steering = default!; [Dependency] private readonly MapSystem _mapSystem = default!; @@ -30,17 +31,15 @@ namespace Content.Client.NPC get => _modes; set { - var overlayManager = IoCManager.Resolve(); - if (value == PathfindingDebugMode.None) { Breadcrumbs.Clear(); Polys.Clear(); - overlayManager.RemoveOverlay(); + _overlayManager.RemoveOverlay(); } - else if (!overlayManager.HasOverlay()) + else if (!_overlayManager.HasOverlay()) { - overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem, _transformSystem)); + _overlayManager.AddOverlay(new PathfindingOverlay(EntityManager, _eyeManager, _inputManager, _mapManager, _cache, this, _mapSystem, _transformSystem)); } if ((value & PathfindingDebugMode.Steering) != 0x0) diff --git a/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs b/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs index 784c39a6ce..1f060e532d 100644 --- a/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs +++ b/Content.Client/Radiation/Overlays/RadiationDebugOverlay.cs @@ -11,6 +11,8 @@ namespace Content.Client.Radiation.Overlays; public sealed class RadiationDebugOverlay : Overlay { [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IResourceCache _cache = default!; + private readonly SharedMapSystem _mapSystem; private readonly RadiationSystem _radiation; @@ -24,8 +26,7 @@ public sealed class RadiationDebugOverlay : Overlay _radiation = _entityManager.System(); _mapSystem = _entityManager.System(); - var cache = IoCManager.Resolve(); - _font = new VectorFont(cache.GetResource("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8); + _font = new VectorFont(_cache.GetResource("/Fonts/NotoSans/NotoSans-Regular.ttf"), 8); } protected override void Draw(in OverlayDrawArgs args) diff --git a/Content.Client/Shuttles/Systems/ShuttleSystem.EmergencyConsole.cs b/Content.Client/Shuttles/Systems/ShuttleSystem.EmergencyConsole.cs index 56b54c176a..f6e6594af5 100644 --- a/Content.Client/Shuttles/Systems/ShuttleSystem.EmergencyConsole.cs +++ b/Content.Client/Shuttles/Systems/ShuttleSystem.EmergencyConsole.cs @@ -16,20 +16,20 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem get => _enableShuttlePosition; set { - if (_enableShuttlePosition == value) return; + if (_enableShuttlePosition == value) + return; _enableShuttlePosition = value; - var overlayManager = IoCManager.Resolve(); if (_enableShuttlePosition) { _overlay = new EmergencyShuttleOverlay(EntityManager.TransformQuery, XformSystem); - overlayManager.AddOverlay(_overlay); + _overlays.AddOverlay(_overlay); RaiseNetworkEvent(new EmergencyShuttleRequestPositionMessage()); } else { - overlayManager.RemoveOverlay(_overlay!); + _overlays.RemoveOverlay(_overlay!); _overlay = null; } } diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index ebc024bd2f..15af9dc981 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -42,6 +42,7 @@ public sealed partial class GunSystem : SharedGunSystem [Dependency] private readonly IComponentFactory _factory = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IInputManager _inputManager = default!; + [Dependency] private readonly IOverlayManager _overlayManager = default!; [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IStateManager _state = default!; [Dependency] private readonly IPrototypeManager _proto = default!; @@ -75,11 +76,10 @@ public sealed partial class GunSystem : SharedGunSystem return; _spreadOverlay = value; - var overlayManager = IoCManager.Resolve(); if (_spreadOverlay) { - overlayManager.AddOverlay(new GunSpreadOverlay( + _overlayManager.AddOverlay(new GunSpreadOverlay( EntityManager, _eyeManager, Timing, @@ -90,7 +90,7 @@ public sealed partial class GunSystem : SharedGunSystem } else { - overlayManager.RemoveOverlay(); + _overlayManager.RemoveOverlay(); } } } diff --git a/Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs b/Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs new file mode 100644 index 0000000000..a7203d9259 --- /dev/null +++ b/Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs @@ -0,0 +1,20 @@ +using Content.IntegrationTests.Tests.Interaction; +using Content.Shared.Engineering.Systems; + +namespace Content.IntegrationTests.Tests.Engineering; + +[TestFixture] +[TestOf(typeof(InflatableSafeDisassemblySystem))] +public sealed class InflatablesDeflateTest : InteractionTest +{ + [Test] + public async Task Test() + { + await SpawnTarget(InflatableWall); + + await InteractUsing(Needle); + + AssertDeleted(); + await AssertEntityLookup(new EntitySpecifier(InflatableWallStack.Id, 1)); + } +} diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs index 5db5d91d0d..8917ba7ead 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs @@ -1,3 +1,6 @@ +using Content.Shared.Stacks; +using Robust.Shared.Prototypes; + namespace Content.IntegrationTests.Tests.Interaction; // This partial class contains various constant prototype IDs common to interaction tests. @@ -32,4 +35,9 @@ public abstract partial class InteractionTest protected const string Manipulator1 = "MicroManipulatorStockPart"; protected const string Battery1 = "PowerCellSmall"; protected const string Battery4 = "PowerCellHyper"; + + // Inflatables & Needle used to pop them + protected static readonly EntProtoId InflatableWall = "InflatableWall"; + protected static readonly EntProtoId Needle = "WeaponMeleeNeedle"; + protected static readonly ProtoId InflatableWallStack = "InflatableWall"; } diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index 2df47f2dfc..ec393f2bbb 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -6,7 +6,6 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Clothing.Systems; using Content.Server.Electrocution; using Content.Server.Explosion.EntitySystems; using Content.Server.GhostKick; @@ -22,6 +21,7 @@ using Content.Server.Tabletop.Components; using Content.Server.Terminator.Systems; using Content.Shared.Administration; using Content.Shared.Administration.Components; +using Content.Shared.Atmos.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Part; using Content.Shared.Clumsy; @@ -47,7 +47,6 @@ using Content.Shared.Nutrition.Components; using Content.Shared.Popups; using Content.Shared.Slippery; using Content.Shared.Storage.Components; -using Content.Shared.Stunnable; using Content.Shared.Tabletop.Components; using Content.Shared.Tools.Systems; using Content.Shared.Verbs; @@ -57,7 +56,6 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using Robust.Shared.Random; -using Robust.Shared.Timing; using Robust.Shared.Utility; using Timer = Robust.Shared.Timing.Timer; diff --git a/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs index d38bda562b..5ceb9888f4 100644 --- a/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/PyroclasticAnomalySystem.cs @@ -1,7 +1,7 @@ -using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Effects.Components; +using Content.Shared.Atmos.Components; using Robust.Shared.Map; namespace Content.Server.Anomaly.Effects; diff --git a/Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs b/Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs new file mode 100644 index 0000000000..8cb3dec3d6 --- /dev/null +++ b/Content.Server/Changeling/Systems/ChangelingIdentitySystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Changeling.Systems; + +namespace Content.Server.Changeling.Systems; + +public sealed class ChangelingIdentitySystem : SharedChangelingIdentitySystem; diff --git a/Content.Server/EntityEffects/EntityEffectSystem.cs b/Content.Server/EntityEffects/EntityEffectSystem.cs index b0b8ab5045..f423a43261 100644 --- a/Content.Server/EntityEffects/EntityEffectSystem.cs +++ b/Content.Server/EntityEffects/EntityEffectSystem.cs @@ -1,6 +1,5 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; -using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Body.Systems; @@ -22,6 +21,7 @@ using Content.Server.Temperature.Systems; using Content.Server.Traits.Assorted; using Content.Server.Zombies; using Content.Shared.Atmos; +using Content.Shared.Atmos.Components; using Content.Shared.Body.Components; using Content.Shared.Coordinates.Helpers; using Content.Shared.EntityEffects.EffectConditions; diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs index bc17eeee65..1649e140b3 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs @@ -5,6 +5,7 @@ using Content.Server.Atmos.Components; using Content.Server.NodeContainer.EntitySystems; using Content.Server.NPC.Pathfinding; using Content.Shared._RMC14.Explosion; +using Content.Shared.Atmos.Components; using Content.Shared.Camera; using Content.Shared.CCVar; using Content.Shared.Damage; diff --git a/Content.Server/Lathe/LatheSystem.cs b/Content.Server/Lathe/LatheSystem.cs index 4599fa31ae..b381a7f28c 100644 --- a/Content.Server/Lathe/LatheSystem.cs +++ b/Content.Server/Lathe/LatheSystem.cs @@ -75,6 +75,9 @@ namespace Content.Server.Lathe SubscribeLocalEvent(OnLatheQueueRecipeMessage); SubscribeLocalEvent(OnLatheSyncRequestMessage); + SubscribeLocalEvent(OnLatheDeleteRequestMessage); + SubscribeLocalEvent(OnLatheMoveRequestMessage); + SubscribeLocalEvent(OnLatheAbortFabricationMessage); SubscribeLocalEvent((u, c, _) => UpdateUserInterfaceState(u, c)); SubscribeLocalEvent(OnMaterialAmountChanged); @@ -168,23 +171,32 @@ namespace Content.Server.Lathe return ev.Recipes.ToList(); } - public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, LatheComponent? component = null) + public bool TryAddToQueue(EntityUid uid, LatheRecipePrototype recipe, int quantity, LatheComponent? component = null) { if (!Resolve(uid, ref component)) return false; - if (!CanProduce(uid, recipe, 1, component)) + if (quantity <= 0) + return false; + quantity = int.Min(quantity, MaxItemsPerRequest); + + if (!CanProduce(uid, recipe, quantity, component)) return false; foreach (var (mat, amount) in recipe.Materials) { var adjustedAmount = recipe.ApplyMaterialDiscount - ? (int) (-amount * component.MaterialUseMultiplier) + ? (int)(-amount * component.MaterialUseMultiplier) : -amount; + adjustedAmount *= quantity; _materialStorage.TryChangeMaterialAmount(uid, mat, adjustedAmount); } - component.Queue.Enqueue(recipe); + + if (component.Queue.Last is { } node && node.ValueRef.Recipe == recipe.ID) + node.ValueRef.ItemsRequested += quantity; + else + component.Queue.AddLast(new LatheRecipeBatch(recipe.ID, 0, quantity)); return true; } @@ -196,8 +208,11 @@ namespace Content.Server.Lathe if (component.CurrentRecipe != null || component.Queue.Count <= 0 || !this.IsPowered(uid, EntityManager)) return false; - var recipeProto = component.Queue.Dequeue(); - var recipe = _proto.Index(recipeProto); + var batch = component.Queue.First(); + batch.ItemsPrinted++; + if (batch.ItemsPrinted >= batch.ItemsRequested || batch.ItemsPrinted < 0) // Rollover sanity check + component.Queue.RemoveFirst(); + var recipe = _proto.Index(batch.Recipe); var time = _reagentSpeed.ApplySpeed(uid, recipe.CompleteTime) * component.TimeMultiplier; @@ -273,8 +288,8 @@ namespace Content.Server.Lathe return; var producing = component.CurrentRecipe; - if (producing == null && component.Queue.TryPeek(out var next)) - producing = next; + if (producing == null && component.Queue.First is { } node) + producing = node.Value.Recipe; var state = new LatheUpdateState(GetAvailableRecipes(uid, component), component.Queue.ToArray(), producing); _uiSys.SetUiState(uid, LatheUiKey.Key, state); @@ -351,12 +366,10 @@ namespace Content.Server.Lathe { if (!args.Powered) { - RemComp(uid); - UpdateRunningAppearance(uid, false); + AbortProduction(uid); } - else if (component.CurrentRecipe != null) + else { - EnsureComp(uid); TryStartProducing(uid, component); } } @@ -420,25 +433,46 @@ namespace Content.Server.Lathe return GetAvailableRecipes(uid, component).Contains(recipe.ID); } + public void AbortProduction(EntityUid uid, LatheComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (component.CurrentRecipe != null) + { + if (component.Queue.Count > 0) + { + // Batch abandoned while printing last item, need to create a one-item batch + var batch = component.Queue.First(); + if (batch.Recipe != component.CurrentRecipe) + { + var newBatch = new LatheRecipeBatch(component.CurrentRecipe.Value, 0, 1); + component.Queue.AddFirst(newBatch); + } + else if (batch.ItemsPrinted > 0) + { + batch.ItemsPrinted--; + } + } + + component.CurrentRecipe = null; + } + RemCompDeferred(uid); + UpdateUserInterfaceState(uid, component); + UpdateRunningAppearance(uid, false); + } + #region UI Messages private void OnLatheQueueRecipeMessage(EntityUid uid, LatheComponent component, LatheQueueRecipeMessage args) { if (_proto.TryIndex(args.ID, out LatheRecipePrototype? recipe)) { - var count = 0; - for (var i = 0; i < args.Quantity; i++) - { - if (TryAddToQueue(uid, recipe, component)) - count++; - else - break; - } - if (count > 0) + if (TryAddToQueue(uid, recipe, args.Quantity, component)) { _adminLogger.Add(LogType.Action, LogImpact.Low, - $"{ToPrettyString(args.Actor):player} queued {count} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}"); + $"{ToPrettyString(args.Actor):player} queued {args.Quantity} {GetRecipeName(recipe)} at {ToPrettyString(uid):lathe}"); } } TryStartProducing(uid, component); @@ -449,6 +483,92 @@ namespace Content.Server.Lathe { UpdateUserInterfaceState(uid, component); } + + /// + /// Removes a batch from the batch queue by index. + /// If the index given does not exist or is outside of the bounds of the lathe's batch queue, nothing happens. + /// + /// The lathe whose queue is being altered. + /// + /// + public void OnLatheDeleteRequestMessage(EntityUid uid, LatheComponent component, ref LatheDeleteRequestMessage args) + { + if (args.Index < 0 || args.Index >= component.Queue.Count) + return; + + var node = component.Queue.First; + for (int i = 0; i < args.Index; i++) + node = node?.Next; + + if (node == null) // Shouldn't happen with checks above. + return; + + var batch = node.Value; + _adminLogger.Add(LogType.Action, + LogImpact.Low, + $"{ToPrettyString(args.Actor):player} deleted a lathe job for ({batch.ItemsPrinted}/{batch.ItemsRequested}) {GetRecipeName(batch.Recipe)} at {ToPrettyString(uid):lathe}"); + + component.Queue.Remove(node); + UpdateUserInterfaceState(uid, component); + } + + public void OnLatheMoveRequestMessage(EntityUid uid, LatheComponent component, ref LatheMoveRequestMessage args) + { + if (args.Change == 0 || args.Index < 0 || args.Index >= component.Queue.Count) + return; + + // New index must be within the bounds of the batch. + var newIndex = args.Index + args.Change; + if (newIndex < 0 || newIndex >= component.Queue.Count) + return; + + var node = component.Queue.First; + for (int i = 0; i < args.Index; i++) + node = node?.Next; + + if (node == null) // Something went wrong. + return; + + if (args.Change > 0) + { + var newRelativeNode = node.Next; + for (int i = 1; i < args.Change; i++) // 1-indexed: starting from Next + newRelativeNode = newRelativeNode?.Next; + + if (newRelativeNode == null) // Something went wrong. + return; + + component.Queue.Remove(node); + component.Queue.AddAfter(newRelativeNode, node); + } + else + { + var newRelativeNode = node.Previous; + for (int i = 1; i < -args.Change; i++) // 1-indexed: starting from Previous + newRelativeNode = newRelativeNode?.Previous; + + if (newRelativeNode == null) // Something went wrong. + return; + + component.Queue.Remove(node); + component.Queue.AddBefore(newRelativeNode, node); + } + + UpdateUserInterfaceState(uid, component); + } + + public void OnLatheAbortFabricationMessage(EntityUid uid, LatheComponent component, ref LatheAbortFabricationMessage args) + { + if (component.CurrentRecipe == null) + return; + + _adminLogger.Add(LogType.Action, + LogImpact.Low, + $"{ToPrettyString(args.Actor):player} aborted printing {GetRecipeName(component.CurrentRecipe.Value)} at {ToPrettyString(uid):lathe}"); + + component.CurrentRecipe = null; + FinishProducing(uid, component); + } #endregion } } diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index 5f077a06bb..813626a1c4 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -1,4 +1,3 @@ -using Content.Server.Atmos.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Hands.Systems; using Content.Server.NPC.Queries; @@ -6,13 +5,11 @@ using Content.Server.NPC.Queries.Considerations; using Content.Server.NPC.Queries.Curves; using Content.Server.NPC.Queries.Queries; using Content.Server.Nutrition.Components; -using Content.Server.Nutrition.EntitySystems; using Content.Server.Temperature.Components; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.Fluids.Components; -using Content.Shared.Hands.Components; using Content.Shared.Inventory; using Content.Shared.Mobs; using Content.Shared.Mobs.Systems; @@ -31,6 +28,7 @@ using Microsoft.Extensions.ObjectPool; using Robust.Server.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Utility; +using Content.Shared.Atmos.Components; using System.Linq; namespace Content.Server.NPC.Systems; diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index 7ac022675c..34ab3c4d18 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -272,7 +272,7 @@ public sealed partial class PolymorphSystem : EntitySystem if (configuration.TransferHumanoidAppearance) { - _humanoid.CloneAppearance(uid, child); + _humanoid.CloneAppearance(child, uid); } if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) diff --git a/Content.Server/Trigger/Systems/GameRuleTriggerSystem.cs b/Content.Server/Trigger/Systems/GameRuleTriggerSystem.cs new file mode 100644 index 0000000000..245b9c8408 --- /dev/null +++ b/Content.Server/Trigger/Systems/GameRuleTriggerSystem.cs @@ -0,0 +1,44 @@ +using Content.Server.Administration.Logs; +using Content.Server.GameTicking; +using Content.Shared.Database; +using Content.Shared.Trigger; +using Content.Shared.Trigger.Components.Effects; + +namespace Content.Server.Trigger.Systems; + +/// +/// Trigger system for game rules. +/// +public sealed class GameRuleTriggerSystem : EntitySystem +{ + [Dependency] private readonly GameTicker _ticker = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(AddRuleOnTrigger); + } + + private void AddRuleOnTrigger(Entity ent, ref TriggerEvent args) + { + if (args.Key != null && !ent.Comp.KeysIn.Contains(args.Key)) + return; + + var rule = _ticker.AddGameRule(ent.Comp.GameRule); + + _adminLogger.Add(LogType.EventStarted, + $"{ToPrettyString(args.User):entity} added a game rule [{ent.Comp.GameRule}]" + + $" via a trigger on {ToPrettyString(ent.Owner):entity}."); + + if (ent.Comp.StartRule && _ticker.RunLevel == GameRunLevel.InRound) + { + _ticker.StartGameRule(rule); + _adminLogger.Add(LogType.EventStarted, $"{ToPrettyString(args.User):entity} started game rule [{ent.Comp.GameRule}]."); + } + + args.Handled = true; + } +} diff --git a/Content.Server/Weapons/Melee/Balloon/BalloonPopperSystem.cs b/Content.Server/Weapons/Melee/Balloon/BalloonPopperSystem.cs index a8460a8c66..d4ab81ae10 100644 --- a/Content.Server/Weapons/Melee/Balloon/BalloonPopperSystem.cs +++ b/Content.Server/Weapons/Melee/Balloon/BalloonPopperSystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Popups; using Content.Shared.Tag; using Content.Shared.Weapons.Melee.Events; using Content.Shared.Throwing; +using Content.Shared.Weapons.Melee.Balloon; using Robust.Shared.Audio.Systems; namespace Content.Server.Weapons.Melee.Balloon; diff --git a/Content.Server/Xenoarchaeology/Artifact/XAE/XAEIgniteSystem.cs b/Content.Server/Xenoarchaeology/Artifact/XAE/XAEIgniteSystem.cs index 14270fb866..7e8fff73ad 100644 --- a/Content.Server/Xenoarchaeology/Artifact/XAE/XAEIgniteSystem.cs +++ b/Content.Server/Xenoarchaeology/Artifact/XAE/XAEIgniteSystem.cs @@ -1,6 +1,6 @@ -using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Xenoarchaeology.Artifact.XAE.Components; +using Content.Shared.Atmos.Components; using Content.Shared.Xenoarchaeology.Artifact; using Content.Shared.Xenoarchaeology.Artifact.XAE; using Robust.Shared.Random; diff --git a/Content.Server/Atmos/Components/FlammableComponent.cs b/Content.Shared/Atmos/Components/FlammableComponent.cs similarity index 95% rename from Content.Server/Atmos/Components/FlammableComponent.cs rename to Content.Shared/Atmos/Components/FlammableComponent.cs index 9ae99a1513..acfb9e2540 100644 --- a/Content.Server/Atmos/Components/FlammableComponent.cs +++ b/Content.Shared/Atmos/Components/FlammableComponent.cs @@ -1,11 +1,12 @@ using Content.Shared.Alert; using Content.Shared.Damage; +using Robust.Shared.GameStates; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Prototypes; -namespace Content.Server.Atmos.Components +namespace Content.Shared.Atmos.Components { - [RegisterComponent] + [RegisterComponent, NetworkedComponent] public sealed partial class FlammableComponent : Component { [DataField] diff --git a/Content.Shared/Changeling/Components/ChangelingIdentityComponent.cs b/Content.Shared/Changeling/Components/ChangelingIdentityComponent.cs index 2779164e4e..8e74f83537 100644 --- a/Content.Shared/Changeling/Components/ChangelingIdentityComponent.cs +++ b/Content.Shared/Changeling/Components/ChangelingIdentityComponent.cs @@ -8,7 +8,7 @@ namespace Content.Shared.Changeling.Components; /// The storage component for Changelings, it handles the link between a changeling and its consumed identities /// that exist on a paused map. /// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)] public sealed partial class ChangelingIdentityComponent : Component { /// diff --git a/Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs b/Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs index a064858d43..500ee06b22 100644 --- a/Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs +++ b/Content.Shared/Changeling/Systems/ChangelingDevourSystem.cs @@ -32,7 +32,7 @@ public sealed class ChangelingDevourSystem : EntitySystem [Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!; [Dependency] private readonly DamageableSystem _damageable = default!; [Dependency] private readonly MobStateSystem _mobState = default!; - [Dependency] private readonly ChangelingIdentitySystem _changelingIdentitySystem = default!; + [Dependency] private readonly SharedChangelingIdentitySystem _changelingIdentitySystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; diff --git a/Content.Shared/Changeling/Systems/ChangelingTransformSystem.UI.cs b/Content.Shared/Changeling/Systems/ChangelingTransformSystem.UI.cs index 98926631dc..e555147352 100644 --- a/Content.Shared/Changeling/Systems/ChangelingTransformSystem.UI.cs +++ b/Content.Shared/Changeling/Systems/ChangelingTransformSystem.UI.cs @@ -14,20 +14,8 @@ public sealed class ChangelingTransformIdentitySelectMessage(NetEntity targetIde public readonly NetEntity TargetIdentity = targetIdentity; } -// TODO: Replace with component states. -// We are already networking the ChangelingIdentityComponent, which contains all this information, -// so we can just read it from them from the component and update the UI in an AfterAuotHandleState subscription. [Serializable, NetSerializable] -public sealed class ChangelingTransformBoundUserInterfaceState(List identities) : BoundUserInterfaceState -{ - /// - /// The uids of the cloned identities. - /// - public readonly List Identites = identities; -} - -[Serializable, NetSerializable] -public enum TransformUI : byte +public enum ChangelingTransformUiKey : byte { Key, } diff --git a/Content.Shared/Changeling/Systems/ChangelingTransformSystem.cs b/Content.Shared/Changeling/Systems/ChangelingTransformSystem.cs index 31f22b9294..cf8d9d7cb6 100644 --- a/Content.Shared/Changeling/Systems/ChangelingTransformSystem.cs +++ b/Content.Shared/Changeling/Systems/ChangelingTransformSystem.cs @@ -44,7 +44,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem _actionsSystem.AddAction(ent, ref ent.Comp.ChangelingTransformActionEntity, ent.Comp.ChangelingTransformAction); var userInterfaceComp = EnsureComp(ent); - _uiSystem.SetUi((ent, userInterfaceComp), TransformUI.Key, new InterfaceData(ChangelingBuiXmlGeneratedName)); + _uiSystem.SetUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, new InterfaceData(ChangelingBuiXmlGeneratedName)); } private void OnShutdown(Entity ent, ref ComponentShutdown args) @@ -64,18 +64,9 @@ public sealed partial class ChangelingTransformSystem : EntitySystem if (!TryComp(ent, out var userIdentity)) return; - if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), TransformUI.Key, args.Performer)) + if (!_uiSystem.IsUiOpen((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer)) { - _uiSystem.OpenUi((ent, userInterfaceComp), TransformUI.Key, args.Performer); - - var identityData = new List(); - - foreach (var consumedIdentity in userIdentity.ConsumedIdentities) - { - identityData.Add(GetNetEntity(consumedIdentity)); - } - - _uiSystem.SetUiState((ent, userInterfaceComp), TransformUI.Key, new ChangelingTransformBoundUserInterfaceState(identityData)); + _uiSystem.OpenUi((ent, userInterfaceComp), ChangelingTransformUiKey.Key, args.Performer); } //TODO: Can add a Else here with TransformInto and CloseUI to make a quick switch, // issue right now is that Radials cover the Action buttons so clicking the action closes the UI (due to clicking off a radial causing it to close, even with UI) // but pressing the number does. @@ -108,7 +99,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem else _adminLogger.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(ent.Owner):player} begun an attempt to transform into \"{Name(targetIdentity)}\""); - var result = _doAfterSystem.TryStartDoAfter(new DoAfterArgs( + _doAfterSystem.TryStartDoAfter(new DoAfterArgs( EntityManager, ent, ent.Comp.TransformWindup, @@ -127,7 +118,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem private void OnTransformSelected(Entity ent, ref ChangelingTransformIdentitySelectMessage args) { - _uiSystem.CloseUi(ent.Owner, TransformUI.Key, ent); + _uiSystem.CloseUi(ent.Owner, ChangelingTransformUiKey.Key, ent); if (!TryGetEntity(args.TargetIdentity, out var targetIdentity)) return; diff --git a/Content.Shared/Changeling/Systems/ChangelingIdentitySystem.cs b/Content.Shared/Changeling/Systems/SharedChangelingIdentitySystem.cs similarity index 68% rename from Content.Shared/Changeling/Systems/ChangelingIdentitySystem.cs rename to Content.Shared/Changeling/Systems/SharedChangelingIdentitySystem.cs index 8467cc5702..e7e46d79a1 100644 --- a/Content.Shared/Changeling/Systems/ChangelingIdentitySystem.cs +++ b/Content.Shared/Changeling/Systems/SharedChangelingIdentitySystem.cs @@ -2,7 +2,6 @@ using Content.Shared.Changeling.Components; using Content.Shared.Cloning; using Content.Shared.Humanoid; -using Content.Shared.Mind.Components; using Content.Shared.NameModifier.EntitySystems; using Robust.Shared.GameStates; using Robust.Shared.Map; @@ -12,7 +11,7 @@ using Robust.Shared.Prototypes; namespace Content.Shared.Changeling.Systems; -public sealed class ChangelingIdentitySystem : EntitySystem +public abstract class SharedChangelingIdentitySystem : EntitySystem { [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; @@ -32,22 +31,19 @@ public sealed class ChangelingIdentitySystem : EntitySystem SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnShutdown); - SubscribeLocalEvent(OnMindAdded); - SubscribeLocalEvent(OnMindRemoved); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnStoredRemove); } - private void OnMindAdded(Entity ent, ref MindAddedMessage args) + private void OnPlayerAttached(Entity ent, ref PlayerAttachedEvent args) { - if (!TryComp(args.Container.Owner, out var actor)) - return; - - HandOverPvsOverride(actor.PlayerSession, ent.Comp); + HandOverPvsOverride(ent, args.Player); } - private void OnMindRemoved(Entity ent, ref MindRemovedMessage args) + private void OnPlayerDetached(Entity ent, ref PlayerDetachedEvent args) { - CleanupPvsOverride(ent, args.Container.Owner); + CleanupPvsOverride(ent, args.Player); } private void OnMapInit(Entity ent, ref MapInitEvent args) @@ -59,7 +55,8 @@ public sealed class ChangelingIdentitySystem : EntitySystem private void OnShutdown(Entity ent, ref ComponentShutdown args) { - CleanupPvsOverride(ent, ent.Owner); + if (TryComp(ent, out var actor)) + CleanupPvsOverride(ent, actor.PlayerSession); CleanupChangelingNullspaceIdentities(ent); } @@ -107,66 +104,63 @@ public sealed class ChangelingIdentitySystem : EntitySystem // Movercontrollers and mob collisions are currently being calculated even for paused entities. // Spawning all of them in the same spot causes severe performance problems. // Cryopods and Polymorph have the same problem. - var mob = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value)); + var clone = Spawn(speciesPrototype.Prototype, new MapCoordinates(new Vector2(2 * _numberOfStoredIdentities++, 0), PausedMapId!.Value)); - var storedIdentity = EnsureComp(mob); + var storedIdentity = EnsureComp(clone); storedIdentity.OriginalEntity = target; // TODO: network this once we have WeakEntityReference or the autonetworking source gen is fixed if (TryComp(target, out var actor)) storedIdentity.OriginalSession = actor.PlayerSession; - _humanoidSystem.CloneAppearance(target, mob); - _cloningSystem.CloneComponents(target, mob, settings); + _humanoidSystem.CloneAppearance(target, clone); + _cloningSystem.CloneComponents(target, clone, settings); var targetName = _nameMod.GetBaseName(target); - _metaSystem.SetEntityName(mob, targetName); - ent.Comp.ConsumedIdentities.Add(mob); + _metaSystem.SetEntityName(clone, targetName); + ent.Comp.ConsumedIdentities.Add(clone); Dirty(ent); - HandlePvsOverride(ent, mob); + HandlePvsOverride(ent, clone); - return mob; + return clone; } /// - /// Simple helper to add a PVS override to a Nullspace Identity + /// Simple helper to add a PVS override to a nullspace identity. /// - /// - /// - private void HandlePvsOverride(EntityUid uid, EntityUid target) + /// The actor that should get the override. + /// The identity stored in nullspace. + private void HandlePvsOverride(EntityUid uid, EntityUid identity) { if (!TryComp(uid, out var actor)) return; - _pvsOverrideSystem.AddSessionOverride(target, actor.PlayerSession); + _pvsOverrideSystem.AddSessionOverride(identity, actor.PlayerSession); } /// - /// Cleanup all Pvs Overrides for the owner of the ChangelingIdentity + /// Cleanup all PVS overrides for the owner of the ChangelingIdentity /// - /// the Changeling itself - /// Who specifically to cleanup from, usually just the same owner, but in the case of a mindswap we want to clean up the victim - private void CleanupPvsOverride(Entity ent, EntityUid entityUid) + /// The changeling storing the identities. + /// + private void CleanupPvsOverride(Entity ent, ICommonSession session) { - if (!TryComp(entityUid, out var actor)) - return; - foreach (var identity in ent.Comp.ConsumedIdentities) { - _pvsOverrideSystem.RemoveSessionOverride(identity, actor.PlayerSession); + _pvsOverrideSystem.RemoveSessionOverride(identity, session); } } /// - /// Inform another Session of the entities stored for Transformation + /// Inform another session of the entities stored for transformation. /// - /// The Session you wish to inform - /// The Target storage of identities - public void HandOverPvsOverride(ICommonSession session, ChangelingIdentityComponent comp) + /// The changeling storing the identities. + /// The session you wish to inform. + public void HandOverPvsOverride(Entity ent, ICommonSession session) { - foreach (var entity in comp.ConsumedIdentities) + foreach (var identity in ent.Comp.ConsumedIdentities) { - _pvsOverrideSystem.AddSessionOverride(entity, session); + _pvsOverrideSystem.AddSessionOverride(identity, session); } } diff --git a/Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs b/Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs new file mode 100644 index 0000000000..47591b6eb9 --- /dev/null +++ b/Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs @@ -0,0 +1,14 @@ +using Content.Shared.Engineering.Systems; +using Content.Shared.Weapons.Melee.Balloon; + +namespace Content.Shared.Engineering.Components; + +/// +/// Implements logic to allow inflatable objects to be safely deflated by items. +/// +/// +/// The owning entity must have to implement the logic. +/// +/// +[RegisterComponent] +public sealed partial class InflatableSafeDisassemblyComponent : Component; diff --git a/Content.Shared/Engineering/Systems/DisassembleOnAltVerbSystem.cs b/Content.Shared/Engineering/Systems/DisassembleOnAltVerbSystem.cs index 150688d3d4..0c2e5398fc 100644 --- a/Content.Shared/Engineering/Systems/DisassembleOnAltVerbSystem.cs +++ b/Content.Shared/Engineering/Systems/DisassembleOnAltVerbSystem.cs @@ -19,14 +19,12 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem SubscribeLocalEvent>(AddDisassembleVerb); SubscribeLocalEvent(OnDisassembleDoAfter); } - private void AddDisassembleVerb(Entity entity, ref GetVerbsEvent args) - { - if (!args.CanInteract || !args.CanAccess || args.Hands == null) - return; + public void StartDisassembly(Entity entity, EntityUid user) + { // Doafter setup var doAfterArgs = new DoAfterArgs(EntityManager, - args.User, + user, entity.Comp.DisassembleTime, new DisassembleDoAfterEvent(), entity, @@ -35,12 +33,22 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem BreakOnMove = true, }; + _doAfter.TryStartDoAfter(doAfterArgs); + } + + private void AddDisassembleVerb(Entity entity, ref GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess || args.Hands == null) + return; + + var user = args.User; + // Actual verb stuff AlternativeVerb verb = new() { Act = () => { - _doAfter.TryStartDoAfter(doAfterArgs); + StartDisassembly(entity, user); }, Text = Loc.GetString("disassemble-system-verb-disassemble"), Priority = 2 diff --git a/Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs b/Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs new file mode 100644 index 0000000000..7852036330 --- /dev/null +++ b/Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs @@ -0,0 +1,39 @@ +using Content.Shared.Engineering.Components; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Weapons.Melee.Balloon; + +namespace Content.Shared.Engineering.Systems; + +/// +/// Implements +/// +public sealed class InflatableSafeDisassemblySystem : EntitySystem +{ + [Dependency] private readonly DisassembleOnAltVerbSystem _disassembleOnAltVerbSystem = null!; + [Dependency] private readonly SharedPopupSystem _popupSystem = null!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(InteractHandler); + } + + private void InteractHandler(Entity ent, ref InteractUsingEvent args) + { + if (args.Handled) + return; + + if (!HasComp(args.Used)) + return; + + _popupSystem.PopupPredicted( + Loc.GetString("inflatable-safe-disassembly", ("item", args.Used), ("target", ent.Owner)), + ent, + args.User); + + _disassembleOnAltVerbSystem.StartDisassembly((ent, Comp(ent)), args.User); + args.Handled = true; + } +} diff --git a/Content.Shared/Lathe/LatheComponent.cs b/Content.Shared/Lathe/LatheComponent.cs index 8b701ff64e..7bd7764514 100644 --- a/Content.Shared/Lathe/LatheComponent.cs +++ b/Content.Shared/Lathe/LatheComponent.cs @@ -26,10 +26,14 @@ namespace Content.Shared.Lathe // Otherwise the material arbitrage test and/or LatheSystem.GetAllBaseRecipes needs to be updated /// - /// The lathe's construction queue + /// The lathe's construction queue. /// + /// + /// This is a LinkedList to allow for constant time insertion/deletion (vs a List), and more efficient + /// moves (vs a Queue). + /// [DataField] - public Queue> Queue = new(); + public LinkedList Queue = new(); /// /// The sound that plays when the lathe is producing an item, if any @@ -97,6 +101,21 @@ namespace Content.Shared.Lathe } } + [Serializable] + public sealed partial class LatheRecipeBatch + { + public ProtoId Recipe; + public int ItemsPrinted; + public int ItemsRequested; + + public LatheRecipeBatch(ProtoId recipe, int itemsPrinted, int itemsRequested) + { + Recipe = recipe; + ItemsPrinted = itemsPrinted; + ItemsRequested = itemsRequested; + } + } + /// /// Event raised on a lathe when it starts producing a recipe. /// diff --git a/Content.Shared/Lathe/LatheMessages.cs b/Content.Shared/Lathe/LatheMessages.cs index 1c1c6440f1..fe72eed367 100644 --- a/Content.Shared/Lathe/LatheMessages.cs +++ b/Content.Shared/Lathe/LatheMessages.cs @@ -10,11 +10,11 @@ public sealed class LatheUpdateState : BoundUserInterfaceState { public List> Recipes; - public ProtoId[] Queue; + public LatheRecipeBatch[] Queue; public ProtoId? CurrentlyProducing; - public LatheUpdateState(List> recipes, ProtoId[] queue, ProtoId? currentlyProducing = null) + public LatheUpdateState(List> recipes, LatheRecipeBatch[] queue, ProtoId? currentlyProducing = null) { Recipes = recipes; Queue = queue; @@ -46,6 +46,33 @@ public sealed class LatheQueueRecipeMessage : BoundUserInterfaceMessage } } +/// +/// Sent to the server to remove a batch from the queue. +/// +[Serializable, NetSerializable] +public sealed class LatheDeleteRequestMessage(int index) : BoundUserInterfaceMessage +{ + public int Index = index; +} + +/// +/// Sent to the server to move the position of a batch in the queue. +/// +[Serializable, NetSerializable] +public sealed class LatheMoveRequestMessage(int index, int change) : BoundUserInterfaceMessage +{ + public int Index = index; + public int Change = change; +} + +/// +/// Sent to the server to stop producing the current item. +/// +[Serializable, NetSerializable] +public sealed class LatheAbortFabricationMessage() : BoundUserInterfaceMessage +{ +} + [NetSerializable, Serializable] public enum LatheUiKey { diff --git a/Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs b/Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs new file mode 100644 index 0000000000..1c616ff105 --- /dev/null +++ b/Content.Shared/Lathe/PrototypeIdLinkedListSerializer.cs @@ -0,0 +1,81 @@ +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.Manager; +using Robust.Shared.Serialization.Markdown; +using Robust.Shared.Serialization.Markdown.Sequence; +using Robust.Shared.Serialization.Markdown.Validation; +using Robust.Shared.Serialization.TypeSerializers.Interfaces; + +namespace Content.Shared.Lathe; + +/// +/// Handles reading, writing, and validation for linked lists of prototypes. +/// +/// The type of prototype this linked list represents +/// +/// This is in the Content.Shared.Lathe namespace as there are no other LinkedList ProtoId instances. +/// +[TypeSerializer] +public sealed class LinkedListSerializer : ITypeSerializer, SequenceDataNode>, ITypeCopier> where T : class +{ + public ValidationNode Validate(ISerializationManager serializationManager, SequenceDataNode node, + IDependencyCollection dependencies, ISerializationContext? context = null) + { + var list = new List(); + + foreach (var elem in node.Sequence) + { + list.Add(serializationManager.ValidateNode(elem, context)); + } + + return new ValidatedSequenceNode(list); + } + + public DataNode Write(ISerializationManager serializationManager, LinkedList value, + IDependencyCollection dependencies, + bool alwaysWrite = false, + ISerializationContext? context = null) + { + var sequence = new SequenceDataNode(); + + foreach (var elem in value) + { + sequence.Add(serializationManager.WriteValue(elem, alwaysWrite, context)); + } + + return sequence; + } + + LinkedList ITypeReader, SequenceDataNode>.Read(ISerializationManager serializationManager, + SequenceDataNode node, + IDependencyCollection dependencies, + SerializationHookContext hookCtx, + ISerializationContext? context, ISerializationManager.InstantiationDelegate>? instanceProvider) + { + var list = instanceProvider != null ? instanceProvider() : new LinkedList(); + + foreach (var dataNode in node.Sequence) + { + list.AddLast(serializationManager.Read(dataNode, hookCtx, context)); + } + + return list; + } + + public void CopyTo( + ISerializationManager serializationManager, + LinkedList source, + ref LinkedList target, + IDependencyCollection dependencies, + SerializationHookContext hookCtx, + ISerializationContext? context = null) + { + target.Clear(); + using var enumerator = source.GetEnumerator(); + + while (enumerator.MoveNext()) + { + var current = enumerator.Current; + target.AddLast(current); + } + } +} diff --git a/Content.Shared/Lathe/SharedLatheSystem.cs b/Content.Shared/Lathe/SharedLatheSystem.cs index 524d83fd84..5942f4bf6c 100644 --- a/Content.Shared/Lathe/SharedLatheSystem.cs +++ b/Content.Shared/Lathe/SharedLatheSystem.cs @@ -22,6 +22,7 @@ public abstract class SharedLatheSystem : EntitySystem [Dependency] private readonly EmagSystem _emag = default!; public readonly Dictionary> InverseRecipes = new(); + public const int MaxItemsPerRequest = 10_000; public override void Initialize() { @@ -86,6 +87,8 @@ public abstract class SharedLatheSystem : EntitySystem return false; if (!HasRecipe(uid, recipe, component)) return false; + if (amount <= 0) + return false; foreach (var (material, needed) in recipe.Materials) { diff --git a/Content.Shared/Trigger/Components/Effects/AddGameRuleOnTriggerComponent.cs b/Content.Shared/Trigger/Components/Effects/AddGameRuleOnTriggerComponent.cs new file mode 100644 index 0000000000..474272694c --- /dev/null +++ b/Content.Shared/Trigger/Components/Effects/AddGameRuleOnTriggerComponent.cs @@ -0,0 +1,26 @@ +using Content.Shared.GameTicking.Components; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Trigger.Components.Effects; + +/// +/// Adds and starts a new game rule on a trigger. +/// The user is always logged alongside the game rule and this entity. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class AddGameRuleOnTriggerComponent : BaseXOnTriggerComponent +{ + /// + /// The game rule that will be added. Entity requires . + /// + [DataField(required: true), AutoNetworkedField] + public EntProtoId GameRule; + + /// + /// Whether to also start the game rule when adding it. + /// You almost always want this to be true. + /// + [DataField, AutoNetworkedField] + public bool StartRule = true; +} diff --git a/Content.Server/Weapons/Melee/Balloon/BalloonPopperComponent.cs b/Content.Shared/Weapons/Melee/Balloon/BalloonPopperComponent.cs similarity index 94% rename from Content.Server/Weapons/Melee/Balloon/BalloonPopperComponent.cs rename to Content.Shared/Weapons/Melee/Balloon/BalloonPopperComponent.cs index e7f318d61c..7e90b2b4ea 100644 --- a/Content.Server/Weapons/Melee/Balloon/BalloonPopperComponent.cs +++ b/Content.Shared/Weapons/Melee/Balloon/BalloonPopperComponent.cs @@ -2,7 +2,7 @@ using Robust.Shared.Audio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.Weapons.Melee.Balloon; +namespace Content.Shared.Weapons.Melee.Balloon; /// /// This is used for weapons that pop balloons on attack. diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 35561495d8..4ece01fac9 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.CombatMode; using Content.Shared.Containers.ItemSlots; using Content.Shared.Damage; using Content.Shared.Examine; -using Content.Shared.Gravity; using Content.Shared.Hands; using Content.Shared.Hands.EntitySystems; using Content.Shared.Hands.Components; @@ -34,7 +33,6 @@ using Robust.Shared.Containers; using Robust.Shared.Input.Binding; using Robust.Shared.Map; using Robust.Shared.Network; -using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; @@ -65,7 +63,6 @@ public abstract partial class SharedGunSystem : EntitySystem [Dependency] protected readonly SharedAudioSystem Audio = default!; [Dependency] private readonly SharedCombatModeSystem _combatMode = default!; [Dependency] protected readonly SharedContainerSystem Containers = default!; - [Dependency] private readonly SharedGravitySystem _gravity = default!; [Dependency] protected readonly SharedPointLightSystem Lights = default!; [Dependency] protected readonly SharedPopupSystem PopupSystem = default!; [Dependency] protected readonly SharedPhysicsSystem Physics = default!; diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 83363a83bc..fc3f0e933b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,27 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Tweak mob collision values in line with RMC14. - type: Tweak - id: 8367 - time: '2025-04-27T14:47:18.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/36851 -- author: Fildrance - changes: - - message: node scanner now dislplays live artifact info (while in range) after - linking to artifact - type: Tweak - id: 8368 - time: '2025-04-27T15:11:13.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/36635 -- author: ArtisticRoomba - changes: - - message: A new Mapping changelog has been added. You can find it in a different - "Mapping" tab under the changelog menu. - type: Add - id: 8369 - time: '2025-04-27T20:15:17.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/34848 - author: ScarKy0 changes: - message: Deliveries can now spawn as fragile-type! Deliver them intact to earn @@ -3948,3 +3925,26 @@ id: 8879 time: '2025-08-22T22:26:48.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/39834 +- author: _miket, RedBookcase + changes: + - message: Added new Derelict Cyborg ghost roles, including the Derelict Engineer, + Janitor, Salvage, Medical, and Assault Cyborg! + type: Add + id: 8880 + time: '2025-08-23T20:32:15.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/38159 +- author: FungiFellow + changes: + - message: Added the Inflatable Module for borgs. + type: Add + id: 8881 + time: '2025-08-23T22:15:28.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/35100 +- author: whatston3 + changes: + - message: Lathes now batch items into jobs, which can be moved around in priority + or deleted. + type: Add + id: 8882 + time: '2025-08-24T15:02:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/38624 diff --git a/Resources/Changelog/Maps.yml b/Resources/Changelog/Maps.yml index 0ec3640252..ba943e2221 100644 --- a/Resources/Changelog/Maps.yml +++ b/Resources/Changelog/Maps.yml @@ -551,4 +551,11 @@ id: 67 time: '2025-08-18T18:22:15.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/39091 +- author: M4rchy-S + changes: + - message: On Marathon, fixed the reagent grinder in perma not having power. + type: Fix + id: 68 + time: '2025-08-23T22:48:39.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/39801 Order: 1 diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 7526e5ac03..7c6bca9005 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0leshe, 0tito, 0x6273, 12rabbits, 1337dakota, 13spacemen, 154942, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, 96flo, aaron, abadaba695, Ablankmann, abregado, Absolute-Potato, Absotively, achookh, Acruid, ActiveMammmoth, actually-reb, ada-please, adamsong, Adeinitas, adm2play, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aearo-Deepwater, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, AgentSmithRadio, Agoichi, Ahion, aiden, Aidenkrz, Aisu9, ajcm, AJCM-git, AjexRose, Alekshhh, alex, alexalexmax, alexkar598, AlexMorgan3817, alexum418, alexumandxgabriel08x, Alice4267, Alithsko, Alkheemist, alliephante, ALMv1, Alpaccalypse, Alpha-Two, AlphaQwerty, Altoids1, amatwiedle, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, ApolloVector, Appiah, ar4ill, Arcane-Waffle, archee1, ArchPigeon, ArchRBX, areitpog, Arendian, areyouconfused, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, Artxmisery, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, AverageNotDoingAnythingEnjoyer, avghdev, Awlod, azzyisnothere, AzzyIsNotHere, B-Kirill, B3CKDOOR, baa14453, BackeTako, Bakke, BananaFlambe, Baptr0b0t, BarryNorfolk, BasedUser, beck-thompson, beesterman, bellwetherlogic, ben, benbryant0, benev0, benjamin-burges, BGare, bhespiritu, bibbly, BigfootBravo, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blitzthesquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, Bokser815, bolantej, Booblesnoot42, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, BWTCK, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, Camdot, capnsockless, CaptainMaru, captainsqrbeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, catdotjs, catlord, Catofquestionableethics, CatTheSystem, Centronias, Chaboricks, chairbender, Chaoticaa, Charlese2, charlie, chartman, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, CheesePlated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, ciaran, citrea, civilCornball, claustro305, Clement-O, clyf, Clyybber, CMDR-Piboy314, cnv41, coco, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, Compilatron144, CookieMasterT, coolboy911, CoolioDudio, coolmankid12345, Coolsurf6, cooperwallace, corentt, CormosLemming, CrafterKolyan, crazybrain23, Crazydave91920, creadth, CrigCrag, CroilBird, Crotalus, CrudeWax, cryals, CrzyPotato, cubixthree, cutemoongod, Cyberboss, d34d10cc, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, dan, dangerrevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, DeepwaterCreations, Deerstop, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, devinschubert14, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinnerCalzone, DinoWattz, Disp-Dev, DisposableCrewmember42, dissidentbullet, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, DR-DOCTOR-EVIL-EVIL, Dragonjspider, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, DuckManZach, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, dylanstrategie, dylanwhittingham, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, EnrichedCaramel, Entvari, eoineoineoin, ephememory, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, farrellka-dev, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, Firewars763, FirinMaLazors, Fishfish458, fl-oz, Flareguy, flashgnash, FlipBrooke, FluffiestFloof, FluffMe, FluidRock, flymo5678, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, foxhorn, freeman2651, freeze2222, frobnic8, Froffy025, Fromoriss, froozigiusz, FrostMando, FrostRibbon, Funce, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gamewar360, gansulalan, GaussiArson, Gaxeer, gbasood, gcoremans, Geekyhobo, genderGeometries, GeneralGaws, Genkail, Gentleman-Bird, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GnarpGnarp, GNF54, godisdeadLOL, goet, GoldenCan, Goldminermac, Golinth, golubgik, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GrownSamoyedDog, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Helix-ctrl, helm4142, Henry, HerCoyote23, HighTechPuddle, Hitlinemoss, hiucko, hivehum, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hoshizora, Hreno, Hrosts, htmlsystem, hubismal, Hugal31, Huxellberger, Hyenh, hyperb1, hyperDelegate, hyphenationc, i-justuser-i, iaada, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imatsoup, IMCB, impubbi, imrenq, imweax, indeano, Injazz, Insineer, insoPL, IntegerTempest, Interrobang01, Intoxicating-Innocence, IProduceWidgets, itsmethom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jacktastic09, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, jbox144, JCGWE30, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jkwookee, jmcb, JohnGinnane, johnku1, Jophire, joshepvodka, JpegOfAFrog, jproads, JrInventor05, Jrpl, jukereise, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, JustinWinningham, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, kaiserbirch, KaiShibaa, kalane15, kalanosh, KamTheSythe, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, KieueCaprie, Killerqu00, Kimpes, KingFroozy, kira-er, kiri-yoshikage, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, Kittygyat, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kontakt, kosticia, koteq, kotobdev, Kowlin, KrasnoshchekovPavel, Krosus777, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, LaCumbiaDelCoronavirus, lajolico, Lamrr, lanedon, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, lettern, LetterN, Level10Cybermancer, LEVELcat, lever1209, LevitatingTree, Lgibb18, lgruthes, LightVillet, liltenhead, linkbro1, LinkUyx, Litraxx, little-meow-meow, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, ljm862, lmsnoise, localcc, lokachop, lolman360, Lomcastar, LordCarve, LordEclipse, lucas, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, Lusatia, Luxeator, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M1tht1c, M3739, M87S, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, maland1, malchanceux, MaloTV, manelnavola, ManelNavola, Mangohydra, marboww, Markek1, marlyn, matt, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, memeproof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, mifia, MilenVolf, MilonPL, Minemoder5000, Minty642, minus1over12, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterImp, MisterMecky, Mith-randalf, Mixelz, mjarduk, MjrLandWhale, mkanke-real, MLGTASTICa, mnva0, moderatelyaware, modern-nm, mokiros, momo, Moneyl, monotheonist, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, murolem, musicmanvr, MWKane, Myakot, Myctai, N3X15, nabegator, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikitosych, nikthechampiongr, Nimfar11, ninruB, Nirnael, NIXC, nkokic, NkoKirkto, nmajask, noctyrnal, noelkathegod, noirogen, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, Nox38, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, Nyxilath, och-och, OctoRocket, OldDanceJacket, OliverOtter, onesch, OneZerooo0, OnyxTheBrave, Orange-Winds, OrangeMoronage9622, Orsoniks, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paige404, paigemaeforrest, pali6, Palladinium, Pangogie, panzer-iv1, partyaddict, patrikturi, PaulRitter, pavlockblaine03, peccneck, Peptide90, peptron1, perryprog, PeterFuto, PetMudstone, pewter-wiz, PGrayCS, pgraycs, Pgriha, Phantom-Lily, pheenty, philingham, Phill101, Phooooooooooooooooooooooooooooooosphate, phunnyguy, PicklOH, PilgrimViis, Pill-U, pinkbat5, Piras314, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, poklj, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, PotRoastPiggy, Princess-Cheeseballs, ProfanedBane, PROG-MohamedDwidar, Prole0, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykana, psykzz, PuceTint, pumkin69, PuroSlavKing, PursuitInAshes, Putnam3145, py01, Pyrovi, qrtDaniil, qrwas, Quantum-cross, quatre, QueerNB, QuietlyWhisper, qwerltaz, Radezolid, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, ReeZer2, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rhsvenson, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, rlebell33, RobbyTheFish, robinthedragon, Rockdtben, Rohesie, rok-povsic, rokudara-sen, rolfero, RomanNovo, rosieposieeee, Roudenn, router, ruddygreat, rumaks, RumiTiger, Ruzihm, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, Samuka-C, SaphireLattice, SapphicOverload, sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, ScholarNZL, schrodinger71, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, SeamLesss, Segonist, semensponge, sephtasm, ser1-1y, Serkket, sewerpig, SG6732, sh18rw, Shaddap1, ShadeAware, ShadowCommander, shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SharkSnake98, shibechef, Siginanto, SignalWalker, siigiil, silicon14wastaken, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skybailey-dev, Skyedra, SlamBamActionman, slarticodefast, Slava0135, sleepyyapril, slimmslamm, Slyfox333, Smugman, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, solstar2, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, soupkilove, southbridge-fur, sowelipililimute, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, Spangs04, spanky-spanky, Sparlight, spartak, SpartanKadence, spderman3333, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, starbuckss14, Stealthbomber16, stellar-novas, stewie523, stomf, Stop-Signs, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, supergdpwyl, superjj18, Supernorn, SweptWasTaken, SyaoranFox, Sybil, SYNCHRONIC, Szunti, t, Tainakov, takemysoult, taonewt, tap, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TeenSarlacc, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, Tezzaide, TGODiamond, TGRCdev, tgrkzus, ThatGuyUSA, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, TheBlueYowie, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheFlyingSentry, TheIntoxicatedCat, thekilk, themias, theomund, TheProNoob678, TherapyGoth, ThereDrD0, TheShuEd, thetolbean, thevinter, TheWaffleJesus, thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, TiniestShark, Titian3, tk-a369, tkdrg, tmtmtl30, ToastEnjoyer, Toby222, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, tornado-technology, TornadoTechnology, tosatur, TotallyLemon, ToxicSonicFan04, Tr1bute, treytipton, trixxedbit, TrixxedHeart, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, tyashley, Tyler-IN, TytosB, Tyzemol, UbaserB, ubis1, UBlueberry, uhbg, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, unusualcrow, Uriende, UristMcDorf, user424242420, Utmanarn, Vaaankas, valentfingerov, valquaint, Varen, Vasilis, VasilisThePikachu, veliebm, Velken, VelonacepsCalyxEggs, veprolet, VerinSenpai, veritable-calamity, Veritius, Vermidia, vero5123, verslebas, vexerot, viceemargo, VigersRay, violet754, Visne, vitusveit, vlad, vlados1408, VMSolidus, vmzd, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, Vortebo, vulppine, wafehling, walksanatora, Warentan, WarMechanic, Watermelon914, weaversam8, wertanchik, whateverusername0, whatston3, widgetbeck, Will-Oliver-Br, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, Wolfkey-SomeoneElseTookMyUsername, wrexbe, wtcwr68, xeri7, xkreksx, xprospero, xRiriq, xsainteer, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, YoungThugSS14, Yousifb26, youtissoum, yunii, yuriykiss, YuriyKiss, zach-hill, Zadeon, Zalycon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, ZeWaka, zHonys, zionnBE, ZNixian, Zokkie, ZoldorfTheWizard, zonespace27, Zylofan, Zymem, zzylex +0leshe, 0tito, 0x6273, 12rabbits, 1337dakota, 13spacemen, 154942, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, 96flo, aaron, abadaba695, Ablankmann, abregado, Absolute-Potato, Absotively, achookh, Acruid, ActiveMammmoth, actually-reb, ada-please, adamsong, Adeinitas, adm2play, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aearo-Deepwater, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, afrokada, AftrLite, AgentSmithRadio, Agoichi, Ahion, aiden, Aidenkrz, Aisu9, ajcm, AJCM-git, AjexRose, Alekshhh, alex, alexalexmax, alexkar598, AlexMorgan3817, alexum418, alexumandxgabriel08x, Alice4267, Alithsko, Alkheemist, alliephante, ALMv1, Alpaccalypse, Alpha-Two, AlphaQwerty, Altoids1, amatwiedle, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, ApolloVector, Appiah, ar4ill, Arcane-Waffle, archee1, ArchPigeon, ArchRBX, areitpog, Arendian, areyouconfused, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, Artxmisery, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, AverageNotDoingAnythingEnjoyer, avghdev, Awlod, azzyisnothere, AzzyIsNotHere, B-Kirill, B3CKDOOR, baa14453, BackeTako, BadaBoomie, Bakke, BananaFlambe, Baptr0b0t, BarryNorfolk, BasedUser, beck-thompson, beesterman, bellwetherlogic, ben, benbryant0, benev0, benjamin-burges, BGare, bhespiritu, bibbly, BigfootBravo, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, blitzthesquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, Bokser815, bolantej, Booblesnoot42, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, BWTCK, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, Camdot, capnsockless, CaptainMaru, captainsqrbeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, catdotjs, catlord, Catofquestionableethics, CatTheSystem, Centronias, Chaboricks, chairbender, Chaoticaa, Charlese2, charlie, chartman, ChaseFlorom, chavonadelal, Cheackraze, CheddaCheez, cheesePizza2, CheesePlated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, ciaran, citrea, civilCornball, claustro305, Clement-O, clyf, Clyybber, CMDR-Piboy314, cnv41, coco, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, Compilatron144, CookieMasterT, coolboy911, CoolioDudio, coolmankid12345, Coolsurf6, cooperwallace, corentt, CormosLemming, CrafterKolyan, crazybrain23, Crazydave91920, creadth, CrigCrag, CroilBird, Crotalus, CrudeWax, cryals, CrzyPotato, cubixthree, cutemoongod, Cyberboss, d34d10cc, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, dan, dangerrevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, DeepwaterCreations, Deerstop, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, devinschubert14, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinnerCalzone, DinoWattz, Disp-Dev, DisposableCrewmember42, dissidentbullet, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, DR-DOCTOR-EVIL-EVIL, Dragonjspider, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, DuckManZach, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, dylanstrategie, dylanwhittingham, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, EnrichedCaramel, Entvari, eoineoineoin, ephememory, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, farrellka-dev, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, Firewars763, FirinMaLazors, Fishfish458, fl-oz, Flareguy, flashgnash, FlipBrooke, FluffiestFloof, FluffMe, FluidRock, flymo5678, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, foxhorn, freeman2651, freeze2222, frobnic8, Froffy025, Fromoriss, froozigiusz, FrostMando, FrostRibbon, Funce, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gamewar360, gansulalan, GaussiArson, Gaxeer, gbasood, gcoremans, Geekyhobo, genderGeometries, GeneralGaws, Genkail, Gentleman-Bird, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GnarpGnarp, GNF54, godisdeadLOL, goet, GoldenCan, Goldminermac, Golinth, golubgik, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GrownSamoyedDog, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Helix-ctrl, helm4142, Henry, HerCoyote23, HighTechPuddle, Hitlinemoss, hiucko, hivehum, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hoshizora, Hreno, Hrosts, htmlsystem, hubismal, Hugal31, Huxellberger, Hyenh, hyperb1, hyperDelegate, hyphenationc, i-justuser-i, iaada, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imatsoup, IMCB, impubbi, imrenq, imweax, indeano, Injazz, Insineer, insoPL, IntegerTempest, Interrobang01, Intoxicating-Innocence, IProduceWidgets, itsmethom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jacktastic09, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, jbox144, JCGWE30, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jkwookee, jmcb, JohnGinnane, johnku1, Jophire, joshepvodka, JpegOfAFrog, jproads, JrInventor05, Jrpl, jukereise, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, JustinWinningham, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, kaiserbirch, KaiShibaa, kalane15, kalanosh, KamTheSythe, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, KieueCaprie, Killerqu00, Kimpes, KingFroozy, kira-er, kiri-yoshikage, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, Kittygyat, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kontakt, kosticia, koteq, kotobdev, Kowlin, KrasnoshchekovPavel, Krosus777, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, LaCumbiaDelCoronavirus, lajolico, Lamrr, lanedon, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonidussaks, leonsfriedrich, LeoSantich, lettern, LetterN, Level10Cybermancer, LEVELcat, lever1209, LevitatingTree, Lgibb18, lgruthes, LightVillet, liltenhead, linkbro1, LinkUyx, Litraxx, little-meow-meow, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, ljm862, lmsnoise, localcc, lokachop, lolman360, Lomcastar, LordCarve, LordEclipse, lucas, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, Lusatia, Luxeator, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M1tht1c, M3739, M4rchy-S, M87S, mac6na6na, MACMAN2003, Macoron, magicalus, magmodius, MagnusCrowe, maland1, malchanceux, MaloTV, manelnavola, ManelNavola, Mangohydra, marboww, Markek1, MarkerWicker, marlyn, matt, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, memeproof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, mifia, MilenVolf, MilonPL, Minemoder5000, Minty642, minus1over12, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterImp, MisterMecky, Mith-randalf, Mixelz, mjarduk, MjrLandWhale, mkanke-real, MLGTASTICa, mnva0, moderatelyaware, modern-nm, mokiros, momo, Moneyl, monotheonist, Moomoobeef, moony, Morb0, MossyGreySlope, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, murolem, musicmanvr, MWKane, Myakot, Myctai, N3X15, nabegator, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikitosych, nikthechampiongr, Nimfar11, ninruB, Nirnael, NIXC, nkokic, NkoKirkto, nmajask, noctyrnal, noelkathegod, noirogen, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, Nox38, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, Nyxilath, och-och, OctoRocket, OldDanceJacket, OliverOtter, onesch, OneZerooo0, OnyxTheBrave, Orange-Winds, OrangeMoronage9622, Orsoniks, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paige404, paigemaeforrest, pali6, Palladinium, Pangogie, panzer-iv1, partyaddict, patrikturi, PaulRitter, pavlockblaine03, peccneck, Peptide90, peptron1, perryprog, PeterFuto, PetMudstone, pewter-wiz, pgraycs, PGrayCS, Pgriha, Phantom-Lily, pheenty, philingham, Phill101, Phooooooooooooooooooooooooooooooosphate, phunnyguy, PicklOH, PilgrimViis, Pill-U, pinkbat5, Piras314, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, poklj, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, PotRoastPiggy, Princess-Cheeseballs, ProfanedBane, PROG-MohamedDwidar, Prole0, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykana, psykzz, PuceTint, pumkin69, PuroSlavKing, PursuitInAshes, Putnam3145, py01, Pyrovi, qrtDaniil, qrwas, Quantum-cross, quatre, QueerNB, QuietlyWhisper, qwerltaz, Radezolid, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, RedBookcase, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, ReeZer2, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rhsvenson, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, rlebell33, RobbyTheFish, robinthedragon, Rockdtben, Rohesie, rok-povsic, rokudara-sen, rolfero, RomanNovo, rosieposieeee, Roudenn, router, ruddygreat, rumaks, RumiTiger, Ruzihm, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, Samuka-C, SaphireLattice, SapphicOverload, sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, ScholarNZL, schrodinger71, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, SeamLesss, Segonist, semensponge, sephtasm, ser1-1y, Serkket, sewerpig, SG6732, sh18rw, Shaddap1, ShadeAware, ShadowCommander, shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SharkSnake98, shibechef, Siginanto, SignalWalker, siigiil, silicon14wastaken, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skybailey-dev, Skyedra, SlamBamActionman, slarticodefast, Slava0135, sleepyyapril, slimmslamm, Slyfox333, Smugman, snebl, snicket, sniperchance, Snowni, snowsignal, SolidSyn, SolidusSnek, solstar2, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, soupkilove, southbridge-fur, sowelipililimute, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, Spangs04, spanky-spanky, Sparlight, spartak, SpartanKadence, spderman3333, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, starbuckss14, Stealthbomber16, stellar-novas, stewie523, stomf, Stop-Signs, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, supergdpwyl, superjj18, Supernorn, SweptWasTaken, SyaoranFox, Sybil, SYNCHRONIC, Szunti, t, Tainakov, takemysoult, taonewt, tap, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TeenSarlacc, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, Tezzaide, TGODiamond, TGRCdev, tgrkzus, ThatGuyUSA, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, TheBlueYowie, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheFlyingSentry, TheIntoxicatedCat, thekilk, themias, theomund, TheProNoob678, TherapyGoth, ThereDrD0, TheShuEd, thetolbean, thevinter, TheWaffleJesus, thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, TiniestShark, Titian3, tk-a369, tkdrg, tmtmtl30, ToastEnjoyer, Toby222, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, tornado-technology, TornadoTechnology, tosatur, TotallyLemon, ToxicSonicFan04, Tr1bute, treytipton, trixxedbit, TrixxedHeart, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, tyashley, Tyler-IN, TytosB, Tyzemol, UbaserB, ubis1, UBlueberry, uhbg, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, unusualcrow, Uriende, UristMcDorf, user424242420, Utmanarn, Vaaankas, valentfingerov, valquaint, Varen, Vasilis, VasilisThePikachu, veliebm, Velken, VelonacepsCalyxEggs, veprolet, VerinSenpai, veritable-calamity, Veritius, Vermidia, vero5123, verslebas, vexerot, viceemargo, VigersRay, violet754, Visne, vitusveit, vlad, vlados1408, VMSolidus, vmzd, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, Vortebo, vulppine, wafehling, walksanatora, Warentan, WarMechanic, Watermelon914, weaversam8, wertanchik, whateverusername0, whatston3, widgetbeck, Will-Oliver-Br, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, Wolfkey-SomeoneElseTookMyUsername, wrexbe, wtcwr68, xeri7, xkreksx, xprospero, xRiriq, xsainteer, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, YoungThugSS14, Yousifb26, youtissoum, yunii, yuriykiss, YuriyKiss, zach-hill, Zadeon, Zalycon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, ZeWaka, zHonys, zionnBE, ZNixian, Zokkie, ZoldorfTheWizard, zonespace27, Zylofan, Zymem, zzylex diff --git a/Resources/Locale/en-US/_strings/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/_strings/ghost/roles/ghost-role-component.ftl index de92116fd2..f478ada429 100644 --- a/Resources/Locale/en-US/_strings/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/_strings/ghost/roles/ghost-role-component.ftl @@ -251,9 +251,24 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them. -ghost-role-information-derelict-cyborg-name = Derelict Cyborg +ghost-role-information-derelict-engineering-cyborg-name = Derelict Engineer Cyborg +ghost-role-information-derelict-engineering-cyborg-description = You are an engineer cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. + +ghost-role-information-derelict-cyborg-name = Derelict Generic Cyborg ghost-role-information-derelict-cyborg-description = You are a regular cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. +ghost-role-information-derelict-janitor-cyborg-name = Derelict Janitor Cyborg +ghost-role-information-derelict-janitor-cyborg-description = You are a janitor cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. + +ghost-role-information-derelict-medical-cyborg-name = Derelict Medical Cyborg +ghost-role-information-derelict-medical-cyborg-description = You are a medical cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. + +ghost-role-information-derelict-mining-cyborg-name = Derelict Salvage Cyborg +ghost-role-information-derelict-mining-cyborg-description = You are a salvage cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. + +ghost-role-information-derelict-syndicate-assault-cyborg-name = Derelict Syndicate Assault Cyborg +ghost-role-information-derelict-syndicate-assault-cyborg-description = You are an early model syndicate assault cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station. + ghost-role-information-security-name = Security ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation... diff --git a/Resources/Locale/en-US/_strings/lathe/ui/lathe-menu.ftl b/Resources/Locale/en-US/_strings/lathe/ui/lathe-menu.ftl index 076a70447c..c04c095162 100644 --- a/Resources/Locale/en-US/_strings/lathe/ui/lathe-menu.ftl +++ b/Resources/Locale/en-US/_strings/lathe/ui/lathe-menu.ftl @@ -29,3 +29,9 @@ lathe-menu-silo-linked-message = Silo Linked lathe-menu-fabricating-message = Fabricating... lathe-menu-materials-title = Materials lathe-menu-queue-title = Build Queue +lathe-menu-delete-fabricating-tooltip = Cancel printing the current item. +lathe-menu-delete-item-tooltip = Cancel printing this batch. +lathe-menu-move-up-tooltip = Move this batch ahead in the queue. +lathe-menu-move-down-tooltip = Move this batch back in the queue. +lathe-menu-item-single = {$index}. {$name} +lathe-menu-item-batch = {$index}. {$name} ({$printed}/{$total}) diff --git a/Resources/Locale/en-US/_strings/robotics/borg_modules.ftl b/Resources/Locale/en-US/_strings/robotics/borg_modules.ftl index b6c55447e7..ba5ee602a5 100644 --- a/Resources/Locale/en-US/_strings/robotics/borg_modules.ftl +++ b/Resources/Locale/en-US/_strings/robotics/borg_modules.ftl @@ -10,3 +10,5 @@ borg-slot-documents-empty = Books and papers borg-slot-soap-empty = Soap borg-slot-instruments-empty = Instruments borg-slot-beakers-empty = Beakers +borg-slot-inflatable-door-empty = Inflatable Door +borg-slot-inflatable-wall-empty = Inflatable Wall diff --git a/Resources/Locale/en-US/engineering/inflatables.ftl b/Resources/Locale/en-US/engineering/inflatables.ftl new file mode 100644 index 0000000000..0c4a2d44c0 --- /dev/null +++ b/Resources/Locale/en-US/engineering/inflatables.ftl @@ -0,0 +1 @@ +inflatable-safe-disassembly = You expertly use { THE($item) } to open the valve on { THE($target) }, and start deflating { OBJECT($target) } without causing damage. diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index 03bd492e52..0b7a4fd659 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -248,6 +248,18 @@ - sprite: Mobs/Aliens/paradox_clone.rsi state: preview +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: SpawnPointGhostDerelictCyborg + id: SpawnPointGhostDerelictEngineeringCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-engineering-cyborg-name + description: ghost-role-information-derelict-engineering-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: entity categories: [ HideSpawnMenu, Spawner ] parent: BaseAntagSpawner @@ -266,6 +278,54 @@ - sprite: Mobs/Silicon/chassis.rsi state: derelict_icon +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: SpawnPointGhostDerelictCyborg + id: SpawnPointGhostDerelictJanitorCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-janitor-cyborg-name + description: ghost-role-information-derelict-janitor-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: SpawnPointGhostDerelictCyborg + id: SpawnPointGhostDerelictMedicalCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-medical-cyborg-name + description: ghost-role-information-derelict-medical-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: SpawnPointGhostDerelictCyborg + id: SpawnPointGhostDerelictMiningCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-mining-cyborg-name + description: ghost-role-information-derelict-mining-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: SpawnPointGhostDerelictCyborg + id: SpawnPointGhostDerelictSyndicateAssaultCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-syndicate-assault-cyborg-name + description: ghost-role-information-derelict-syndicate-assault-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: entity categories: [ HideSpawnMenu, Spawner ] parent: BaseAntagSpawner diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 6981320678..1eb22fb150 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -413,6 +413,7 @@ - Syndicate - type: ActiveRadio channels: + - Binary - Syndicate - type: ShowSyndicateIcons - type: MovementAlwaysTouching @@ -460,6 +461,19 @@ chance: 1 - type: ShowJobIcons +- type: entity + id: BaseBorgChassisSyndicateDerelict #For assault borg and maybe others in time + parent: BaseBorgChassisSyndicate + abstract: true + components: + - type: SiliconLawProvider + laws: SyndicateStatic #Non-subverted version so they can still be changed + - type: StartIonStormed + ionStormAmount: 3 + - type: IonStormTarget + chance: 1 + - type: ShowJobIcons + - type: entity parent: BaseBorgChassisNotIonStormable id: BaseXenoborgChassis diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index c2d4700d97..3c359823fd 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -254,7 +254,7 @@ map: ["light"] visible: false - type: BorgChassis - maxModules: 5 # the sixth one broke lol + maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg. moduleWhitelist: tags: - BorgModuleGeneric @@ -267,3 +267,164 @@ interactFailureString: petting-failure-derelict-cyborg interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg + +- type: entity + parent: BaseBorgChassisDerelict + id: EngineeringBorgChassisDerelict + name: derelict engineer cyborg + description: A man-machine hybrid that assists the engineering department. This one seems to have chunks of strange crystals pockmarking its surface. + components: + - type: Sprite + layers: + - state: engineer_derelict + - state: engineer_e_r + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: engineer_derelict_crystal #This layer and the layer below are duplicated in order to create a more mellow unshaded layer. See https://github.com/space-wizards/space-station-14/pull/37869 for more info on the method. + shader: unshaded + - state: engineer_derelict_crystal + shader: shaded + - state: engineer_l + shader: unshaded + map: ["light"] + visible: false + - type: BorgChassis + maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg. + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleEngineering + hasMindState: engineer_e + noMindState: engineer_e_r + +- type: entity + parent: BaseBorgChassisDerelict + id: JanitorBorgChassisDerelict + name: derelict janitor cyborg + description: A man-machine hybrid that assists the service department. It's a bigger mess than anything it can clean up. + components: + - type: Sprite + layers: + - state: janitor_derelict + map: ["movement"] + - state: janitor_e_r + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: janitor_l + shader: unshaded + map: ["light"] + visible: false + - type: SpriteMovement + movementLayers: + movement: + state: janitor_moving_derelict + noMovementLayers: + movement: + state: janitor_derelict + - type: BorgChassis + maxModules: 5 # One less module slot than the regular module to reflect this being a "broken" cyborg. + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleJanitor + hasMindState: janitor_e + noMindState: janitor_e_r + +- type: entity + parent: BaseBorgChassisDerelict + id: MedicalBorgChassisDerelict + name: derelict medical cyborg + description: A man-machine hybrid that assists the medical department. This one's needles don't look very sanitary. + components: + - type: Sprite + layers: + - state: medical_derelict + map: ["movement"] + - state: medical_e_r + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: medical_l + shader: unshaded + map: ["light"] + visible: false + - type: SpriteMovement + movementLayers: + movement: + state: medical_moving_derelict + noMovementLayers: + movement: + state: medical_derelict + - type: BorgChassis + maxModules: 6 # One less module slot than the regular module to reflect this being a "broken" cyborg. + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleMedical + hasMindState: medical_e + noMindState: medical_e_r + +- type: entity + parent: BaseBorgChassisDerelict + id: MiningBorgChassisDerelict + name: derelict salvage cyborg + description: A man-machine hybrid that assists the cargo department. This one has seen the wrong side of a gibtonite chunk. + components: + - type: Sprite + layers: + - state: miner_derelict + map: ["movement"] + - state: miner_e_r + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: miner_l + shader: unshaded + map: ["light"] + visible: false + - type: SpriteMovement + movementLayers: + movement: + state: miner_moving_derelict + noMovementLayers: + movement: + state: miner_derelict + - type: BorgChassis + maxModules: 6 # One less module slot than the regular module to reflect this being a "broken" cyborg. + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleCargo + hasMindState: miner_e + noMindState: miner_e_r + +- type: entity + parent: BaseBorgChassisSyndicateDerelict + id: SyndicateAssaultBorgChassisDerelict + name: derelict syndicate assault cyborg + description: A lean, mean killing machine with access to a variety of deadly modules. This one is more rust-orange than blood-red. + components: + - type: Sprite + layers: + - state: synd_sec_derelict + - state: synd_sec_e + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: synd_sec_l + shader: unshaded + map: ["light"] + visible: false + - type: BorgChassis + maxModules: 3 + moduleWhitelist: # Note - the Derelict Assault Borg does not have a traversal module. This is intentional as Assault Borgs have space traversal with their c20 and free space movement, and they can navigate to the station using the pinpointer. + tags: + - BorgModuleGeneric + - BorgModuleSyndicate + - BorgModuleSyndicateAssault + hasMindState: synd_sec_derelict_e + noMindState: synd_sec_derelict + - type: Construction + node: derelictcyborg diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 4369196934..98c839f42a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -401,7 +401,7 @@ # borg_module: # - BorgModuleOperative # - BorgModuleL6C -# - BorgModuleEsword +# - BorgModuleDoubleEsword # - type: ItemSlots # slots: # cell_slot: @@ -471,8 +471,44 @@ - PlayerBorgSyndicateSaboteurGhostRole - type: entity - id: PlayerBorgDerelict + parent: EngineeringBorgChassisDerelict + id: PlayerEngineeringBorgDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleTool + - BorgModuleFireExtinguisher + - BorgModuleConstruction + - BorgModuleRCD + - BorgModuleCable + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh + - type: RandomMetadata + nameSegments: [NamesBorg] + +- type: entity + parent: PlayerEngineeringBorgDerelict + id: PlayerEngineeringBorgDerelictGhostRole + suffix: Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-engineering-cyborg-name + description: ghost-role-information-derelict-engineering-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable + +- type: entity parent: BorgChassisDerelict + id: PlayerBorgDerelict suffix: Battery, Module components: - type: ContainerFill @@ -491,8 +527,8 @@ nameSegments: [NamesBorg] - type: entity - id: PlayerBorgDerelictGhostRole parent: PlayerBorgDerelict + id: PlayerBorgDerelictGhostRole suffix: Ghost role components: - type: GhostRole @@ -502,3 +538,143 @@ raffle: settings: default - type: GhostTakeoverAvailable + +- type: entity + parent: JanitorBorgChassisDerelict + id: PlayerJanitorBorgDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleTool + - BorgModuleFireExtinguisher + - BorgModuleCleaning + - BorgModuleCustodial + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh + - type: RandomMetadata + nameSegments: [NamesBorg] + +- type: entity + parent: PlayerJanitorBorgDerelict + id: PlayerJanitorBorgDerelictGhostRole + suffix: Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-janitor-cyborg-name + description: ghost-role-information-derelict-janitor-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable + +- type: entity + parent: MedicalBorgChassisDerelict + id: PlayerMedicalBorgDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleTool + - BorgModuleFireExtinguisher + - BorgModuleChemical + - BorgModuleTopicals + - BorgModuleRescue + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh + - type: RandomMetadata + nameSegments: [NamesBorg] + +- type: entity + parent: PlayerMedicalBorgDerelict + id: PlayerMedicalBorgDerelictGhostRole + suffix: Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-medical-cyborg-name + description: ghost-role-information-derelict-medical-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable + +- type: entity + parent: MiningBorgChassisDerelict + id: PlayerMiningBorgDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleTool #No fire extinguisher, traversal is better + - BorgModuleMining + - BorgModuleTraversal + - BorgModuleAppraisal + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh + - type: RandomMetadata + nameSegments: [NamesBorg] + +- type: entity + parent: PlayerMiningBorgDerelict + id: PlayerMiningBorgDerelictGhostRole + suffix: Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-mining-cyborg-name + description: ghost-role-information-derelict-mining-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable + +- type: entity + parent: SyndicateAssaultBorgChassisDerelict + id: PlayerSyndicateAssaultBorgDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleOperative + - BorgModuleC20r + - BorgModuleEsword + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHyper + - type: RandomMetadata + nameSegments: [NamesDeathCommando] + +- type: entity + parent: PlayerSyndicateAssaultBorgDerelict + id: PlayerBorgSyndicateDerelictGhostRole + suffix: Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-syndicate-assault-cyborg-name + description: ghost-role-information-derelict-syndicate-assault-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable diff --git a/Resources/Prototypes/Entities/Objects/Misc/inflatable_wall.yml b/Resources/Prototypes/Entities/Objects/Misc/inflatable_wall.yml index 0641084847..577ab1dddd 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/inflatable_wall.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/inflatable_wall.yml @@ -33,6 +33,7 @@ - type: DisassembleOnAltVerb prototypeToSpawn: InflatableWallStack1 disassembleTime: 3 + - type: InflatableSafeDisassembly - type: Airtight - type: Transform anchored: true @@ -81,5 +82,6 @@ - type: DisassembleOnAltVerb prototypeToSpawn: InflatableDoorStack1 disassembleTime: 3 + - type: InflatableSafeDisassembly - type: Occluder enabled: false diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml index 51b977790a..99db379356 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml @@ -489,6 +489,36 @@ - type: BorgModuleIcon icon: { sprite: Interface/Actions/actions_borg.rsi, state: tool-module } +- type: entity + id: BorgModuleInflatable + parent: [ BaseBorgModule, BaseProviderBorgModule ] + name: inflatable cyborg module + components: + - type: Sprite + layers: + - state: generic + - state: icon-inflatable + - type: ItemBorgModule + hands: + - item: InflatableDoorStack + hand: + emptyRepresentative: InflatableDoorStack + emptyLabel: borg-slot-inflatable-door-empty + whitelist: + tags: + - Inflatable + - item: InflatableWallStack + hand: + emptyRepresentative: InflatableWallStack + emptyLabel: borg-slot-inflatable-wall-empty + whitelist: + tags: + - Inflatable + - item: BoxInflatable + - item: WeaponMeleeNeedle + - type: BorgModuleIcon + icon: { sprite: Interface/Actions/actions_borg.rsi, state: inflatable-module } + # cargo modules - type: entity id: BorgModuleAppraisal @@ -1135,8 +1165,8 @@ #syndicate modules - type: entity - id: BorgModuleSyndicateWeapon parent: [ BaseBorgModule, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleSyndicateWeapon name: weapon cyborg module components: - type: Sprite @@ -1171,8 +1201,8 @@ price: 2500 - type: entity - id: BorgModuleOperative parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleOperative name: operative cyborg module description: A module that comes with a crowbar, an Access Breaker and a syndicate pinpointer. components: @@ -1190,42 +1220,76 @@ icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-operative-module } - type: entity - id: BorgModuleEsword parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleEsword name: energy sword cyborg module - description: A module that comes with a double energy sword. + description: A weapons module that comes with an energy sword. components: - - type: Sprite - layers: - - state: syndicate - - state: icon-syndicate - - type: ItemBorgModule - hands: - - item: CyborgEnergySwordDouble - - item: PinpointerSyndicateNuclear - - type: BorgModuleIcon - icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-esword-module } + - type: Sprite + layers: + - state: syndicate + - state: icon-syndicate + - type: ItemBorgModule + hands: + - item: CyborgEnergySword + - item: PinpointerSyndicateNuclear + - type: BorgModuleIcon + icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-esword-module } + +- type: entity + id: BorgModuleDoubleEsword + parent: [ BaseBorgModuleSyndicate, BaseProviderBorgModule, BaseSyndicateContraband ] + name: double energy sword cyborg module + description: A weapons module that comes with a double energy sword. + components: + - type: Sprite + layers: + - state: syndicate + - state: icon-syndicate + - type: ItemBorgModule + hands: + - item: CyborgEnergySwordDouble + - item: PinpointerSyndicateNuclear + - type: BorgModuleIcon + icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-desword-module } - type: entity - id: BorgModuleL6C parent: [ BaseBorgModuleSyndicateAssault, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleL6C name: L6C ROW cyborg module - description: A module that comes with a L6C. + description: A weapons module that comes with a L6C. components: - - type: Sprite - layers: - - state: syndicate - - state: icon-syndicate - - type: ItemBorgModule - hands: - - item: WeaponLightMachineGunL6C - - item: PinpointerSyndicateNuclear - - type: BorgModuleIcon - icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-l6c-module } + - type: Sprite + layers: + - state: syndicate + - state: icon-syndicate + - type: ItemBorgModule + hands: + - item: WeaponLightMachineGunL6C + - item: PinpointerSyndicateNuclear + - type: BorgModuleIcon + icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-l6c-module } + +- type: entity + parent: [ BaseBorgModuleSyndicateAssault, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleC20r + name: C20-r ROW cyborg module + description: A weapons module that comes with a burst-fire C-20r. + components: + - type: Sprite + layers: + - state: syndicate + - state: icon-syndicate + - type: ItemBorgModule + hands: + - item: WeaponSubMachineGunC20rROW + - item: PinpointerSyndicateNuclear + - type: BorgModuleIcon + icon: { sprite: Interface/Actions/actions_borg.rsi, state: syndicate-c20r-module } - type: entity - id: BorgModuleMartyr parent: [ BaseBorgModule, BaseProviderBorgModule, BaseSyndicateContraband ] + id: BorgModuleMartyr name: martyr cyborg module description: "A module that comes with an explosive you probably don't want to handle yourself." components: diff --git a/Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml b/Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml index f5e05b4e28..4f55d5c164 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml @@ -5,21 +5,24 @@ description: A folded membrane which rapidly expands into a large cubical shape on activation. suffix: Full components: - - type: Stack - stackType: InflatableWall - count: 10 - - type: Sprite - sprite: Objects/Misc/inflatable_wall.rsi - state: item_wall - - type: Item - sprite: Objects/Misc/inflatable_wall.rsi - size: Small - - type: SpawnAfterInteract - prototype: InflatableWall - doAfter: 1 - removeOnInteract: true - - type: Clickable - - type: PhysicalComposition + - type: Stack + stackType: InflatableWall + count: 10 + - type: Sprite + sprite: Objects/Misc/inflatable_wall.rsi + state: item_wall + - type: Item + sprite: Objects/Misc/inflatable_wall.rsi + size: Small + - type: SpawnAfterInteract + prototype: InflatableWall + doAfter: 1 + removeOnInteract: true + - type: Clickable + - type: PhysicalComposition + - type: Tag + tags: + - Inflatable # TODO: Add stack sprites + visuals. - type: entity @@ -29,21 +32,24 @@ description: A folded membrane which rapidly expands into a large cubical shape on activation. suffix: Full components: - - type: Stack - stackType: InflatableDoor - count: 4 - - type: Sprite - sprite: Objects/Misc/inflatable_door.rsi - state: item_door - - type: Item - sprite: Objects/Misc/inflatable_door.rsi - size: Small - - type: SpawnAfterInteract - prototype: InflatableDoor - doAfter: 1 - removeOnInteract: true - - type: Clickable - - type: PhysicalComposition + - type: Stack + stackType: InflatableDoor + count: 4 + - type: Sprite + sprite: Objects/Misc/inflatable_door.rsi + state: item_door + - type: Item + sprite: Objects/Misc/inflatable_door.rsi + size: Small + - type: SpawnAfterInteract + prototype: InflatableDoor + doAfter: 1 + removeOnInteract: true + - type: Clickable + - type: PhysicalComposition + - type: Tag + tags: + - Inflatable # TODO: Add stack sprites + visuals. - type: entity @@ -51,27 +57,27 @@ id: InflatableWallStack5 suffix: 5 components: - - type: Sprite - state: item_wall - - type: Stack - count: 5 + - type: Sprite + state: item_wall + - type: Stack + count: 5 - type: entity parent: InflatableWallStack id: InflatableWallStack1 suffix: 1 components: - - type: Sprite - state: item_wall - - type: Stack - count: 1 + - type: Sprite + state: item_wall + - type: Stack + count: 1 - type: entity parent: InflatableDoorStack id: InflatableDoorStack1 suffix: 1 components: - - type: Sprite - state: item_door - - type: Stack - count: 1 + - type: Sprite + state: item_door + - type: Stack + count: 1 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml index d646582d38..286d4ab313 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml @@ -143,6 +143,47 @@ - type: StaticPrice price: 5000 +- type: entity + name: C-20r ROW #I think ROW stands for Recharging Onboard Weapon so i'm following the L6C's example + id: WeaponSubMachineGunC20rROW + parent: BaseItem + description: A burst-fire C-20r submachine gun for use by cyborgs. Creates .35 caliber ammo on the fly from an internal ammo fabricator, which slowly self-charges. + components: + - type: Gun + minAngle: 2 + maxAngle: 16 + angleIncrease: 4 + angleDecay: 16 + fireRate: 8 + burstFireRate: 8 + selectedMode: Burst + availableModes: + - Burst + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/c-20r.ogg + - type: Sprite + sprite: Objects/Weapons/Guns/SMGs/c20r.rsi + layers: + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-5 + map: ["enum.GunVisualLayers.Mag"] + - type: Item + size: Huge + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + - type: ProjectileBatteryAmmoProvider + proto: CartridgePistol + fireCost: 100 + - type: Battery + maxCharge: 3000 + startingCharge: 3000 + - type: BatterySelfRecharger + autoRecharge: true + autoRechargeRate: 25 + - type: AmmoCounter + - type: entity name: Drozd parent: [BaseWeaponSubMachineGun, BaseSecurityContraband] diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml index 28a2188043..dbfd5ef0ce 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/e_sword.yml @@ -444,10 +444,17 @@ spread: 75 # Borgs + +- type: entity + parent: EnergySword + id: CyborgEnergySword + suffix: For Borgs + description: A very loud & dangerous sword with a beam made of pure, concentrated plasma. Specially designed for syndicate cyborgs. + - type: entity - suffix: One-Handed, For Borgs parent: EnergySwordDouble id: CyborgEnergySwordDouble # why is this invalid if ID is BorgEnergySwordDouble + suffix: One-Handed, For Borgs description: Syndicate Command Interns thought that having one blade on the energy sword was not enough. Specially designed for syndicate cyborgs. components: # could add energy-draining like the L6C - type: Wieldable diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index fbc369db26..c6709fb48a 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -34,7 +34,8 @@ - id: ClosetSkeleton - id: KingRatMigration - id: RevenantSpawn - - id: DerelictCyborgSpawn + - !type:NestedSelector + tableId: DerelictBorgEventTable - type: entityTable id: ModerateAntagEventsTable @@ -48,6 +49,25 @@ - id: LoneOpsSpawn - id: WizardSpawn - id: AbductorsSpawn # Sunrise-Edit + - !type:NestedSelector + tableId: DerelictBorgEventTable + +- type: entityTable + id: DerelictBorgEventTable #For Derelict Borg spawns + table: !type:GroupSelector + children: + - !type:GroupSelector # Standard NT Borgs + weight: 85 + children: + - id: DerelictEngineerCyborgSpawn + - id: DerelictGenericCyborgSpawn + - id: DerelictJanitorCyborgSpawn + - id: DerelictMedicalCyborgSpawn + - id: DerelictMiningCyborgSpawn + - !type:GroupSelector # Other Borgs + weight: 15 + children: + - id: DerelictSyndicateAssaultCyborgSpawn - type: entity id: BaseStationEvent @@ -556,7 +576,7 @@ earliestStart: 35 weight: 5.5 minimumPlayers: 20 - duration: null # LoneOpsSpawn needs an infinite duration so that it inherits the NukeOpsRule things of an actually appropriate end scrreen (not always "Neutral outcome!") and... ending the game if the station is nuked. + duration: null # LoneOpsSpawn needs an infinite duration so that it inherits the NukeOpsRule things of an actually appropriate end screen (not always "Neutral outcome!") and... ending the game if the station is nuked. - type: RuleGrids - type: LoadMapRule gridPath: /Maps/Shuttles/ShuttleEvent/striker.yml @@ -697,10 +717,10 @@ - type: entity parent: BaseGameRule - id: DerelictCyborgSpawn + id: DerelictEngineerCyborgSpawn components: - type: StationEvent - weight: 5 + weight: 2.5 earliestStart: 15 reoccurrenceDelay: 20 minimumPlayers: 4 @@ -708,10 +728,115 @@ - type: SpaceSpawnRule spawnDistance: 0 - type: AntagSpawner - prototype: PlayerBorgDerelict + prototype: PlayerEngineeringBorgDerelictGhostRole + - type: AntagSelection + definitions: + - spawnerPrototype: SpawnPointGhostDerelictEngineeringCyborg + min: 1 + max: 1 + pickPlayer: false + +- type: entity + parent: BaseGameRule + id: DerelictGenericCyborgSpawn + components: + - type: StationEvent + weight: 2.5 + earliestStart: 15 + reoccurrenceDelay: 20 + minimumPlayers: 4 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerBorgDerelictGhostRole - type: AntagSelection definitions: - spawnerPrototype: SpawnPointGhostDerelictCyborg min: 1 max: 1 pickPlayer: false + +- type: entity + parent: BaseGameRule + id: DerelictJanitorCyborgSpawn + components: + - type: StationEvent + weight: 2.5 + earliestStart: 15 + reoccurrenceDelay: 20 + minimumPlayers: 4 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerJanitorBorgDerelictGhostRole + - type: AntagSelection + definitions: + - spawnerPrototype: SpawnPointGhostDerelictJanitorCyborg + min: 1 + max: 1 + pickPlayer: false + +- type: entity + parent: BaseGameRule + id: DerelictMedicalCyborgSpawn + components: + - type: StationEvent + weight: 2.5 + earliestStart: 15 + reoccurrenceDelay: 20 + minimumPlayers: 4 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerMedicalBorgDerelictGhostRole + - type: AntagSelection + definitions: + - spawnerPrototype: SpawnPointGhostDerelictMedicalCyborg + min: 1 + max: 1 + pickPlayer: false + +- type: entity + parent: BaseGameRule + id: DerelictMiningCyborgSpawn + components: + - type: StationEvent + weight: 2.5 + earliestStart: 15 + reoccurrenceDelay: 20 + minimumPlayers: 4 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerMiningBorgDerelictGhostRole + - type: AntagSelection + definitions: + - spawnerPrototype: SpawnPointGhostDerelictMiningCyborg + min: 1 + max: 1 + pickPlayer: false + +- type: entity + parent: BaseGameRule + id: DerelictSyndicateAssaultCyborgSpawn + components: + - type: StationEvent + weight: 2.5 + earliestStart: 25 + reoccurrenceDelay: 20 + minimumPlayers: 15 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerBorgSyndicateDerelictGhostRole + - type: AntagSelection + definitions: + - spawnerPrototype: SpawnPointGhostDerelictSyndicateAssaultCyborg + min: 1 + max: 1 + pickPlayer: false diff --git a/Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml b/Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml index 814e1eec94..810e454174 100644 --- a/Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml @@ -15,6 +15,7 @@ - BorgModuleTool - BorgModuleCable - BorgModuleFireExtinguisher + - BorgModuleInflatable - type: latheRecipePack id: BorgLimbsStatic diff --git a/Resources/Prototypes/Recipes/Lathes/robot_modules.yml b/Resources/Prototypes/Recipes/Lathes/robot_modules.yml index 9210529a1d..9465d7b87a 100644 --- a/Resources/Prototypes/Recipes/Lathes/robot_modules.yml +++ b/Resources/Prototypes/Recipes/Lathes/robot_modules.yml @@ -37,6 +37,11 @@ id: BorgModuleFireExtinguisher result: BorgModuleFireExtinguisher +- type: latheRecipe + parent: BaseBorgModuleRecipe + id: BorgModuleInflatable + result: BorgModuleInflatable + # Cargo Modules - type: latheRecipe diff --git a/Resources/Prototypes/borg_types.yml b/Resources/Prototypes/borg_types.yml index 6902b265ca..641904f5ee 100644 --- a/Resources/Prototypes/borg_types.yml +++ b/Resources/Prototypes/borg_types.yml @@ -18,6 +18,7 @@ defaultModules: - BorgModuleTool + - BorgModuleInflatable - BorgModuleArtifact - BorgModuleAnomaly diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 7423987142..32523736a7 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -804,6 +804,9 @@ - type: Tag id: Ingot +- type: Tag + id: Inflatable + - type: Tag id: InstantDoAfters diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png new file mode 100644 index 0000000000..15e1c86629 Binary files /dev/null and b/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png differ diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json index fcde6a539f..5380cc63d2 100644 --- a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json +++ b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA", + "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, inflatable module by FungiFellow (GitHub), Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA. c20r and esword by RedBookcase on Github.", "size": { "x": 32, "y": 32 @@ -31,6 +31,9 @@ { "name":"geiger-module" }, + { + "name":"inflatable-module" + }, { "name":"rcd-module" }, @@ -109,12 +112,18 @@ { "name":"syndicate-operative-module" }, + { + "name":"syndicate-desword-module" + }, { "name":"syndicate-esword-module" }, { "name":"syndicate-l6c-module" }, + { + "name":"syndicate-c20r-module" + }, { "name":"syndicate-martyr-module" }, diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-c20r-module.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-c20r-module.png new file mode 100644 index 0000000000..52c14b2651 Binary files /dev/null and b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-c20r-module.png differ diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-desword-module.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-desword-module.png new file mode 100644 index 0000000000..201149cf18 Binary files /dev/null and b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-desword-module.png differ diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-esword-module.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-esword-module.png index 201149cf18..944c4ee918 100644 Binary files a/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-esword-module.png and b/Resources/Textures/Interface/Actions/actions_borg.rsi/syndicate-esword-module.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict.png new file mode 100644 index 0000000000..7eb8b01ad0 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict_crystal.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict_crystal.png new file mode 100644 index 0000000000..38bae65c83 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/engineer_derelict_crystal.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_derelict.png new file mode 100644 index 0000000000..34ae031b79 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_moving_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_moving_derelict.png new file mode 100644 index 0000000000..ce6b1bc61e Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/janitor_moving_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_derelict.png new file mode 100644 index 0000000000..8fd1dba350 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_moving_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_moving_derelict.png new file mode 100644 index 0000000000..4054df6184 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/medical_moving_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json index 898e5de172..6e450b88d2 100644 --- a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json +++ b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json @@ -1,675 +1,807 @@ { - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/faf6db214927874c19b8fa8585d26b5d40de1acc, derelict sprites modified by GoldenCan(GitHub), xenoborg sprites, created and modified by Samuka-C (github).", - "states": [ - { - "name": "clown", - "directions": 4 - }, - { - "name": "clown_e", - "directions": 4 - }, - { - "name": "clown_e_r", - "directions": 4 - }, - { - "name": "clown_l", - "directions": 4 - }, - { - "name": "derelict", - "directions": 4 - }, - { - "name": "derelict_e", - "directions": 4 - }, - { - "name": "derelict_e_r", - "directions": 4 - }, - { - "name": "derelict_icon", - "directions": 1 - }, - { - "name": "derelict_l", - "directions": 4 - }, - { - "name": "engineer", - "directions": 4 - }, - { - "name": "engineer_e", - "directions": 4 - }, - { - "name": "engineer_e_r", - "directions": 4 - }, - { - "name": "engineer_l", - "directions": 4 - }, - { - "name": "janitor", - "directions": 4 - }, - { - "name": "janitor_moving", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "janitor_e", - "directions": 4 - }, - { - "name": "janitor_e_r", - "directions": 4 - }, - { - "name": "janitor_l", - "directions": 4 - }, - { - "name": "medical", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "medical_moving", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "medical_e", - "directions": 4 - }, - { - "name": "medical_e_r", - "directions": 4 - }, - { - "name": "medical_l", - "directions": 4 - }, - { - "name": "miner", - "directions": 4 - }, - { - "name": "miner_moving", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1 - ], - [ - 0.1, - 0.1 - ], - [ - 0.1, - 0.1 - ], - [ - 0.1, - 0.1 - ] - ] - }, - { - "name": "miner_e", - "directions": 4 - }, - { - "name": "miner_e_r", - "directions": 4 - }, - { - "name": "miner_l", - "directions": 4 - }, - { - "name": "robot", - "directions": 4 - }, - { - "name": "robot_e", - "directions": 4 - }, - { - "name": "robot_e_r", - "directions": 4 - }, - { - "name": "robot_l", - "directions": 4 - }, - { - "name": "peace", - "directions": 4 - }, - { - "name": "peace_e", - "directions": 4 - }, - { - "name": "peace_e_r", - "directions": 4 - }, - { - "name": "peace_l", - "directions": 4 - }, - { - "name": "service", - "directions": 4 - }, - { - "name": "service_e", - "directions": 4 - }, - { - "name": "service_e_r", - "directions": 4 - }, - { - "name": "service_l", - "directions": 4 - }, - { - "name": "synd_sec", - "directions": 4 - }, - { - "name": "synd_sec_e", - "directions": 4 - }, - { - "name": "synd_sec_l", - "directions": 4 - }, - { - "name": "synd_medical", - "directions": 4 - }, - { - "name": "synd_medical_l", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "synd_medical_e", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "synd_engi", - "directions": 4 - }, - { - "name": "synd_engi_e", - "directions": 4 - }, - { - "name": "synd_engi_l", - "directions": 4 - }, - { - "name": "xenoborg_heavy", - "directions": 4 - }, - { - "name": "xenoborg_heavy_e", - "directions": 4 - }, - { - "name": "xenoborg_heavy_e_r", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "xenoborg_heavy_l", - "directions": 4 - }, - { - "name": "xenoborg_scout", - "directions": 4 - }, - { - "name": "xenoborg_scout_l", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "xenoborg_scout_e", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "xenoborg_scout_e_r", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "xenoborg_engi", - "directions": 4 - }, - { - "name": "xenoborg_engi_e", - "directions": 4 - }, - { - "name": "xenoborg_engi_e_r", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "xenoborg_engi_l", - "directions": 4 - }, - { - "name": "xenoborg_stealth", - "directions": 4 - }, - { - "name": "xenoborg_stealth_e", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "xenoborg_stealth_e_r", - "directions": 4, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ], - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] - }, - { - "name": "xenoborg_stealth_l", - "directions": 4, - "delays": [ - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ], - [ - 0.1, - 0.2, - 0.1 - ] - ] - }, - { - "name": "sec", - "directions": 4 - }, - { - "name": "sec_e", - "directions": 4 - }, - { - "name": "sec_e_r", - "directions": 4 - }, - { - "name": "sec_l", - "directions": 4 - } - ] + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/faf6db214927874c19b8fa8585d26b5d40de1acc, derelict generic sprites modified by GoldenCan(GitHub), xenoborg sprites, created and modified by Samuka-C (github). Derelict Engineer, Janitor, Miner, Medical, and Assault Borg sprites by _miket on Discord.", + "states": [ + { + "name": "clown", + "directions": 4 + }, + { + "name": "clown_e", + "directions": 4 + }, + { + "name": "clown_e_r", + "directions": 4 + }, + { + "name": "clown_l", + "directions": 4 + }, + { + "name": "derelict", + "directions": 4 + }, + { + "name": "derelict_e", + "directions": 4 + }, + { + "name": "derelict_e_r", + "directions": 4 + }, + { + "name": "derelict_icon", + "directions": 1 + }, + { + "name": "derelict_l", + "directions": 4 + }, + { + "name": "engineer", + "directions": 4 + }, + { + "name": "engineer_e", + "directions": 4 + }, + { + "name": "engineer_e_r", + "directions": 4 + }, + { + "name": "engineer_l", + "directions": 4 + }, + { + "name": "engineer_derelict", + "directions": 4 + }, + { + "name": "engineer_derelict_crystal", + "directions": 4 + }, + { + "name": "janitor", + "directions": 4 + }, + { + "name": "janitor_moving", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "janitor_e", + "directions": 4 + }, + { + "name": "janitor_e_r", + "directions": 4 + }, + { + "name": "janitor_l", + "directions": 4 + }, + { + "name": "janitor_derelict", + "directions": 4 + }, + { + "name": "janitor_moving_derelict", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "medical", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "medical_moving", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "medical_e", + "directions": 4 + }, + { + "name": "medical_e_r", + "directions": 4 + }, + { + "name": "medical_l", + "directions": 4 + }, + { + "name": "medical_derelict", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "medical_moving_derelict", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "miner", + "directions": 4 + }, + { + "name": "miner_moving", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "miner_e", + "directions": 4 + }, + { + "name": "miner_e_r", + "directions": 4 + }, + { + "name": "miner_l", + "directions": 4 + }, + { + "name": "miner_derelict", + "directions": 4 + }, + { + "name": "miner_moving_derelict", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ], + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "robot", + "directions": 4 + }, + { + "name": "robot_e", + "directions": 4 + }, + { + "name": "robot_e_r", + "directions": 4 + }, + { + "name": "robot_l", + "directions": 4 + }, + { + "name": "peace", + "directions": 4 + }, + { + "name": "peace_e", + "directions": 4 + }, + { + "name": "peace_e_r", + "directions": 4 + }, + { + "name": "peace_l", + "directions": 4 + }, + { + "name": "service", + "directions": 4 + }, + { + "name": "service_e", + "directions": 4 + }, + { + "name": "service_e_r", + "directions": 4 + }, + { + "name": "service_l", + "directions": 4 + }, + { + "name": "synd_sec", + "directions": 4 + }, + { + "name": "synd_sec_e", + "directions": 4 + }, + { + "name": "synd_sec_l", + "directions": 4 + }, + { + "name": "synd_sec_derelict", + "directions": 4 + }, + { + "name": "synd_sec_derelict_e", + "directions": 4 + }, + { + "name": "synd_sec_derelict_l", + "directions": 4 + }, + { + "name": "synd_medical", + "directions": 4 + }, + { + "name": "synd_medical_l", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "synd_medical_e", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "synd_engi", + "directions": 4 + }, + { + "name": "synd_engi_e", + "directions": 4 + }, + { + "name": "synd_engi_l", + "directions": 4 + }, + { + "name": "xenoborg_heavy", + "directions": 4 + }, + { + "name": "xenoborg_heavy_e", + "directions": 4 + }, + { + "name": "xenoborg_heavy_e_r", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "xenoborg_heavy_l", + "directions": 4 + }, + { + "name": "xenoborg_scout", + "directions": 4 + }, + { + "name": "xenoborg_scout_l", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "xenoborg_scout_e", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "xenoborg_scout_e_r", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "xenoborg_engi", + "directions": 4 + }, + { + "name": "xenoborg_engi_e", + "directions": 4 + }, + { + "name": "xenoborg_engi_e_r", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "xenoborg_engi_l", + "directions": 4 + }, + { + "name": "xenoborg_stealth", + "directions": 4 + }, + { + "name": "xenoborg_stealth_e", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "xenoborg_stealth_e_r", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "xenoborg_stealth_l", + "directions": 4, + "delays": [ + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ], + [ + 0.1, + 0.2, + 0.1 + ] + ] + }, + { + "name": "sec", + "directions": 4 + }, + { + "name": "sec_e", + "directions": 4 + }, + { + "name": "sec_e_r", + "directions": 4 + }, + { + "name": "sec_l", + "directions": 4 + } + ] } diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_derelict.png new file mode 100644 index 0000000000..d9d812c761 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_moving_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_moving_derelict.png new file mode 100644 index 0000000000..05cd74494b Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/miner_moving_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict.png new file mode 100644 index 0000000000..9b42b90f6e Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_e.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_e.png new file mode 100644 index 0000000000..a846febc06 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_e.png differ diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_l.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_l.png new file mode 100644 index 0000000000..b479c411a7 Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/synd_sec_derelict_l.png differ diff --git a/Resources/Textures/Objects/Specific/Medical/medical.rsi/meta.json b/Resources/Textures/Objects/Specific/Medical/medical.rsi/meta.json index be70ae85d4..dd005e48b3 100644 --- a/Resources/Textures/Objects/Specific/Medical/medical.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Medical/medical.rsi/meta.json @@ -1,9 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/commit/740ff31a81313086cf16761f3677cf1e2ab46c93 and Taken from tgstation at https://github.com/tgstation/tgstation/blob/623290915c2292b56da11048deb62d758e1e3fb4/icons/obj/bloodpack.dmi, Blood pack redone by Ubaser", - "copyright": "Taken from https://github.com/tgstation/tgstation/blob/a3568da5634e756d0849480104afda402c6f1c3c/icons/obj/medical/stack_medical.dmi", - "copyright": "Tourniquet Sprite by PoorMansDreams, in-hand sprites of tourniquet, gauze, and bloodpack made by SeamLesss (github)", + "copyright": "Taken from cev-eris at https://github.com/discordia-space/CEV-Eris/commit/740ff31a81313086cf16761f3677cf1e2ab46c93 and Taken from tgstation at https://github.com/tgstation/tgstation/blob/623290915c2292b56da11048deb62d758e1e3fb4/icons/obj/bloodpack.dmi, Blood pack redone by Ubaser. Taken from https://github.com/tgstation/tgstation/blob/a3568da5634e756d0849480104afda402c6f1c3c/icons/obj/medical/stack_medical.dmi. Tourniquet Sprite by PoorMansDreams, in-hand sprites of tourniquet, gauze, and bloodpack made by SeamLesss (github).", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png new file mode 100644 index 0000000000..8a6a2fa6ec Binary files /dev/null and b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png differ diff --git a/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json index 21734f4104..0eb0cc72a4 100644 --- a/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC0-1.0", - "copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). layered inhands by mubururu_ (github), icon-chem.png & icon-mining-adv.png created by mubururu_ (github), Xenoborg modules sprites by Samuka-C (github)", + "copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). icon-chem.png & icon-mining-adv.png created by mubururu_ (github) icon-inflatable.png made by FungiFellow (GitHub), Xenoborg modules sprites by Samuka-C (github)", "size": { "x": 32, "y": 32 @@ -28,6 +28,9 @@ { "name": "icon-cables" }, + { + "name": "icon-inflatable" + }, { "name": "icon-chemist" }, @@ -244,4 +247,5 @@ "name": "NT" } ] + }