From 4ee734951455da15eedaf766cee1f64b48959702 Mon Sep 17 00:00:00 2001 From: Guillaume E <262623+quatre@users.noreply.github.com> Date: Sat, 27 Jan 2024 13:06:39 +0100 Subject: [PATCH 1/9] Keep reagent dispenser inventory ordered (#24304) * Keep reagent dispenser inventory ordered This way, reagents wont be "moving around" in the UI when juggling jugs. The reagent dispensers will also show what reagents their storage slots contain if jugs are not labelled. * Move sorting client-side * Revert "Keep reagent dispenser inventory ordered" This reverts commit 3a1fc2e36d593937d4ecc581ae5a617a273a9d1c. --- Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs index 332de34345c807..a36cc2fe54f5b3 100644 --- a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs +++ b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs @@ -58,6 +58,8 @@ public void UpdateReagentsList(List x.Value.Key.CompareTo(y.Value.Key)); foreach (KeyValuePair> entry in inventory) { From 34eb6914489a368dd85f1e3e8d2152c6e36d3ed5 Mon Sep 17 00:00:00 2001 From: Kara Date: Sat, 27 Jan 2024 05:08:50 -0700 Subject: [PATCH 2/9] Default navmap to show departments (#24613) --- Content.Client/Pinpointer/UI/NavMapControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Pinpointer/UI/NavMapControl.cs b/Content.Client/Pinpointer/UI/NavMapControl.cs index 320c5f899aca9f..3b426e73d89143 100644 --- a/Content.Client/Pinpointer/UI/NavMapControl.cs +++ b/Content.Client/Pinpointer/UI/NavMapControl.cs @@ -94,7 +94,7 @@ public partial class NavMapControl : MapGridControl Margin = new Thickness(4f, 0f), VerticalAlignment = VAlignment.Center, HorizontalAlignment = HAlignment.Center, - Pressed = false, + Pressed = true, }; public NavMapControl() : base(MinDisplayedRange, MaxDisplayedRange, DefaultDisplayedRange) From 639a453a39014cc2a53cf8cef6899d2a7f207540 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 27 Jan 2024 12:09:56 +0000 Subject: [PATCH 3/9] Automatic changelog update --- Resources/Changelog/Changelog.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1195be8934e4cb..2744895768749e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,10 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Removed gas tank throwing damage. - type: Remove - id: 5302 - time: '2023-12-10T14:11:26.0000000+00:00' - author: Nairodian changes: - message: Adjusted welder blindness to be much less forgiving. @@ -3818,3 +3812,10 @@ id: 5802 time: '2024-01-27T03:53:09.0000000+00:00' url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24577 +- author: mirrorcult + changes: + - message: Navmap now defaults to showing departments + type: Tweak + id: 5803 + time: '2024-01-27T12:08:50.0000000+00:00' + url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24613 From be09538f28aeefc9b2522423a090222a2d322a31 Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Sat, 27 Jan 2024 07:12:53 -0500 Subject: [PATCH 4/9] Repairable vending machines (#24603) * Add Repairable to vending machines * Removed fuelcost (outdated) --- .../Entities/Structures/Machines/vending_machines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml index 0cf1cc9de0880e..0bfb173c8019ee 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/vending_machines.yml @@ -53,6 +53,8 @@ - !type:PlaySoundBehavior sound: collection: MetalGlassBreak + - type: Repairable + doAfterDelay: 8 - type: ActivatableUI key: enum.VendingMachineUiKey.Key - type: ActivatableUIRequiresPower From 23999b3d6947ae9f62c4b10d06f452ce20f7a071 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 27 Jan 2024 12:13:58 +0000 Subject: [PATCH 5/9] Automatic changelog update --- Resources/Changelog/Changelog.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 2744895768749e..840328f8d8a631 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,10 +1,4 @@ Entries: -- author: Nairodian - changes: - - message: Adjusted welder blindness to be much less forgiving. - type: Tweak - id: 5303 - time: '2023-12-10T23:10:07.0000000+00:00' - author: KittenColony changes: - message: Added various gauze wraps to most species in the form of markings @@ -3819,3 +3813,10 @@ id: 5803 time: '2024-01-27T12:08:50.0000000+00:00' url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24613 +- author: Tayrtahn + changes: + - message: Vending machines can now be repaired with a welder. + type: Tweak + id: 5804 + time: '2024-01-27T12:12:53.0000000+00:00' + url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24603 From a923beb21bf1cd3df2d77d2b8c6b55b4f4d50a87 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Sat, 27 Jan 2024 15:15:05 +0300 Subject: [PATCH 6/9] Gravity anomaly rework (#24452) * balance * gorilla gauntlet fix * magboots update * some more buff * randomwalk speed scales with severity * nerf * content * Revert "content" --- .../Anomaly/Effects/GravityAnomalySystem.cs | 35 +++++++----- .../EntitySystems/GravityWellSystem.cs | 4 ++ .../Components/GravityAnomalyComponent.cs | 54 +++++++++++++++---- .../Components/MeleeThrowOnHitComponent.cs | 7 +++ .../Weapons/Melee/MeleeThrowOnHitSystem.cs | 3 +- .../Structures/Specific/Anomaly/anomalies.yml | 8 +++ 6 files changed, 88 insertions(+), 23 deletions(-) diff --git a/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs b/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs index a928add35b4a74..02cd0aafc6239e 100644 --- a/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/GravityAnomalySystem.cs @@ -1,4 +1,5 @@ -using Content.Server.Singularity.Components; +using Content.Server.Physics.Components; +using Content.Server.Singularity.Components; using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Effects; using Content.Shared.Anomaly.Effects.Components; @@ -19,21 +20,31 @@ public override void Initialize() SubscribeLocalEvent(OnStabilityChanged); } - private void OnSeverityChanged(EntityUid uid, GravityAnomalyComponent component, ref AnomalySeverityChangedEvent args) + private void OnSeverityChanged(Entity anomaly, ref AnomalySeverityChangedEvent args) { - if (TryComp(uid, out var radSource)) - radSource.Intensity = component.MaxRadiationIntensity * args.Severity; + if (TryComp(anomaly, out var radSource)) + radSource.Intensity = anomaly.Comp.MaxRadiationIntensity * args.Severity; - if (!TryComp(uid, out var gravityWell)) - return; - var accel = (component.MaxAccel - component.MinAccel) * args.Severity + component.MinAccel; - gravityWell.BaseRadialAcceleration = accel; - gravityWell.BaseTangentialAcceleration = accel * 0.2f; + if (TryComp(anomaly, out var gravityWell)) + { + var accel = MathHelper.Lerp(anomaly.Comp.MinAccel, anomaly.Comp.MaxAccel, args.Severity); + gravityWell.BaseRadialAcceleration = accel; + + var radialAccel = MathHelper.Lerp(anomaly.Comp.MinRadialAccel, anomaly.Comp.MaxRadialAccel, args.Severity); + gravityWell.BaseTangentialAcceleration = radialAccel; + } + + if (TryComp(anomaly, out var randomWalk)) + { + var speed = MathHelper.Lerp(anomaly.Comp.MinSpeed, anomaly.Comp.MaxSpeed, args.Severity); + randomWalk.MinSpeed = speed - anomaly.Comp.SpeedVariation; + randomWalk.MaxSpeed = speed + anomaly.Comp.SpeedVariation; + } } - private void OnStabilityChanged(EntityUid uid, GravityAnomalyComponent component, ref AnomalyStabilityChangedEvent args) + private void OnStabilityChanged(Entity anomaly, ref AnomalyStabilityChangedEvent args) { - if (TryComp(uid, out var gravityWell)) - gravityWell.MaxRange = component.MaxGravityWellRange * args.Stability; + if (TryComp(anomaly, out var gravityWell)) + gravityWell.MaxRange = anomaly.Comp.MaxGravityWellRange * args.Stability; } } diff --git a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs index 2ba4dbd41cbb03..ce4334391db6e7 100644 --- a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs +++ b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Atmos.Components; using Content.Server.Singularity.Components; using Content.Shared.Ghost; using Content.Shared.Singularity.EntitySystems; @@ -192,6 +193,9 @@ public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange, in continue; } + if (TryComp(entity, out var movedPressure) && !movedPressure.Enabled) //Ignore magboots users + continue; + if(!CanGravPulseAffect(entity)) continue; diff --git a/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs index ac2ae32dff6092..7c6dccea862478 100644 --- a/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs +++ b/Content.Shared/Anomaly/Effects/Components/GravityAnomalyComponent.cs @@ -1,4 +1,4 @@ -using Robust.Shared.GameStates; +using Robust.Shared.GameStates; namespace Content.Shared.Anomaly.Effects.Components; @@ -9,47 +9,81 @@ public sealed partial class GravityAnomalyComponent : Component /// The maximumum size the GravityWellComponent MaxRange can be. /// Is scaled linearly with stability. /// - [DataField("maxGravityWellRange"), ViewVariables(VVAccess.ReadWrite)] - public float MaxGravityWellRange = 8f; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxGravityWellRange = 10f; /// /// The maximum distance from which the anomaly /// can throw you via a pulse. /// - [DataField("maxThrowRange"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float MaxThrowRange = 5f; /// /// The maximum strength the anomaly /// can throw you via a pulse /// - [DataField("maxThrowStrength"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float MaxThrowStrength = 10; /// /// The maximum Intensity of the RadiationSourceComponent. /// Is scaled linearly with stability. /// - [DataField("maxRadiationIntensity"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float MaxRadiationIntensity = 3f; /// /// The minimum acceleration value for GravityWellComponent /// Is scaled linearly with stability. /// - [DataField("minAccel"), ViewVariables(VVAccess.ReadWrite)] - public float MinAccel = 1f; + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MinAccel = 0f; /// /// The maximum acceleration value for GravityWellComponent /// Is scaled linearly with stability. /// - [DataField("maxAccel"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float MaxAccel = 5f; + /// + /// The minimum acceleration value for GravityWellComponent + /// Is scaled linearly with stability. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MinRadialAccel = 0f; + + /// + /// The maximum acceleration value for GravityWellComponent + /// Is scaled linearly with stability. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxRadialAccel = 5f; + + /// + /// The maximum speed for RandomWalkComponent + /// Is scaled linearly with severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MinSpeed = 0.1f; + + /// + /// The maximum speed for RandomWalkComponent + /// Is scaled linearly with severity. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float MaxSpeed = 1.0f; + + /// + /// Random +- speed modifier + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SpeedVariation = 0.1f; + /// /// The range around the anomaly that will be spaced on supercritical. /// - [DataField("spaceRange"), ViewVariables(VVAccess.ReadWrite)] + [DataField, ViewVariables(VVAccess.ReadWrite)] public float SpaceRange = 3f; } diff --git a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs index ef8ee3f89ce089..82ffc5e51fc662 100644 --- a/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs +++ b/Content.Shared/Weapons/Melee/Components/MeleeThrowOnHitComponent.cs @@ -1,5 +1,6 @@ using System.Numerics; using Robust.Shared.GameStates; +using Robust.Shared.Physics.Components; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Weapons.Melee.Components; @@ -89,6 +90,12 @@ public sealed partial class MeleeThrownComponent : Component [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoNetworkedField] public TimeSpan MinLifetimeTime; + + /// + /// the status to which the entity will return when the thrown ends + /// + [DataField] + public BodyStatus PreviousStatus; } /// diff --git a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs index d755f7a0b4e0c0..fc364286549ef6 100644 --- a/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs +++ b/Content.Shared/Weapons/Melee/MeleeThrowOnHitSystem.cs @@ -71,6 +71,7 @@ private void OnThrownStartup(Entity ent, ref ComponentStar (body.BodyType & (BodyType.Dynamic | BodyType.KinematicController)) == 0x0) return; + comp.PreviousStatus = body.BodyStatus; comp.ThrownEndTime = _timing.CurTime + TimeSpan.FromSeconds(comp.Lifetime); comp.MinLifetimeTime = _timing.CurTime + TimeSpan.FromSeconds(comp.MinLifetime); _physics.SetBodyStatus(body, BodyStatus.InAir); @@ -82,7 +83,7 @@ private void OnThrownStartup(Entity ent, ref ComponentStar private void OnThrownShutdown(Entity ent, ref ComponentShutdown args) { if (TryComp(ent, out var body)) - _physics.SetBodyStatus(body, BodyStatus.OnGround); + _physics.SetBodyStatus(body,ent.Comp.PreviousStatus); var ev = new MeleeThrowOnHitEndEvent(); RaiseLocalEvent(ent, ref ev); } diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml index 56c970929cbff7..e357769aa50ba0 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml @@ -102,6 +102,14 @@ - type: GravityAnomaly - type: GravityWell - type: RadiationSource + - type: Physics + bodyType: Dynamic + bodyStatus: InAir + - type: CanMoveInAir + - type: RandomWalk + - type: SingularityDistortion + intensity: 1000 + falloffPower: 2.7 - type: entity id: AnomalyElectricity From 7e16ee0b55fdef2ce77b13cd72dbc00b63d776c4 Mon Sep 17 00:00:00 2001 From: avery <51971268+graevy@users.noreply.github.com> Date: Sat, 27 Jan 2024 05:51:24 -0800 Subject: [PATCH 7/9] Hallway textscreens (#24189) * hallway screen refactor pending comms console support * comms console broadcasts * screen and timer localization --- ...CommunicationsConsoleBoundUserInterface.cs | 9 ++ .../UI/CommunicationsConsoleMenu.xaml | 1 + .../UI/CommunicationsConsoleMenu.xaml.cs | 3 + Content.Client/TextScreen/TextScreenSystem.cs | 75 +++++++++--- .../TextScreen/TextScreenVisualsComponent.cs | 3 +- .../CommunicationsConsoleComponent.cs | 14 ++- .../CommunicationsConsoleSystem.cs | 26 ++++ Content.Server/RoundEnd/RoundEndSystem.cs | 16 +-- .../Screens/Components/ScreenComponent.cs | 35 ++++++ .../Screens/Systems/ScreenSystem.cs | 114 ++++++++++++++++++ .../Components/ShuttleTimerComponent.cs | 24 ---- .../Shuttles/Systems/ArrivalsSystem.cs | 1 + .../Systems/EmergencyShuttleSystem.Console.cs | 1 + .../Systems/EmergencyShuttleSystem.cs | 13 +- .../Shuttles/Systems/ShuttleTimerSystem.cs | 69 ----------- .../SharedCommunicationsConsoleComponent.cs | 14 ++- .../TextScreen/TextScreenVisuals.cs | 20 +-- .../communications-console-component.ftl | 1 + Resources/Locale/en-US/shuttles/screens.ftl | 2 + Resources/Locale/en-US/shuttles/timer.ftl | 9 ++ .../Machines/Computers/computers.yml | 2 + .../Entities/Structures/Wallmounts/screen.yml | 7 +- .../Entities/Structures/Wallmounts/timer.yml | 1 + 23 files changed, 318 insertions(+), 142 deletions(-) create mode 100644 Content.Server/Screens/Components/ScreenComponent.cs create mode 100644 Content.Server/Screens/Systems/ScreenSystem.cs delete mode 100644 Content.Server/Shuttles/Components/ShuttleTimerComponent.cs delete mode 100644 Content.Server/Shuttles/Systems/ShuttleTimerSystem.cs create mode 100644 Resources/Locale/en-US/shuttles/screens.ftl diff --git a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs index 07492b310f3d70..1c94d32bf8d17d 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs +++ b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs @@ -16,6 +16,8 @@ public sealed class CommunicationsConsoleBoundUserInterface : BoundUserInterface [ViewVariables] public bool CanAnnounce { get; private set; } + [ViewVariables] + public bool CanBroadcast { get; private set; } [ViewVariables] public bool CanCall { get; private set; } @@ -71,6 +73,11 @@ public void AnnounceButtonPressed(string message) SendMessage(new CommunicationsConsoleAnnounceMessage(msg)); } + public void BroadcastButtonPressed(string message) + { + SendMessage(new CommunicationsConsoleBroadcastMessage(message)); + } + public void CallShuttle() { SendMessage(new CommunicationsConsoleCallEmergencyShuttleMessage()); @@ -89,6 +96,7 @@ protected override void UpdateState(BoundUserInterfaceState state) return; CanAnnounce = commsState.CanAnnounce; + CanBroadcast = commsState.CanBroadcast; CanCall = commsState.CanCall; _expectedCountdownTime = commsState.ExpectedCountdownEnd; CountdownStarted = commsState.CountdownStarted; @@ -102,6 +110,7 @@ protected override void UpdateState(BoundUserInterfaceState state) _menu.AlertLevelButton.Disabled = !AlertLevelSelectable; _menu.EmergencyShuttleButton.Disabled = !CanCall; _menu.AnnounceButton.Disabled = !CanAnnounce; + _menu.BroadcastButton.Disabled = !CanBroadcast; } } diff --git a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml index 86c0b4e2d5337b..ea2f77d457d781 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml +++ b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml @@ -5,6 +5,7 @@ + /// + /// The appearance updates are batched; order matters for both sender and receiver. + /// protected override void OnAppearanceChange(EntityUid uid, TextScreenVisualsComponent component, ref AppearanceChangeEvent args) { if (!Resolve(uid, ref args.Sprite)) return; - var appearance = args.Component; + if (args.AppearanceData.TryGetValue(TextScreenVisuals.Color, out var color) && color is Color) + component.Color = (Color) color; + + // DefaultText: broadcast updates from comms consoles + // ScreenText: the text accompanying shuttle timers e.g. "ETA" + if (args.AppearanceData.TryGetValue(TextScreenVisuals.DefaultText, out var newDefault) && newDefault is string) + { + string?[] defaultText = SegmentText((string) newDefault, component); + component.Text = defaultText; + component.TextToDraw = defaultText; + ResetText(uid, component); + BuildTextLayers(uid, component, args.Sprite); + DrawLayers(uid, component.LayerStatesToDraw); + } + if (args.AppearanceData.TryGetValue(TextScreenVisuals.ScreenText, out var text) && text is string) + { + component.TextToDraw = SegmentText((string) text, component); + ResetText(uid, component); + BuildTextLayers(uid, component, args.Sprite); + DrawLayers(uid, component.LayerStatesToDraw); + } - if (AppearanceSystem.TryGetData(uid, TextScreenVisuals.TargetTime, out TimeSpan time, appearance)) + if (args.AppearanceData.TryGetValue(TextScreenVisuals.TargetTime, out var time) && time is TimeSpan) { - if (time > _gameTiming.CurTime) + var target = (TimeSpan) time; + if (target > _gameTiming.CurTime) { var timer = EnsureComp(uid); - timer.Target = time; + timer.Target = target; BuildTimerLayers(uid, timer, component); DrawLayers(uid, timer.LayerStatesToDraw); } @@ -120,14 +144,6 @@ protected override void OnAppearanceChange(EntityUid uid, TextScreenVisualsCompo OnTimerFinish(uid, component); } } - - if (AppearanceSystem.TryGetData(uid, TextScreenVisuals.ScreenText, out string?[] text, appearance)) - { - component.TextToDraw = text; - ResetText(uid, component); - BuildTextLayers(uid, component, args.Sprite); - DrawLayers(uid, component.LayerStatesToDraw); - } } /// @@ -151,10 +167,28 @@ private void OnTimerFinish(EntityUid uid, TextScreenVisualsComponent screen) DrawLayers(uid, screen.LayerStatesToDraw); } + /// + /// Converts string to string?[] based on + /// and . + /// + private string?[] SegmentText(string text, TextScreenVisualsComponent component) + { + int segment = component.RowLength; + var segmented = new string?[Math.Min(component.Rows, (text.Length - 1) / segment + 1)]; + + // populate segmented with a string sliding window using Substring. + // (Substring(5, 5) will return the 5 characters starting from 5th index) + // the Mins are for the very short string case, the very long string case, and to not OOB the end of the string. + for (int i = 0; i < Math.Min(text.Length, segment * component.Rows); i += segment) + segmented[i / segment] = text.Substring(i, Math.Min(text.Length - i, segment)).Trim(); + + return segmented; + } + /// /// Clears , and instantiates new blank defaults. /// - public void ResetText(EntityUid uid, TextScreenVisualsComponent component, SpriteComponent? sprite = null) + private void ResetText(EntityUid uid, TextScreenVisualsComponent component, SpriteComponent? sprite = null) { if (!Resolve(uid, ref sprite)) return; @@ -167,11 +201,12 @@ public void ResetText(EntityUid uid, TextScreenVisualsComponent component, Sprit for (var row = 0; row < component.Rows; row++) for (var i = 0; i < component.RowLength; i++) { - sprite.LayerMapReserveBlank(TextMapKey + row + i); - component.LayerStatesToDraw.Add(TextMapKey + row + i, null); - sprite.LayerSetRSI(TextMapKey + row + i, new ResPath(TextPath)); - sprite.LayerSetColor(TextMapKey + row + i, component.Color); - sprite.LayerSetState(TextMapKey + row + i, DefaultState); + var key = TextMapKey + row + i; + sprite.LayerMapReserveBlank(key); + component.LayerStatesToDraw.Add(key, null); + sprite.LayerSetRSI(key, new ResPath(TextPath)); + sprite.LayerSetColor(key, component.Color); + sprite.LayerSetState(key, DefaultState); } } @@ -182,7 +217,7 @@ public void ResetText(EntityUid uid, TextScreenVisualsComponent component, Sprit /// /// Remember to set to a string?[] first. /// - public void BuildTextLayers(EntityUid uid, TextScreenVisualsComponent component, SpriteComponent? sprite = null) + private void BuildTextLayers(EntityUid uid, TextScreenVisualsComponent component, SpriteComponent? sprite = null) { if (!Resolve(uid, ref sprite)) return; @@ -211,7 +246,7 @@ public void BuildTextLayers(EntityUid uid, TextScreenVisualsComponent component, /// /// Populates timer.LayerStatesToDraw & the sprite component's layer dict with calculated offsets. /// - public void BuildTimerLayers(EntityUid uid, TextScreenTimerComponent timer, TextScreenVisualsComponent screen) + private void BuildTimerLayers(EntityUid uid, TextScreenTimerComponent timer, TextScreenVisualsComponent screen) { if (!TryComp(uid, out var sprite)) return; diff --git a/Content.Client/TextScreen/TextScreenVisualsComponent.cs b/Content.Client/TextScreen/TextScreenVisualsComponent.cs index cf3619024c6060..e74f38f4320e8c 100644 --- a/Content.Client/TextScreen/TextScreenVisualsComponent.cs +++ b/Content.Client/TextScreen/TextScreenVisualsComponent.cs @@ -1,5 +1,4 @@ using System.Numerics; -using Content.Shared.TextScreen; using Robust.Client.Graphics; namespace Content.Client.TextScreen; @@ -37,7 +36,7 @@ public sealed partial class TextScreenVisualsComponent : Component /// Number of rows of text this screen can render. /// [DataField("rows")] - public int Rows = 1; + public int Rows = 2; /// /// Spacing between each text row diff --git a/Content.Server/Communications/CommunicationsConsoleComponent.cs b/Content.Server/Communications/CommunicationsConsoleComponent.cs index 52f3087b65809b..56c8e9504b1b07 100644 --- a/Content.Server/Communications/CommunicationsConsoleComponent.cs +++ b/Content.Server/Communications/CommunicationsConsoleComponent.cs @@ -12,10 +12,14 @@ public sealed partial class CommunicationsConsoleComponent : SharedCommunication /// /// Remaining cooldown between making announcements. /// - [ViewVariables(VVAccess.ReadWrite)] + [ViewVariables] [DataField] public float AnnouncementCooldownRemaining; + [ViewVariables] + [DataField] + public float BroadcastCooldownRemaining; + /// /// Fluent ID for the announcement title /// If a Fluent ID isn't found, just uses the raw string @@ -27,28 +31,28 @@ public sealed partial class CommunicationsConsoleComponent : SharedCommunication /// /// Announcement color /// - [ViewVariables(VVAccess.ReadWrite)] + [ViewVariables] [DataField] public Color Color = Color.Gold; /// /// Time in seconds between announcement delays on a per-console basis /// - [ViewVariables(VVAccess.ReadWrite)] + [ViewVariables] [DataField] public int Delay = 90; /// /// Time in seconds of announcement cooldown when a new console is created on a per-console basis /// - [ViewVariables(VVAccess.ReadWrite)] + [ViewVariables] [DataField] public int InitialDelay = 30; /// /// Can call or recall the shuttle /// - [ViewVariables(VVAccess.ReadWrite)] + [ViewVariables] [DataField] public bool CanShuttle = true; diff --git a/Content.Server/Communications/CommunicationsConsoleSystem.cs b/Content.Server/Communications/CommunicationsConsoleSystem.cs index 6a4cd23ba12b4e..4fa60563bddba8 100644 --- a/Content.Server/Communications/CommunicationsConsoleSystem.cs +++ b/Content.Server/Communications/CommunicationsConsoleSystem.cs @@ -3,9 +3,14 @@ using Content.Server.Administration.Logs; using Content.Server.AlertLevel; using Content.Server.Chat.Systems; +using Content.Server.DeviceNetwork; +using Content.Server.DeviceNetwork.Components; +using Content.Server.DeviceNetwork.Systems; using Content.Server.Interaction; using Content.Server.Popups; using Content.Server.RoundEnd; +using Content.Server.Screens; +using Content.Server.Screens.Components; using Content.Server.Shuttles.Systems; using Content.Server.Station.Systems; using Content.Shared.Access.Components; @@ -27,6 +32,7 @@ public sealed class CommunicationsConsoleSystem : EntitySystem [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!; [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!; [Dependency] private readonly EmergencyShuttleSystem _emergency = default!; [Dependency] private readonly IdCardSystem _idCardSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; @@ -49,6 +55,7 @@ public override void Initialize() // Messages from the BUI SubscribeLocalEvent(OnSelectAlertLevelMessage); SubscribeLocalEvent(OnAnnounceMessage); + SubscribeLocalEvent(OnBroadcastMessage); SubscribeLocalEvent(OnCallShuttleMessage); SubscribeLocalEvent(OnRecallShuttleMessage); @@ -162,6 +169,7 @@ public void UpdateCommsConsoleInterface(EntityUid uid, CommunicationsConsoleComp _uiSystem.SetUiState(ui, new CommunicationsConsoleInterfaceState( CanAnnounce(comp), + CanBroadcast(comp), CanCallOrRecall(comp), levels, currentLevel, @@ -175,6 +183,11 @@ private static bool CanAnnounce(CommunicationsConsoleComponent comp) return comp.AnnouncementCooldownRemaining <= 0f; } + private static bool CanBroadcast(CommunicationsConsoleComponent comp) + { + return comp.AnnouncementCooldownRemaining <= 0f; + } + private bool CanUse(EntityUid user, EntityUid console) { // This shouldn't technically be possible because of BUI but don't trust client. @@ -278,6 +291,19 @@ private void OnAnnounceMessage(EntityUid uid, CommunicationsConsoleComponent com _adminLogger.Add(LogType.Chat, LogImpact.Low, $"{ToPrettyString(message.Session.AttachedEntity.Value):player} has sent the following station announcement: {msg}"); } + private void OnBroadcastMessage(EntityUid uid, CommunicationsConsoleComponent component, CommunicationsConsoleBroadcastMessage message) + { + if (!TryComp(uid, out var net)) + return; + + var payload = new NetworkPayload + { + [ScreenMasks.Text] = message.Message + }; + + _deviceNetworkSystem.QueuePacket(uid, null, payload, net.TransmitFrequency); + } + private void OnCallShuttleMessage(EntityUid uid, CommunicationsConsoleComponent comp, CommunicationsConsoleCallEmergencyShuttleMessage message) { if (!CanCallOrRecall(comp)) diff --git a/Content.Server/RoundEnd/RoundEndSystem.cs b/Content.Server/RoundEnd/RoundEndSystem.cs index 88c55154a320e9..10d4bea8b54053 100644 --- a/Content.Server/RoundEnd/RoundEndSystem.cs +++ b/Content.Server/RoundEnd/RoundEndSystem.cs @@ -8,6 +8,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; using Content.Server.GameTicking; +using Content.Server.Screens.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Systems; using Content.Server.Station.Components; @@ -16,7 +17,6 @@ using Content.Shared.GameTicking; using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; -using Robust.Shared.Map; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -34,14 +34,11 @@ public sealed class RoundEndSystem : EntitySystem [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly IMapManager _mapManager = default!; - [Dependency] private readonly IPrototypeManager _protoManager = default!; [Dependency] private readonly ChatSystem _chatSystem = default!; [Dependency] private readonly GameTicker _gameTicker = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!; [Dependency] private readonly EmergencyShuttleSystem _shuttle = default!; - [Dependency] private readonly ShuttleTimerSystem _shuttleTimerSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly StationSystem _stationSystem = default!; @@ -112,13 +109,9 @@ private void Reset() /// public EntityUid? GetCentcomm() { - if (AllEntityQuery() - .MoveNext(out var centcomm, out var xform)) - { - return xform.MapUid; - } + AllEntityQuery().MoveNext(out var centcomm); - return null; + return centcomm == null ? null : centcomm.MapEntity; } public bool CanCallOrRecall() @@ -243,7 +236,7 @@ public void CancelRoundEndCountdown(EntityUid? requester = null, bool checkCoold ActivateCooldown(); RaiseLocalEvent(RoundEndSystemChangedEvent.Default); - // remove all active shuttle timers + // remove active clientside evac shuttle timers by zeroing the target time var zero = TimeSpan.Zero; var shuttle = _shuttle.GetShuttle(); if (shuttle != null && TryComp(shuttle, out var net)) @@ -256,7 +249,6 @@ public void CancelRoundEndCountdown(EntityUid? requester = null, bool checkCoold [ShuttleTimerMasks.ShuttleTime] = zero, [ShuttleTimerMasks.SourceTime] = zero, [ShuttleTimerMasks.DestTime] = zero, - [ShuttleTimerMasks.Text] = new string?[] { string.Empty, string.Empty } }; _deviceNetworkSystem.QueuePacket(shuttle.Value, null, payload, net.TransmitFrequency); } diff --git a/Content.Server/Screens/Components/ScreenComponent.cs b/Content.Server/Screens/Components/ScreenComponent.cs new file mode 100644 index 00000000000000..1ed760874027b3 --- /dev/null +++ b/Content.Server/Screens/Components/ScreenComponent.cs @@ -0,0 +1,35 @@ +namespace Content.Server.Screens.Components; + +[RegisterComponent] +public sealed partial class ScreenComponent : Component +{ + +} + +/// +/// Player-facing hashable string consts for NetworkPayload +/// +public sealed class ScreenMasks +{ + public static readonly string Text = Loc.GetString("screen-text"); + public static readonly string Color = Loc.GetString("screen-color"); +} + +/// +/// Player-facing hashable string consts for NetworkPayload +/// +public sealed class ShuttleTimerMasks +{ + public static readonly string ShuttleTime = Loc.GetString("shuttle-timer-shuttle-time"); + public static readonly string DestTime = Loc.GetString("shuttle-timer-dest-time"); + public static readonly string SourceTime = Loc.GetString("shuttle-timer-source-time"); + public static readonly string ShuttleMap = Loc.GetString("shuttle-timer-shuttle-map"); + public static readonly string SourceMap = Loc.GetString("shuttle-timer-source-map"); + public static readonly string DestMap = Loc.GetString("shuttle-timer-dest-map"); + public static readonly string Docked = Loc.GetString("shuttle-timer-docked"); + public static readonly string ETA = Loc.GetString("shuttle-timer-eta"); + public static readonly string ETD = Loc.GetString("shuttle-timer-etd"); + public static readonly string Bye = Loc.GetString("shuttle-timer-bye"); + public static readonly string Kill = Loc.GetString("shuttle-timer-kill"); +} + diff --git a/Content.Server/Screens/Systems/ScreenSystem.cs b/Content.Server/Screens/Systems/ScreenSystem.cs new file mode 100644 index 00000000000000..19790f64d5b1f2 --- /dev/null +++ b/Content.Server/Screens/Systems/ScreenSystem.cs @@ -0,0 +1,114 @@ +using Content.Shared.TextScreen; +using Content.Server.Screens.Components; +using Content.Server.DeviceNetwork.Components; +using Content.Server.DeviceNetwork.Systems; +using Robust.Shared.Timing; + + +namespace Content.Server.Screens.Systems; + +/// +/// Controls the wallmounted screens on stations and shuttles displaying e.g. FTL duration, ETA +/// +public sealed class ScreenSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPacketReceived); + } + + /// + /// Calls either a normal screen text update or shuttle timer update based on the presence of + /// in + /// + private void OnPacketReceived(EntityUid uid, ScreenComponent component, DeviceNetworkPacketEvent args) + { + if (args.Data.TryGetValue(ShuttleTimerMasks.ShuttleMap, out _)) + ShuttleTimer(uid, component, args); + else + ScreenText(uid, component, args); + } + + /// + /// Send a text update to every screen on the same MapUid as the originating comms console. + /// + private void ScreenText(EntityUid uid, ScreenComponent component, DeviceNetworkPacketEvent args) + { + // don't allow text updates if there's an active timer + // (and just check here so the server doesn't have to track them) + if (_appearanceSystem.TryGetData(uid, TextScreenVisuals.TargetTime, out TimeSpan target) + && target > _gameTiming.CurTime) + return; + + var screenMap = Transform(uid).MapUid; + var argsMap = Transform(args.Sender).MapUid; + + if (screenMap != null + && argsMap != null + && screenMap == argsMap + && args.Data.TryGetValue(ScreenMasks.Text, out string? text) + && text != null + ) + { + _appearanceSystem.SetData(uid, TextScreenVisuals.DefaultText, text); + } + } + + /// + /// Determines if/how a timer packet affects this screen. + /// Currently there are 2 broadcast domains: Arrivals, and every other screen. + /// Domain is determined by the on each timer. + /// Each broadcast domain is divided into subnets. Screen MapUid determines subnet. + /// Subnets are the shuttle, source, and dest. Source/dest change each jump. + /// This is required to send different timers to the shuttle/terminal/station. + /// + private void ShuttleTimer(EntityUid uid, ScreenComponent component, DeviceNetworkPacketEvent args) + { + var timerXform = Transform(uid); + + // no false positives. + if (timerXform.MapUid == null) + return; + + string key; + args.Data.TryGetValue(ShuttleTimerMasks.ShuttleMap, out EntityUid? shuttleMap); + args.Data.TryGetValue(ShuttleTimerMasks.SourceMap, out EntityUid? source); + args.Data.TryGetValue(ShuttleTimerMasks.DestMap, out EntityUid? dest); + args.Data.TryGetValue(ShuttleTimerMasks.Docked, out bool docked); + string text = docked ? ShuttleTimerMasks.ETD : ShuttleTimerMasks.ETA; + + switch (timerXform.MapUid) + { + // sometimes the timer transforms on FTL shuttles have a hyperspace mapuid, so matching by grid works as a fallback. + case var local when local == shuttleMap || timerXform.GridUid == shuttleMap: + key = ShuttleTimerMasks.ShuttleTime; + break; + case var origin when origin == source: + key = ShuttleTimerMasks.SourceTime; + break; + case var remote when remote == dest: + key = ShuttleTimerMasks.DestTime; + text = ShuttleTimerMasks.ETA; + break; + default: + return; + } + + if (!args.Data.TryGetValue(key, out TimeSpan duration)) + return; + + if (args.Data.TryGetValue(ScreenMasks.Text, out string? label) && label != null) + text = label; + + _appearanceSystem.SetData(uid, TextScreenVisuals.ScreenText, text); + _appearanceSystem.SetData(uid, TextScreenVisuals.TargetTime, _gameTiming.CurTime + duration); + + if (args.Data.TryGetValue(ScreenMasks.Color, out Color color)) + _appearanceSystem.SetData(uid, TextScreenVisuals.Color, color); + } +} diff --git a/Content.Server/Shuttles/Components/ShuttleTimerComponent.cs b/Content.Server/Shuttles/Components/ShuttleTimerComponent.cs deleted file mode 100644 index 03b4f05c14f258..00000000000000 --- a/Content.Server/Shuttles/Components/ShuttleTimerComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Content.Server.Shuttles.Components; - -[RegisterComponent] -public sealed partial class ShuttleTimerComponent : Component -{ - -} - -/// -/// Awkward hashable string consts because NetworkPayload requires string keys -/// TODO: Refactor NetworkPayload to accept bytes from enums? -/// -public sealed class ShuttleTimerMasks -{ - public static readonly string ShuttleTime = "ShuttleTime"; - public static readonly string DestTime = "DestTime"; - public static readonly string SourceTime = "SourceTime"; - public static readonly string ShuttleMap = "ShuttleMap"; - public static readonly string SourceMap = "SourceMap"; - public static readonly string DestMap = "DestMap"; - public static readonly string Docked = "Docked"; - public static readonly string Text = "Text"; -} - diff --git a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs index 41f455cea1fa84..f1f52c224152da 100644 --- a/Content.Server/Shuttles/Systems/ArrivalsSystem.cs +++ b/Content.Server/Shuttles/Systems/ArrivalsSystem.cs @@ -8,6 +8,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; using Content.Server.Salvage; +using Content.Server.Screens.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; using Content.Server.Spawners.Components; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs index d14c5be43887f6..3b9a12a3310ca5 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.Console.cs @@ -1,6 +1,7 @@ using System.Threading; using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork.Components; +using Content.Server.Screens.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; using Content.Server.UserInterface; diff --git a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs index eb205cae63381a..d984c727376dd6 100644 --- a/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs @@ -11,6 +11,7 @@ using Content.Server.GameTicking.Events; using Content.Server.Popups; using Content.Server.RoundEnd; +using Content.Server.Screens.Components; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; using Content.Server.Station.Components; @@ -235,8 +236,18 @@ private void OnEmergencyFTLComplete(EntityUid uid, EmergencyShuttleComponent com [ShuttleTimerMasks.ShuttleTime] = countdownTime, [ShuttleTimerMasks.SourceTime] = countdownTime, [ShuttleTimerMasks.DestTime] = countdownTime, - [ShuttleTimerMasks.Text] = new string?[] { "BYE!" } }; + + // by popular request + // https://discord.com/channels/310555209753690112/770682801607278632/1189989482234126356 + if (_random.Next(1000) == 0) + { + payload.Add(ScreenMasks.Text, ShuttleTimerMasks.Kill); + payload.Add(ScreenMasks.Color, Color.Red); + } + else + payload.Add(ScreenMasks.Text, ShuttleTimerMasks.Bye); + _deviceNetworkSystem.QueuePacket(shuttle, null, payload, net.TransmitFrequency); } } diff --git a/Content.Server/Shuttles/Systems/ShuttleTimerSystem.cs b/Content.Server/Shuttles/Systems/ShuttleTimerSystem.cs deleted file mode 100644 index 9a098cd17ac836..00000000000000 --- a/Content.Server/Shuttles/Systems/ShuttleTimerSystem.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Content.Shared.TextScreen; -using Content.Server.Shuttles.Components; -using Content.Server.DeviceNetwork.Systems; -using Robust.Shared.Timing; - - -namespace Content.Server.Shuttles.Systems; - -/// -/// Controls the wallmounted screens on stations and shuttles displaying e.g. FTL duration, ETA -/// -public sealed class ShuttleTimerSystem : EntitySystem -{ - [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnPacketReceived); - } - - /// - /// Determines if/how a broadcast packet affects this timer. - /// All shuttle timer packets are broadcast in their network, and subnetting is implemented by filtering timer MapUid. - /// - private void OnPacketReceived(EntityUid uid, ShuttleTimerComponent component, DeviceNetworkPacketEvent args) - { - var timerXform = Transform(uid); - - // no false positives. - if (timerXform.MapUid == null) - return; - - string key; - args.Data.TryGetValue(ShuttleTimerMasks.ShuttleMap, out EntityUid? shuttleMap); - args.Data.TryGetValue(ShuttleTimerMasks.SourceMap, out EntityUid? source); - args.Data.TryGetValue(ShuttleTimerMasks.DestMap, out EntityUid? dest); - args.Data.TryGetValue(ShuttleTimerMasks.Docked, out bool docked); - string?[] text = new string?[] { docked ? Loc.GetString("shuttle-timer-etd") : Loc.GetString("shuttle-timer-eta")}; - - switch (timerXform.MapUid) - { - // sometimes the timer transforms on FTL shuttles have a hyperspace mapuid, so matching by grid works as a fallback. - case var local when local == shuttleMap || timerXform.GridUid == shuttleMap: - key = ShuttleTimerMasks.ShuttleTime; - break; - case var origin when origin == source: - key = ShuttleTimerMasks.SourceTime; - break; - case var remote when remote == dest: - key = ShuttleTimerMasks.DestTime; - text = new string?[] { Loc.GetString("shuttle-timer-eta") }; - break; - default: - return; - } - - if (!args.Data.TryGetValue(key, out TimeSpan duration)) - return; - - if (args.Data.TryGetValue(ShuttleTimerMasks.Text, out string?[]? label)) - text = label; - - _appearanceSystem.SetData(uid, TextScreenVisuals.TargetTime, _gameTiming.CurTime + duration); - _appearanceSystem.SetData(uid, TextScreenVisuals.ScreenText, text); - } -} diff --git a/Content.Shared/Communications/SharedCommunicationsConsoleComponent.cs b/Content.Shared/Communications/SharedCommunicationsConsoleComponent.cs index 7f9094726c843d..bf0f5195b714fb 100644 --- a/Content.Shared/Communications/SharedCommunicationsConsoleComponent.cs +++ b/Content.Shared/Communications/SharedCommunicationsConsoleComponent.cs @@ -11,6 +11,7 @@ public partial class SharedCommunicationsConsoleComponent : Component public sealed class CommunicationsConsoleInterfaceState : BoundUserInterfaceState { public readonly bool CanAnnounce; + public readonly bool CanBroadcast; public readonly bool CanCall; public readonly TimeSpan? ExpectedCountdownEnd; public readonly bool CountdownStarted; @@ -18,9 +19,10 @@ public sealed class CommunicationsConsoleInterfaceState : BoundUserInterfaceStat public string CurrentAlert; public float CurrentAlertDelay; - public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canCall, List? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd = null) + public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canBroadcast, bool canCall, List? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd = null) { CanAnnounce = canAnnounce; + CanBroadcast = canBroadcast; CanCall = canCall; ExpectedCountdownEnd = expectedCountdownEnd; CountdownStarted = expectedCountdownEnd != null; @@ -52,6 +54,16 @@ public CommunicationsConsoleAnnounceMessage(string message) } } + [Serializable, NetSerializable] + public sealed class CommunicationsConsoleBroadcastMessage : BoundUserInterfaceMessage + { + public readonly string Message; + public CommunicationsConsoleBroadcastMessage(string message) + { + Message = message; + } + } + [Serializable, NetSerializable] public sealed class CommunicationsConsoleCallEmergencyShuttleMessage : BoundUserInterfaceMessage { diff --git a/Content.Shared/TextScreen/TextScreenVisuals.cs b/Content.Shared/TextScreen/TextScreenVisuals.cs index 605428632d74c5..102a0cec5ce582 100644 --- a/Content.Shared/TextScreen/TextScreenVisuals.cs +++ b/Content.Shared/TextScreen/TextScreenVisuals.cs @@ -5,15 +5,15 @@ namespace Content.Shared.TextScreen; [Serializable, NetSerializable] public enum TextScreenVisuals : byte { + // TODO: support for a small image, I think. Probably want to rename textscreen to just screen then. /// - /// Should this show any text?
- /// Expects a . + /// What text to default to after timer completion? + /// Expects a . ///
- On, - + DefaultText, /// - /// What text to show?
- /// Expects a . + /// What text to render?
+ /// Expects a . ///
ScreenText, @@ -21,5 +21,11 @@ public enum TextScreenVisuals : byte /// What is the target time?
/// Expects a . ///
- TargetTime + TargetTime, + + /// + /// Change text color on the entire screen + /// Expects a . + /// + Color } diff --git a/Resources/Locale/en-US/communications/communications-console-component.ftl b/Resources/Locale/en-US/communications/communications-console-component.ftl index a3b95940dfacd4..f7cc87cb8ba1b1 100644 --- a/Resources/Locale/en-US/communications/communications-console-component.ftl +++ b/Resources/Locale/en-US/communications/communications-console-component.ftl @@ -2,6 +2,7 @@ comms-console-menu-title = Communications Console comms-console-menu-announcement-placeholder = Announcement text... comms-console-menu-announcement-button = Announce +comms-console-menu-broadcast-button = Broadcast comms-console-menu-call-shuttle = Call emergency shuttle comms-console-menu-recall-shuttle = Recall emergency shuttle diff --git a/Resources/Locale/en-US/shuttles/screens.ftl b/Resources/Locale/en-US/shuttles/screens.ftl new file mode 100644 index 00000000000000..7a1a60e2edb135 --- /dev/null +++ b/Resources/Locale/en-US/shuttles/screens.ftl @@ -0,0 +1,2 @@ +screens-text = text +screens-color = color diff --git a/Resources/Locale/en-US/shuttles/timer.ftl b/Resources/Locale/en-US/shuttles/timer.ftl index 82ca71d65402b9..2b489707c4046e 100644 --- a/Resources/Locale/en-US/shuttles/timer.ftl +++ b/Resources/Locale/en-US/shuttles/timer.ftl @@ -1,2 +1,11 @@ shuttle-timer-eta = ETA shuttle-timer-etd = ETD +shuttle-timer-shuttle-time = ShuttleTime +shuttle-timer-source-time = SourceTime +shuttle-timer-dest-time = DestTime +shuttle-timer-shuttle-map = ShuttleMap +shuttle-timer-source-map = SourceMap +shuttle-timer-dest-map = DestMap +shuttle-timer-docked = Docked +shuttle-timer-bye = BYE! +shuttle-timer-kill = KILL diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index c0c91d57c69d37..5aa1680aaeacf3 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -548,6 +548,8 @@ access: [[ "Command" ]] - type: CommunicationsConsole title: comms-console-announcement-title-station + - type: DeviceNetwork + transmitFrequencyId: ShuttleTimer - type: ActivatableUI key: enum.CommunicationsConsoleUiKey.Key - type: UserInterface diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/screen.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/screen.yml index c0f1b56b0d482c..f3fcb5062a83f7 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/screen.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/screen.yml @@ -2,12 +2,17 @@ id: Screen name: screen description: Displays text or time. + placement: + mode: SnapgridCenter + snap: + - Wallmount components: - type: Transform anchored: true - type: WallMount arc: 360 - type: InteractionOutline + - type: Clickable - type: Appearance - type: Rotatable - type: TextScreenVisuals @@ -28,7 +33,7 @@ enabled: false usesApcPower: true - type: ExtensionCableReceiver - - type: ShuttleTimer + - type: Screen - type: DeviceNetwork receiveFrequencyId: ShuttleTimer diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml index fbb2b7fe5668b3..0c284eec7afcc2 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/timer.yml @@ -58,6 +58,7 @@ textOffset: 0,8 timerOffset: 0,8 textLength: 5 + rows: 1 - type: Sprite drawdepth: WallMountedItems sprite: Structures/Wallmounts/signalscreen.rsi From 70a63452b9df2245d3e9ed7c175229846ab17905 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 27 Jan 2024 13:52:31 +0000 Subject: [PATCH 8/9] Automatic changelog update --- Resources/Changelog/Changelog.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 840328f8d8a631..98364bcd4be732 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,10 +1,4 @@ Entries: -- author: KittenColony - changes: - - message: Added various gauze wraps to most species in the form of markings - type: Add - id: 5304 - time: '2023-12-10T23:16:38.0000000+00:00' - author: Simyon changes: - message: Moths that are turned into zombies will now prefer cloth instead of brains. @@ -3820,3 +3814,10 @@ id: 5804 time: '2024-01-27T12:12:53.0000000+00:00' url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24603 +- author: graevy + changes: + - message: Added hallway screen prototypes and comms console text broadcasts. + type: Add + id: 5805 + time: '2024-01-27T13:51:25.0000000+00:00' + url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24189 From 69d9d9f34b262c3cd8762972faee6629071caf18 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Sat, 27 Jan 2024 15:44:46 +0100 Subject: [PATCH 9/9] Admin Observers get a hat slot and a pda (#20183) --- .../Fills/Backpacks/StarterGear/satchel.yml | 12 ++++++++++++ .../Entities/Mobs/Player/admin_ghost.yml | 5 +++++ .../Entities/Objects/Devices/pda.yml | 18 ++++++++++++++++++ .../aghost_inventory_template.yml | 19 +++++++++++++++++++ .../Roles/Jobs/Fun/misc_startinggear.yml | 6 ++++++ 5 files changed, 60 insertions(+) create mode 100644 Resources/Prototypes/InventoryTemplates/aghost_inventory_template.yml diff --git a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml index 3cd6dac00d496d..a17d49127d8b44 100644 --- a/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml +++ b/Resources/Prototypes/Catalog/Fills/Backpacks/StarterGear/satchel.yml @@ -285,3 +285,15 @@ contents: - id: BoxSurvival - id: RubberStampMime + +- type: entity + noSpawn: true + parent: ClothingBackpackSatchelHolding + id: ClothingBackpackSatchelHoldingAdmin + components: + - type: StorageFill + contents: + - id: AdminPDA + - id: GasAnalyzer + - id: trayScanner + - type: Unremoveable diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 3d6b173f3d528d..d74f91109d0877 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -83,6 +83,11 @@ - type: Stripping - type: SolutionScanner - type: IgnoreUIRange + - type: Inventory + templateId: aghost + - type: InventorySlots + - type: Loadout + prototypes: [ MobAghostGear ] - type: entity id: ActionAGhostShowSolar diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index 133ae8eb2c2a17..72942cbb916a30 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -654,6 +654,24 @@ - type: Icon state: pda-centcom +- type: entity + parent: CentcomPDA + id: AdminPDA + name: Admin PDA + description: If you are not an admin please return this PDA to the nearest admin. + components: + - type: Pda + id: PassengerIDCard + - type: HealthAnalyzer + scanDelay: 0 + - type: CartridgeLoader + uiKey: enum.PdaUiKey.Key + preinstalled: + - CrewManifestCartridge + - NotekeeperCartridge + - NewsReadCartridge + - LogProbeCartridge + - type: entity parent: CentcomPDA id: CentcomPDAFake diff --git a/Resources/Prototypes/InventoryTemplates/aghost_inventory_template.yml b/Resources/Prototypes/InventoryTemplates/aghost_inventory_template.yml new file mode 100644 index 00000000000000..b34378c39d52a9 --- /dev/null +++ b/Resources/Prototypes/InventoryTemplates/aghost_inventory_template.yml @@ -0,0 +1,19 @@ +- type: inventoryTemplate + id: aghost + slots: + - name: back + slotTexture: back + slotFlags: BACK + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 2,1 + strippingWindowPos: 2,4 + displayName: ID + + # For drip reasons. + - name: head + slotTexture: head + slotFlags: HEAD + uiWindowPos: 0,1 + strippingWindowPos: 0,0 + displayName: Head diff --git a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml index 21b9673e900320..ec4c6581de31b5 100644 --- a/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml +++ b/Resources/Prototypes/Roles/Jobs/Fun/misc_startinggear.yml @@ -323,6 +323,12 @@ satchel: ClothingBackpackSatchelBrigmedicFilled duffelbag: ClothingBackpackDuffelBrigmedicFilled +# Aghost +- type: startingGear + id: MobAghostGear + equipment: + back: ClothingBackpackSatchelHoldingAdmin + #Head Rev Gear - type: startingGear id: HeadRevGear