Merge remote-tracking branch 'space-wizards/master'

This commit is contained in:
Vigers Ray 2025-04-11 18:58:41 +03:00
commit 022d9ddd1b
37 changed files with 277 additions and 263 deletions

View file

@ -1,7 +0,0 @@
using Content.Shared.Labels.EntitySystems;
namespace Content.Client.Labels;
public sealed partial class LabelSystem : SharedLabelSystem
{
}

View file

@ -25,6 +25,6 @@ public sealed class BorgSelectTypeUserInterface : BoundUserInterface
base.Open();
_menu = this.CreateWindow<BorgSelectTypeMenu>();
_menu.ConfirmedBorgType += prototype => SendMessage(new BorgSelectTypeMessage(prototype));
_menu.ConfirmedBorgType += prototype => SendPredictedMessage(new BorgSelectTypeMessage(prototype));
}
}

View file

@ -22,10 +22,10 @@ using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Content.Server.Labels.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
using Content.Shared.Labels.Components;
namespace Content.Server.Botany.Systems;
@ -45,8 +45,7 @@ public sealed class PlantHolderSystem : EntitySystem
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
public const float HydroponicsSpeedMultiplier = 1f;
public const float HydroponicsConsumptionMultiplier = 2f;

View file

@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Cargo.Components;
using Content.Server.Labels;
using Content.Server.NameIdentifier;
using Content.Shared.Access.Components;
using Content.Shared.Cargo;
@ -9,6 +8,7 @@ using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.Database;
using Content.Shared.IdentityManagement;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.NameIdentifier;
using Content.Shared.Paper;
using Content.Shared.Stacks;

View file

@ -1,6 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Cargo.Components;
using Content.Server.Labels.Components;
using Content.Server.Station.Components;
using Content.Shared.Cargo;
using Content.Shared.Cargo.BUI;
@ -11,6 +10,7 @@ using Content.Shared.Database;
using Content.Shared.Emag.Systems;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Labels.Components;
using Content.Shared.Paper;
using Robust.Shared.Audio;
using Robust.Shared.Map;

View file

@ -23,7 +23,7 @@ public sealed class LogProbeCartridgeSystem : EntitySystem
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedLabelSystem _label = default!;
[Dependency] private readonly LabelSystem _label = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly PaperSystem _paper = default!;

View file

@ -1,5 +1,4 @@
using Content.Server.Chemistry.Components;
using Content.Server.Labels;
using Content.Server.Popups;
using Content.Server.Storage.EntitySystems;
using Content.Shared.Administration.Logs;
@ -10,6 +9,7 @@ using Content.Shared.Chemistry.Reagent;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Storage;
using JetBrains.Annotations;
using Robust.Server.Audio;

View file

@ -25,7 +25,7 @@ namespace Content.Server.Cloning;
public sealed partial class CloningSystem : EntitySystem
{
[Dependency] private readonly SharedStackSystem _stack = default!;
[Dependency] private readonly SharedLabelSystem _label = default!;
[Dependency] private readonly LabelSystem _label = default!;
[Dependency] private readonly ForensicsSystem _forensics = default!;
[Dependency] private readonly PaperSystem _paper = default!;

View file

@ -23,7 +23,7 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
[Dependency] private readonly StationRecordsSystem _records = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly FingerprintReaderSystem _fingerprintReader = default!;
[Dependency] private readonly SharedLabelSystem _label = default!;
[Dependency] private readonly LabelSystem _label = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
public override void Initialize()

View file

@ -4,7 +4,6 @@ using Content.Server.Chat.Managers;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Labels;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Tools;
@ -20,6 +19,7 @@ using Content.Shared.Fax.Systems;
using Content.Shared.Fax.Components;
using Content.Shared.Interaction;
using Content.Shared.Labels.Components;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Mobs.Components;
using Content.Shared.Paper;
using Robust.Server.GameObjects;

View file

@ -1,4 +1,3 @@
using Content.Server.Labels;
using Content.Server.Popups;
using Content.Shared.DoAfter;
using Content.Shared.Examine;
@ -7,6 +6,7 @@ using Content.Shared.Forensics.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Labels.EntitySystems;
namespace Content.Server.Forensics
{

View file

@ -1,14 +0,0 @@
using Content.Shared.Containers.ItemSlots;
namespace Content.Server.Labels.Components
{
/// <summary>
/// This component allows you to attach and remove a piece of paper to an entity.
/// </summary>
[RegisterComponent]
public sealed partial class PaperLabelComponent : Component
{
[DataField("labelSlot")]
public ItemSlot LabelSlot = new();
}
}

View file

@ -1,115 +0,0 @@
using Content.Server.Labels.Components;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Examine;
using Content.Shared.Labels;
using Content.Shared.Labels.Components;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Paper;
using JetBrains.Annotations;
using Robust.Shared.Containers;
namespace Content.Server.Labels
{
/// <summary>
/// A system that lets players see the contents of a label on an object.
/// </summary>
[UsedImplicitly]
public sealed class LabelSystem : SharedLabelSystem
{
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public const string ContainerName = "paper_label";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PaperLabelComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<PaperLabelComponent, ComponentRemove>(OnComponentRemove);
SubscribeLocalEvent<PaperLabelComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
SubscribeLocalEvent<PaperLabelComponent, EntRemovedFromContainerMessage>(OnContainerModified);
SubscribeLocalEvent<PaperLabelComponent, ExaminedEvent>(OnExamined);
}
/// <summary>
/// Apply or remove a label on an entity.
/// </summary>
/// <param name="uid">EntityUid to change label on</param>
/// <param name="text">intended label text (null to remove)</param>
/// <param name="label">label component for resolve</param>
/// <param name="metadata">metadata component for resolve</param>
public override void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null)
{
if (!Resolve(uid, ref label, false))
label = EnsureComp<LabelComponent>(uid);
label.CurrentLabel = text;
NameMod.RefreshNameModifiers(uid);
Dirty(uid, label);
}
private void OnComponentInit(EntityUid uid, PaperLabelComponent component, ComponentInit args)
{
_itemSlotsSystem.AddItemSlot(uid, ContainerName, component.LabelSlot);
UpdateAppearance((uid, component));
}
private void OnComponentRemove(EntityUid uid, PaperLabelComponent component, ComponentRemove args)
{
_itemSlotsSystem.RemoveItemSlot(uid, component.LabelSlot);
}
private void OnExamined(EntityUid uid, PaperLabelComponent comp, ExaminedEvent args)
{
if (comp.LabelSlot.Item is not {Valid: true} item)
return;
using (args.PushGroup(nameof(PaperLabelComponent)))
{
if (!args.IsInDetailsRange)
{
args.PushMarkup(Loc.GetString("comp-paper-label-has-label-cant-read"));
return;
}
if (!EntityManager.TryGetComponent(item, out PaperComponent? paper))
// Assuming yaml has the correct entity whitelist, this should not happen.
return;
if (string.IsNullOrWhiteSpace(paper.Content))
{
args.PushMarkup(Loc.GetString("comp-paper-label-has-label-blank"));
return;
}
args.PushMarkup(Loc.GetString("comp-paper-label-has-label"));
var text = paper.Content;
args.PushMarkup(text.TrimEnd());
}
}
private void OnContainerModified(EntityUid uid, PaperLabelComponent label, ContainerModifiedMessage args)
{
if (!label.Initialized) return;
if (args.Container.ID != label.LabelSlot.ID)
return;
UpdateAppearance((uid, label));
}
private void UpdateAppearance(Entity<PaperLabelComponent, AppearanceComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp2, false))
return;
var slot = ent.Comp1.LabelSlot;
_appearance.SetData(ent, PaperLabelVisuals.HasLabel, slot.HasItem, ent.Comp2);
if (TryComp<PaperLabelTypeComponent>(slot.Item, out var type))
_appearance.SetData(ent, PaperLabelVisuals.LabelType, type.PaperType, ent.Comp2);
}
}
}

View file

@ -16,7 +16,7 @@ using Content.Shared.Construction.EntitySystems;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
using Content.Server.Labels;
using Content.Shared.Labels.EntitySystems;
using Robust.Shared.EntitySerialization.Systems;
namespace Content.Server.Salvage

View file

@ -1,8 +1,8 @@
using Content.Server.Administration;
using Content.Server.Labels;
using Content.Shared.Administration;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.Shuttles.Components;
using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems;

View file

@ -106,7 +106,7 @@ namespace Content.Shared.Interaction
_uiQuery = GetEntityQuery<ActivatableUIComponent>();
SubscribeLocalEvent<BoundUserInterfaceCheckRangeEvent>(HandleUserInterfaceRangeCheck);
SubscribeLocalEvent<BoundUserInterfaceMessageAttempt>(OnBoundInterfaceInteractAttempt);
SubscribeLocalEvent<ActivatableUIComponent, BoundUserInterfaceMessageAttempt>(OnBoundInterfaceInteractAttempt);
SubscribeAllEvent<InteractInventorySlotEvent>(HandleInteractInventorySlotEvent);
@ -151,13 +151,12 @@ namespace Content.Shared.Interaction
/// <summary>
/// Check that the user that is interacting with the BUI is capable of interacting and can access the entity.
/// </summary>
private void OnBoundInterfaceInteractAttempt(BoundUserInterfaceMessageAttempt ev)
private void OnBoundInterfaceInteractAttempt(Entity<ActivatableUIComponent> ent, ref BoundUserInterfaceMessageAttempt ev)
{
_uiQuery.TryComp(ev.Target, out var uiComp);
if (!_actionBlockerSystem.CanInteract(ev.Actor, ev.Target))
{
// We permit ghosts to open uis unless explicitly blocked
if (ev.Message is not OpenBoundInterfaceMessage || !HasComp<GhostComponent>(ev.Actor) || uiComp?.BlockSpectators == true)
if (ev.Message is not OpenBoundInterfaceMessage || !HasComp<GhostComponent>(ev.Actor) || ent.Comp.BlockSpectators)
{
ev.Cancel();
return;
@ -175,16 +174,14 @@ namespace Content.Shared.Interaction
return;
}
if (uiComp == null)
return;
if (uiComp.SingleUser && uiComp.CurrentSingleUser != null && uiComp.CurrentSingleUser != ev.Actor)
if (ent.Comp.SingleUser && ent.Comp.CurrentSingleUser != null && ent.Comp.CurrentSingleUser != ev.Actor)
{
ev.Cancel();
return;
}
if (uiComp.RequiresComplex && !_actionBlockerSystem.CanComplexInteract(ev.Actor))
if (ent.Comp.RequiresComplex && !_actionBlockerSystem.CanComplexInteract(ev.Actor))
ev.Cancel();
}

View file

@ -1,3 +1,4 @@
using Content.Shared.Labels.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared.Labels.Components;
@ -6,6 +7,7 @@ namespace Content.Shared.Labels.Components;
/// Makes entities have a label in their name. Labels are normally given by <see cref="HandLabelerComponent"/>
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(LabelSystem))]
public sealed partial class LabelComponent : Component
{
/// <summary>

View file

@ -0,0 +1,19 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Labels.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared.Labels.Components;
/// <summary>
/// This component allows you to attach and remove a piece of paper to an entity.
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(LabelSystem))]
public sealed partial class PaperLabelComponent : Component
{
/// <summary>
/// The slot where the label is stored.
/// </summary>
[DataField]
public ItemSlot LabelSlot = new();
}

View file

@ -1,15 +1,17 @@
using Content.Shared.Labels.EntitySystems;
using Robust.Shared.GameStates;
namespace Content.Shared.Labels.Components;
/// <summary>
/// Specifies the paper type (see textures/storage/crates/labels.rsi to see currently supported paper types) to show on crates this label is attached to.
/// </summary>
/// <summary>
/// Specifies the paper type (see textures/storage/crates/labels.rsi to see currently supported paper types) to show on crates this label is attached to.
/// </summary>
[RegisterComponent, NetworkedComponent]
[Access(typeof(LabelSystem))]
public sealed partial class PaperLabelTypeComponent : Component
{
/// <summary>
/// The type of label to show.
/// <summary>
/// The type of label to show.
/// </summary>
[DataField]
public string PaperType = "Paper";

View file

@ -0,0 +1,144 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Examine;
using Content.Shared.Labels.Components;
using Content.Shared.NameModifier.EntitySystems;
using Content.Shared.Paper;
using Robust.Shared.Containers;
using Robust.Shared.Utility;
namespace Content.Shared.Labels.EntitySystems;
public sealed partial class LabelSystem : EntitySystem
{
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public const string ContainerName = "paper_label";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LabelComponent, MapInitEvent>(OnLabelCompMapInit);
SubscribeLocalEvent<LabelComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<LabelComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
SubscribeLocalEvent<PaperLabelComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<PaperLabelComponent, ComponentRemove>(OnComponentRemove);
SubscribeLocalEvent<PaperLabelComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
SubscribeLocalEvent<PaperLabelComponent, EntRemovedFromContainerMessage>(OnContainerModified);
SubscribeLocalEvent<PaperLabelComponent, ExaminedEvent>(OnExamined);
}
private void OnLabelCompMapInit(Entity<LabelComponent> ent, ref MapInitEvent args)
{
if (!string.IsNullOrEmpty(ent.Comp.CurrentLabel))
{
ent.Comp.CurrentLabel = Loc.GetString(ent.Comp.CurrentLabel);
Dirty(ent);
}
_nameModifier.RefreshNameModifiers(ent.Owner);
}
/// <summary>
/// Apply or remove a label on an entity.
/// </summary>
/// <param name="uid">EntityUid to change label on</param>
/// <param name="text">intended label text (null to remove)</param>
/// <param name="label">label component for resolve</param>
/// <param name="metadata">metadata component for resolve</param>
public void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null)
{
label ??= EnsureComp<LabelComponent>(uid);
label.CurrentLabel = text;
_nameModifier.RefreshNameModifiers(uid);
Dirty(uid, label);
}
private void OnExamine(Entity<LabelComponent> ent, ref ExaminedEvent args)
{
if (!ent.Comp.Examinable)
return;
if (ent.Comp.CurrentLabel == null)
return;
var message = new FormattedMessage();
message.AddText(Loc.GetString("hand-labeler-has-label", ("label", ent.Comp.CurrentLabel)));
args.PushMessage(message);
}
private void OnRefreshNameModifiers(Entity<LabelComponent> entity, ref RefreshNameModifiersEvent args)
{
if (!string.IsNullOrEmpty(entity.Comp.CurrentLabel))
args.AddModifier("comp-label-format", extraArgs: ("label", entity.Comp.CurrentLabel));
}
private void OnComponentInit(Entity<PaperLabelComponent> ent, ref ComponentInit args)
{
_itemSlots.AddItemSlot(ent, ContainerName, ent.Comp.LabelSlot);
UpdateAppearance(ent);
}
private void OnComponentRemove(Entity<PaperLabelComponent> ent, ref ComponentRemove args)
{
_itemSlots.RemoveItemSlot(ent, ent.Comp.LabelSlot);
}
private void OnExamined(Entity<PaperLabelComponent> ent, ref ExaminedEvent args)
{
if (ent.Comp.LabelSlot.Item is not {Valid: true} item)
return;
using (args.PushGroup(nameof(PaperLabelComponent)))
{
if (!args.IsInDetailsRange)
{
args.PushMarkup(Loc.GetString("comp-paper-label-has-label-cant-read"));
return;
}
// Assuming yaml has the correct entity whitelist, this should not happen.
if (!TryComp<PaperComponent>(item, out var paper))
return;
if (string.IsNullOrWhiteSpace(paper.Content))
{
args.PushMarkup(Loc.GetString("comp-paper-label-has-label-blank"));
return;
}
args.PushMarkup(Loc.GetString("comp-paper-label-has-label"));
var text = paper.Content;
args.PushMarkup(text.TrimEnd());
}
}
// Not ref-sub due to being used for multiple subscriptions.
private void OnContainerModified(EntityUid uid, PaperLabelComponent label, ContainerModifiedMessage args)
{
if (!label.Initialized)
return;
if (args.Container.ID != label.LabelSlot.ID)
return;
UpdateAppearance((uid, label));
}
private void UpdateAppearance(Entity<PaperLabelComponent, AppearanceComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp2, false))
return;
var slot = ent.Comp1.LabelSlot;
_appearance.SetData(ent, PaperLabelVisuals.HasLabel, slot.HasItem, ent.Comp2);
if (TryComp<PaperLabelTypeComponent>(slot.Item, out var type))
_appearance.SetData(ent, PaperLabelVisuals.LabelType, type.PaperType, ent.Comp2);
}
}

View file

@ -14,7 +14,7 @@ public abstract class SharedHandLabelerSystem : EntitySystem
{
[Dependency] protected readonly SharedUserInterfaceSystem UserInterfaceSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedLabelSystem _labelSystem = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;

View file

@ -1,54 +0,0 @@
using Content.Shared.Examine;
using Content.Shared.Labels.Components;
using Content.Shared.NameModifier.EntitySystems;
using Robust.Shared.Utility;
namespace Content.Shared.Labels.EntitySystems;
public abstract partial class SharedLabelSystem : EntitySystem
{
[Dependency] protected readonly NameModifierSystem NameMod = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LabelComponent, MapInitEvent>(OnLabelCompMapInit);
SubscribeLocalEvent<LabelComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<LabelComponent, RefreshNameModifiersEvent>(OnRefreshNameModifiers);
}
private void OnLabelCompMapInit(EntityUid uid, LabelComponent component, MapInitEvent args)
{
if (!string.IsNullOrEmpty(component.CurrentLabel))
{
component.CurrentLabel = Loc.GetString(component.CurrentLabel);
Dirty(uid, component);
}
NameMod.RefreshNameModifiers(uid);
}
public virtual void Label(EntityUid uid, string? text, MetaDataComponent? metadata = null, LabelComponent? label = null){}
private void OnExamine(EntityUid uid, LabelComponent? label, ExaminedEvent args)
{
if (!Resolve(uid, ref label))
return;
if (!label.Examinable)
return;
if (label.CurrentLabel == null)
return;
var message = new FormattedMessage();
message.AddText(Loc.GetString("hand-labeler-has-label", ("label", label.CurrentLabel)));
args.PushMessage(message);
}
private void OnRefreshNameModifiers(Entity<LabelComponent> entity, ref RefreshNameModifiersEvent args)
{
if (!string.IsNullOrEmpty(entity.Comp.CurrentLabel))
args.AddModifier("comp-label-format", extraArgs: ("label", entity.Comp.CurrentLabel));
}
}

View file

@ -20,7 +20,7 @@ public abstract partial class SharedStationAiSystem
private void InitializeHeld()
{
SubscribeLocalEvent<StationAiRadialMessage>(OnRadialMessage);
SubscribeLocalEvent<BoundUserInterfaceMessageAttempt>(OnMessageAttempt);
SubscribeLocalEvent<StationAiWhitelistComponent, BoundUserInterfaceMessageAttempt>(OnMessageAttempt);
SubscribeLocalEvent<StationAiWhitelistComponent, GetVerbsEvent<AlternativeVerb>>(OnTargetVerbs);
SubscribeLocalEvent<StationAiHeldComponent, InteractionAttemptEvent>(OnHeldInteraction);
@ -116,7 +116,7 @@ public abstract partial class SharedStationAiSystem
RaiseLocalEvent(target.Value, (object) ev.Event);
}
private void OnMessageAttempt(BoundUserInterfaceMessageAttempt ev)
private void OnMessageAttempt(Entity<StationAiWhitelistComponent> ent, ref BoundUserInterfaceMessageAttempt ev)
{
if (ev.Actor == ev.Target)
return;

View file

@ -142,7 +142,7 @@ public abstract class SharedStorageSystem : EntitySystem
SubscribeLocalEvent<StorageComponent, OpenStorageImplantEvent>(OnImplantActivate);
SubscribeLocalEvent<StorageComponent, AfterInteractEvent>(AfterInteract);
SubscribeLocalEvent<StorageComponent, DestructionEventArgs>(OnDestroy);
SubscribeLocalEvent<BoundUserInterfaceMessageAttempt>(OnBoundUIAttempt);
SubscribeLocalEvent<StorageComponent, BoundUserInterfaceMessageAttempt>(OnBoundUIAttempt);
SubscribeLocalEvent<StorageComponent, BoundUIOpenedEvent>(OnBoundUIOpen);
SubscribeLocalEvent<StorageComponent, LockToggledEvent>(OnLockToggled);
SubscribeLocalEvent<MetaDataComponent, StackCountChangedEvent>(OnStackCountChanged);
@ -761,7 +761,7 @@ public abstract class SharedStorageSystem : EntitySystem
UpdateAppearance((ent.Owner, ent.Comp, null));
}
private void OnBoundUIAttempt(BoundUserInterfaceMessageAttempt args)
private void OnBoundUIAttempt(Entity<StorageComponent> ent, ref BoundUserInterfaceMessageAttempt args)
{
if (args.UiKey is not StorageComponent.StorageUiKey.Key ||
_openStorageLimit == -1 ||

View file

@ -1,35 +1,4 @@
Entries:
- author: red15
changes:
- message: Vending machine lights turns off when broken.
type: Fix
id: 7653
time: '2024-11-25T12:35:14.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33513
- author: metalgearsloth
changes:
- message: Adjusted the top menu on the separated game screen. The buttons will
now form multiple rows and no longer overflow into the viewport.
type: Tweak
id: 7654
time: '2024-11-26T00:59:35.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33047
- author: slarticodefast
changes:
- message: Added the greytide virus station event. It will bolt open all doors in
a few randomly chosen departments and unlock lockers with the corresponding
access.
type: Add
id: 7655
time: '2024-11-26T13:50:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33547
- author: slarticodefast
changes:
- message: Fixed space ambient music not playing.
type: Fix
id: 7656
time: '2024-11-27T05:32:39.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/33594
- author: slarticodefast
changes:
- message: Fixed windoors and high security doors not showing up on the AI's electrocution
@ -3892,3 +3861,33 @@
id: 8152
time: '2025-04-11T01:12:13.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/36453
- author: YoungThugSS14
changes:
- message: Wizards now appear roundstart in the "all at once" gamemode.
type: Tweak
id: 8153
time: '2025-04-11T02:06:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/36408
- author: DinnerCalzone
changes:
- message: Fixed gas mixers and pneumatic valves being hidden by floor tiles.
type: Fix
id: 8154
time: '2025-04-11T02:10:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/36428
- author: Nox38, BurgerMoth, ArtisticRoomba
changes:
- message: Added descriptions for all .25 caseless cartridges, magazines, and ammo
boxes.
type: Add
id: 8155
time: '2025-04-11T02:15:27.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/36385
- author: Nox38, BurgerMoth, ArtisticRoomba
changes:
- message: Added descriptions to all .45 magnum cartridges, magazines, speed loaders,
and ammo boxes.
type: Add
id: 8156
time: '2025-04-11T04:58:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/36383

View file

@ -29,6 +29,7 @@
parent: BaseMagazineBoxCaselessRifle
id: MagazineBoxCaselessRifle
name: ammunition box (.25 caseless)
description: A cardboard box of .25 caseless rounds. Intended to hold general-purpose kinetic ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeCaselessRifle
@ -43,6 +44,7 @@
parent: BaseMagazineBoxCaselessRifle
id: MagazineBoxCaselessRiflePractice
name: ammunition box (.25 caseless practice)
description: A cardboard box of .25 caseless rounds. Intended to hold non-harmful chalk ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeCaselessRiflePractice

View file

@ -28,6 +28,7 @@
parent: BaseMagazineBoxMagnum
id: MagazineBoxMagnum
name: ammunition box (.45 magnum)
description: A cardboard box of .45 magnum rounds. Intended to hold general-purpose kinetic ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnum
@ -42,6 +43,7 @@
parent: BaseMagazineBoxMagnum
id: MagazineBoxMagnumPractice
name: ammunition box (.45 magnum practice)
description: A cardboard box of .45 magnum rounds. Intended to hold non-harmful chalk ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumPractice
@ -57,6 +59,7 @@
id: MagazineBoxMagnumIncendiary
parent: BaseMagazineBoxMagnum
name: ammunition box (.45 magnum incendiary)
description: A cardboard box of .45 magnum rounds. Intended to hold self-igniting incendiary ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumIncendiary
@ -72,6 +75,7 @@
id: MagazineBoxMagnumUranium
parent: BaseMagazineBoxMagnum
name: ammunition box (.45 magnum uranium)
description: A cardboard box of .45 magnum rounds. Intended to hold exotic uranium-core ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumUranium
@ -87,6 +91,7 @@
id: MagazineBoxMagnumAP
parent: BaseMagazineBoxMagnum
name: ammunition box (.45 magnum armor-piercing)
description: A cardboard box of .45 magnum rounds. Intended to hold rare armor-piercing ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumAP

View file

@ -1,6 +1,6 @@
- type: entity
id: BaseCartridgeCaselessRifle
name: cartridge (.25 rifle)
name: cartridge (.25 caseless)
parent: [ BaseCartridge, BaseSecurityContraband ]
abstract: true
components:
@ -25,6 +25,7 @@
id: CartridgeCaselessRifle
name: cartridge (.25 caseless)
parent: BaseCartridgeCaselessRifle
description: A small caliber utilizing caseless technology, omitting conventional brass casing in favor of hardened propellant. Standard kinetic ammunition is common and useful in most situations.
components:
- type: HitScanCartridgeAmmo
proto: BulletCaselessRifle
@ -33,6 +34,7 @@
id: CartridgeCaselessRiflePractice
name: cartridge (.25 caseless practice)
parent: BaseCartridgeCaselessRifle
description: A small caliber utilizing caseless technology, omitting conventional brass casing in favor of hardened propellant. Chalk ammunition is generally non-harmful, used for practice.
components:
- type: HitScanCartridgeAmmo
proto: BulletCaselessRiflePractice

View file

@ -22,6 +22,7 @@
id: CartridgeMagnum
name: cartridge (.45 magnum)
parent: BaseCartridgeMagnum
description: Heavy magnum cartridge mostly used by revolvers. Standard kinetic ammunition is common and useful in most situations.
components:
- type: HitScanCartridgeAmmo
proto: BulletMagnum
@ -30,6 +31,7 @@
id: CartridgeMagnumPractice
name: cartridge (.45 magnum practice)
parent: BaseCartridgeMagnum
description: Heavy magnum cartridge mostly used by revolvers. Chalk ammunition is generally non-harmful, used for practice.
components:
- type: HitScanCartridgeAmmo
proto: BulletMagnumPractice
@ -45,6 +47,7 @@
id: CartridgeMagnumIncendiary
name: cartridge (.45 magnum incendiary)
parent: BaseCartridgeMagnum
description: Heavy magnum cartridge mostly used by revolvers. Incendiary ammunition contains a self-igniting compound that sets the target ablaze.
components:
- type: HitScanCartridgeAmmo
proto: BulletMagnumIncendiary
@ -62,6 +65,7 @@
id: CartridgeMagnumAP
name: cartridge (.45 magnum armor-piercing)
parent: BaseCartridgeMagnum
description: Heavy magnum cartridge mostly used by revolvers. Armor piercing ammunition is renowned for its ability to cut straight through body armor.
components:
- type: HitScanCartridgeAmmo
proto: BulletMagnumAP
@ -77,6 +81,7 @@
id: CartridgeMagnumUranium
name: cartridge (.45 magnum uranium)
parent: BaseCartridgeMagnum
description: Heavy magnum cartridge mostly used by revolvers. Uranium ammunition replaces the lead core of the bullet with fissile material, irradiating the target from the inside.
components:
- type: HitScanCartridgeAmmo
proto: BulletMagnumUranium
@ -87,4 +92,3 @@
- state: tip
map: [ "enum.AmmoVisualLayers.Tip" ]
color: "#65fe08"

View file

@ -100,6 +100,7 @@
id: MagazinePistolCaselessRifle
name: "pistol magazine (.25 caseless)"
parent: BaseMagazinePistolCaselessRifle
description: 10-round magazine for the Cobra pistol. Intended to hold general-purpose kinetic ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeCaselessRifle
@ -120,6 +121,7 @@
id: MagazinePistolCaselessRiflePractice
name: "pistol magazine (.25 caseless practice)"
parent: BaseMagazinePistolCaselessRifle
description: 10-round magazine for the Cobra pistol. Intended to hold non-harmful chalk ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeCaselessRiflePractice

View file

@ -52,6 +52,7 @@
name: pistol magazine (.45 magnum any)
suffix: empty
parent: BaseMagazineMagnum
description: 7-round single stack pistol magazine.
components:
- type: BallisticAmmoProvider
proto: null
@ -66,6 +67,7 @@
id: MagazineMagnum
name: pistol magazine (.45 magnum)
parent: BaseMagazineMagnum
description: 7-round single stack pistol magazine. Intended to hold general-purpose kinetic ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnum
@ -80,6 +82,7 @@
id: MagazineMagnumPractice
name: pistol magazine (.45 magnum practice)
parent: BaseMagazineMagnum
description: 7-round single stack pistol magazine. Intended to hold non-harmful chalk ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumPractice
@ -94,6 +97,7 @@
id: MagazineMagnumUranium
name: pistol magazine (.45 magnum uranium)
parent: BaseMagazineMagnum
description: 7-round single stack pistol magazine. Intended to hold exotic uranium-core ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumUranium
@ -108,6 +112,7 @@
id: MagazineMagnumAP
name: pistol magazine (.45 magnum armor-piercing)
parent: BaseMagazineMagnum
description: 7-round single stack pistol magazine. Intended to hold rare armor-piercing ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumAP

View file

@ -23,6 +23,7 @@
id: SpeedLoaderMagnum
name: "speed loader (.45 magnum)"
parent: BaseSpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds. Intended to hold general-purpose kinetic ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnum
@ -43,6 +44,7 @@
id: SpeedLoaderMagnumEmpty
name: "speed loader (.45 magnum any)"
parent: SpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds for the big iron on your hip. #Big Iron reference (duh)
components:
- type: BallisticAmmoProvider
proto: null
@ -61,6 +63,7 @@
id: SpeedLoaderMagnumIncendiary
name: "speed loader (.45 magnum incendiary)"
parent: SpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds. Intended to hold self-igniting incendiary ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumIncendiary
@ -69,6 +72,7 @@
id: SpeedLoaderMagnumPractice
name: "speed loader (.45 magnum practice)"
parent: BaseSpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds. Intended to hold non-harmful chalk ammunition, perfect for practicing your quick draw.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumPractice
@ -89,6 +93,7 @@
id: SpeedLoaderMagnumAP
name: "speed loader (.45 magnum armor-piercing)"
parent: BaseSpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds. Intended to hold rare armor-piercing ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumAP
@ -109,6 +114,7 @@
id: SpeedLoaderMagnumUranium
name: "speed loader (.45 magnum uranium)"
parent: BaseSpeedLoaderMagnum
description: Designed to quickly refill an empty revolver, it fits up to six rounds. Intended to hold exotic uranium-core ammunition.
components:
- type: BallisticAmmoProvider
proto: CartridgeMagnumUranium

View file

@ -151,7 +151,7 @@
name: cobra
parent: [ BaseWeaponPistol, BaseSyndicateContraband ]
id: WeaponPistolCobra
description: A rugged, robust operator handgun with inbuilt silencer. Uses .25 caseless ammo.
description: Integrally suppressed semi-automatic pistol used by the Syndicate, firing caseless subsonic rounds. Favored by any agent who likes to keep things quiet and leave no evidence behind. Feeds from .25 pistol magazines.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Pistols/cobra.rsi
@ -219,8 +219,8 @@
- type: entity
name: N1984
parent: [BaseWeaponPistol, BaseSecurityContraband]
id: WeaponPistolN1984 # the spaces in description are for formatting.
description: The sidearm of any self respecting officer. Comes in .45 magnum, the lord's caliber.
id: WeaponPistolN1984
description: An exceptionally powerful hand cannon designed as part of Nanotrasen's BFG initiative. Chambered in .45, the lords caliber, it is generally considered too unwieldy for standard use but has become something of a status symbol among Nanotrasen officials. Feeds from .45 pistol magazines.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Pistols/N1984.rsi

View file

@ -68,7 +68,7 @@
name: Deckard
parent: [BaseWeaponRevolver, BaseSecurityCommandContraband]
id: WeaponRevolverDeckard
description: A rare, custom-built revolver. Use when there is no time for Voight-Kampff test. Uses .45 magnum ammo.
description: A beautifully machined, custom-built revolver. Used when there is no time for the Voight-Kampff test. Loads 5 rounds of .45 magnum.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Revolvers/deckard.rsi
@ -96,7 +96,7 @@
name: Inspector
parent: [BaseWeaponRevolver, BaseSecurityContraband]
id: WeaponRevolverInspector
description: A detective's best friend. Uses .45 magnum ammo.
description: A single-action revolver manufactured by various companies. It is readily available on the civilian market, making it a popular choice among private investigators. You feel lucky just holding it. Loads 6 rounds of .45 magnum.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Revolvers/inspector.rsi
@ -114,7 +114,7 @@
name: Mateba
parent: [BaseWeaponRevolver, BaseMajorContraband]
id: WeaponRevolverMateba
description: The iconic sidearm of the dreaded death squads. Uses .45 magnum ammo.
description: A modern revolver used by Nanotrasens elite, near mythical Death Squad task force. Its unique trigger action and barrel placement enable a high fire rate with minimal muzzle flip. Many have looked down this barrel, but few have lived to tell of it. Loads 6 rounds of .45 magnum.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Revolvers/mateba.rsi
@ -137,7 +137,7 @@
name: Python
parent: [BaseWeaponRevolver, BaseSyndicateContraband]
id: WeaponRevolverPython
description: A robust revolver favoured by Syndicate agents. Uses .45 magnum ammo.
description: A powerful double-action revolver manufactured by the Syndicate. Loud and flashy, perfect for any agent looking to make a statement. Loads 6 rounds of .45 magnum.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Revolvers/python.rsi
@ -170,7 +170,7 @@
name: pirate revolver
parent: [BaseWeaponRevolver, BaseMinorContraband]
id: WeaponRevolverPirate
description: An odd, old-looking revolver, favoured by pirate crews. Uses .45 magnum ammo.
description: A crude single-action revolver handmade by a space pirate. Old and covered in rust, it somehow still works. Loads 5 rounds of .45 magnum.
components:
- type: Sprite
sprite: Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi

View file

@ -407,6 +407,15 @@
- type: Wires
layoutId: AirlockMedical
- type: entity
parent: WindoorSecureCommandLocked
id: WindoorSecureResearchDirectorLocked
suffix: ResearchDirector, Locked
components:
- type: ContainerFill
containers:
board: [ DoorElectronicsResearchDirector ]
- type: entity
parent: WindoorSecureCargoLocked
id: WindoorSecureSalvageLocked

View file

@ -158,6 +158,9 @@
placement:
mode: SnapgridCenter
components:
- type: SubFloorHide
visibleLayers:
- enum.SubfloorLayers.FirstLayer
- type: Sprite
sprite: Structures/Piping/Atmospherics/gasmixer.rsi
layers:
@ -281,6 +284,8 @@
- type: SubFloorHide
blockInteractions: false
blockAmbience: false
visibleLayers:
- enum.SubfloorLayers.FirstLayer
- type: NodeContainer
nodes:
inlet:

View file

@ -44,6 +44,7 @@
- Traitor
- Revolutionary
- Zombie
- Wizard
- KesslerSyndromeScheduler
- RampingStationEventScheduler
- SpaceTrafficControlEventScheduler
@ -66,6 +67,7 @@
- Traitor
- Revolutionary
- Zombie
- Wizard
- BasicStationEventScheduler
- KesslerSyndromeScheduler
- MeteorSwarmMildScheduler