]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Generic Numeric Alerts (#38370)
authorScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Sat, 21 Jun 2025 17:59:37 +0000 (19:59 +0200)
committerGitHub <noreply@github.com>
Sat, 21 Jun 2025 17:59:37 +0000 (20:59 +0300)
20 files changed:
Content.Client/Alerts/GenericCounterAlertSystem.cs [new file with mode: 0644]
Content.Client/Alerts/UpdateAlertSpriteEvent.cs
Content.Client/Revenant/RevenantSystem.cs
Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
Content.Client/UserInterface/Systems/Alerts/Controls/AlertControl.cs
Content.Shared/Alert/Components/GenericCounterAlertComponent.cs [new file with mode: 0644]
Content.Shared/Revenant/SharedRevenant.cs
Resources/Prototypes/Alerts/revenant.yml
Resources/Textures/Interface/Alerts/generic_counter.rsi/0.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/1.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/2.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/3.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/4.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/5.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/6.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/7.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/8.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/9.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/base.png [new file with mode: 0644]
Resources/Textures/Interface/Alerts/generic_counter.rsi/meta.json [new file with mode: 0644]

diff --git a/Content.Client/Alerts/GenericCounterAlertSystem.cs b/Content.Client/Alerts/GenericCounterAlertSystem.cs
new file mode 100644 (file)
index 0000000..de9d97d
--- /dev/null
@@ -0,0 +1,90 @@
+using System.Numerics;
+using Content.Shared.Alert.Components;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+
+namespace Content.Client.Alerts;
+
+/// <summary>
+/// This handles <see cref="GenericCounterAlertComponent"/>
+/// </summary>
+public sealed class GenericCounterAlertSystem : EntitySystem
+{
+    [Dependency] private readonly SpriteSystem _sprite = default!;
+
+    /// <inheritdoc/>
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<GenericCounterAlertComponent, UpdateAlertSpriteEvent>(OnUpdateAlertSprite);
+    }
+
+    private void OnUpdateAlertSprite(Entity<GenericCounterAlertComponent> ent, ref UpdateAlertSpriteEvent args)
+    {
+        var sprite = args.SpriteViewEnt.Comp;
+
+        var ev = new GetGenericAlertCounterAmountEvent(args.Alert);
+        RaiseLocalEvent(args.ViewerEnt, ref ev);
+
+        if (!ev.Handled)
+            return;
+
+        // It cannot be null if its handled, but good to check to avoid ugly null ignores.
+        if (ev.Amount == null)
+            return;
+
+        // How many digits can we display
+        var maxDigitCount = GetMaxDigitCount((ent, ent, sprite));
+
+        // Clamp it to a positive number that we can actually display in full (no rollover to 0)
+        var amount = (int) Math.Clamp(ev.Amount.Value, 0, Math.Pow(10, maxDigitCount) - 1);
+
+        // This is super wack but ig it works?
+        var digitCount = ent.Comp.HideLeadingZeroes
+            ? amount.ToString().Length
+            : maxDigitCount;
+
+        if (ent.Comp.HideLeadingZeroes)
+        {
+            for (var i = 0; i < ent.Comp.DigitKeys.Count; i++)
+            {
+                if (!_sprite.LayerMapTryGet(ent.Owner, ent.Comp.DigitKeys[i], out var layer, false))
+                    continue;
+
+                _sprite.LayerSetVisible(ent.Owner, layer, i <= digitCount - 1);
+            }
+        }
+
+        // ReSharper disable once PossibleLossOfFraction
+        var baseOffset = (ent.Comp.AlertSize.X - digitCount * ent.Comp.GlyphWidth) / 2 * (1f / EyeManager.PixelsPerMeter);
+
+        for (var i = 0; i < ent.Comp.DigitKeys.Count; i++)
+        {
+            if (!_sprite.LayerMapTryGet(ent.Owner, ent.Comp.DigitKeys[i], out var layer, false))
+                continue;
+
+            var result = amount / (int) Math.Pow(10, i) % 10;
+            _sprite.LayerSetRsiState(ent.Owner, layer, result.ToString());
+
+            if (ent.Comp.CenterGlyph)
+            {
+                var offset = baseOffset + (digitCount - 1 - i) * ent.Comp.GlyphWidth * (1f / EyeManager.PixelsPerMeter);
+                _sprite.LayerSetOffset(ent.Owner, layer, new Vector2(offset, 0));
+            }
+        }
+    }
+
+    /// <summary>
+    /// Gets the number of digits that we can display.
+    /// </summary>
+    /// <returns>The number of digits.</returns>
+    private int GetMaxDigitCount(Entity<GenericCounterAlertComponent, SpriteComponent> ent)
+    {
+        for (var i = ent.Comp1.DigitKeys.Count - 1; i >= 0; i--)
+        {
+            if (_sprite.LayerExists((ent.Owner, ent.Comp2), ent.Comp1.DigitKeys[i]))
+                return i + 1;
+        }
+
+        return 0;
+    }
+}
index 4f182c458ccf152ac7439a158e5e3f328fe8ecdb..d8222c23403610bff068e27109b1d86708cc9b3e 100644 (file)
@@ -11,11 +11,14 @@ public record struct UpdateAlertSpriteEvent
 {
     public Entity<SpriteComponent> SpriteViewEnt;
 
+    public EntityUid ViewerEnt;
+
     public AlertPrototype Alert;
 
-    public UpdateAlertSpriteEvent(Entity<SpriteComponent> spriteViewEnt, AlertPrototype alert)
+    public UpdateAlertSpriteEvent(Entity<SpriteComponent> spriteViewEnt, EntityUid viewerEnt, AlertPrototype alert)
     {
         SpriteViewEnt = spriteViewEnt;
+        ViewerEnt = viewerEnt;
         Alert = alert;
     }
 }
index 0534522b40a45e87f34c1a1b37f361f47d084beb..21d2d7888db8a2909a86115145f05400ee514837 100644 (file)
@@ -1,4 +1,6 @@
 using Content.Client.Alerts;
+using Content.Shared.Alert;
+using Content.Shared.Alert.Components;
 using Content.Shared.Revenant;
 using Content.Shared.Revenant.Components;
 using Robust.Client.GameObjects;
@@ -15,7 +17,7 @@ public sealed class RevenantSystem : EntitySystem
         base.Initialize();
 
         SubscribeLocalEvent<RevenantComponent, AppearanceChangeEvent>(OnAppearanceChange);
-        SubscribeLocalEvent<RevenantComponent, UpdateAlertSpriteEvent>(OnUpdateAlert);
+        SubscribeLocalEvent<RevenantComponent, GetGenericAlertCounterAmountEvent>(OnGetCounterAmount);
     }
 
     private void OnAppearanceChange(EntityUid uid, RevenantComponent component, ref AppearanceChangeEvent args)
@@ -40,14 +42,14 @@ public sealed class RevenantSystem : EntitySystem
         }
     }
 
-    private void OnUpdateAlert(Entity<RevenantComponent> ent, ref UpdateAlertSpriteEvent args)
+    private void OnGetCounterAmount(Entity<RevenantComponent> ent, ref GetGenericAlertCounterAmountEvent args)
     {
-        if (args.Alert.ID != ent.Comp.EssenceAlert)
+        if (args.Handled)
             return;
 
-        var essence = Math.Clamp(ent.Comp.Essence.Int(), 0, 999);
-        _sprite.LayerSetRsiState(args.SpriteViewEnt.AsNullable(), RevenantVisualLayers.Digit1, $"{(essence / 100) % 10}");
-        _sprite.LayerSetRsiState(args.SpriteViewEnt.AsNullable(), RevenantVisualLayers.Digit2, $"{(essence / 10) % 10}");
-        _sprite.LayerSetRsiState(args.SpriteViewEnt.AsNullable(), RevenantVisualLayers.Digit3, $"{essence % 10}");
+        if (ent.Comp.EssenceAlert != args.Alert)
+            return;
+
+        args.Amount = ent.Comp.Essence.Int();
     }
 }
index 5c1951203892735c07522d1cceb25ab89615247b..3fe553be3b7e8753a82e767ff1c1ff3c82608b2d 100644 (file)
@@ -98,7 +98,8 @@ public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayS
         if (!EntityManager.TryGetComponent<SpriteComponent>(spriteViewEnt, out var sprite))
             return;
 
-        var ev = new UpdateAlertSpriteEvent((spriteViewEnt, sprite), alert);
+        var ev = new UpdateAlertSpriteEvent((spriteViewEnt, sprite), player, alert);
         EntityManager.EventBus.RaiseLocalEvent(player, ref ev);
+        EntityManager.EventBus.RaiseLocalEvent(spriteViewEnt, ref ev);
     }
 }
index 847b25358687ee5b498a063ffb4ffb945eef35c3..fe22ebba40f1e38a0e6012e23765ad0667914132 100644 (file)
@@ -57,10 +57,15 @@ namespace Content.Client.UserInterface.Systems.Alerts.Controls
             _sprite = _entityManager.System<SpriteSystem>();
             TooltipSupplier = SupplyTooltip;
             Alert = alert;
+
+            HorizontalAlignment = HAlignment.Left;
             _severity = severity;
             _icon = new SpriteView
             {
-                Scale = new Vector2(2, 2)
+                Scale = new Vector2(2, 2),
+                MaxSize = new Vector2(64, 64),
+                Stretch = SpriteView.StretchMode.None,
+                HorizontalAlignment = HAlignment.Left
             };
 
             SetupIcon();
diff --git a/Content.Shared/Alert/Components/GenericCounterAlertComponent.cs b/Content.Shared/Alert/Components/GenericCounterAlertComponent.cs
new file mode 100644 (file)
index 0000000..d0c7fc1
--- /dev/null
@@ -0,0 +1,63 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Alert.Components;
+
+/// <summary>
+/// This is used for an alert which simply displays a generic number over a texture.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class GenericCounterAlertComponent : Component
+{
+    /// <summary>
+    /// The width, in pixels, of an individual glyph, accounting for the space between glyphs.
+    /// A 3 pixel wide glyph with one pixel of space between it and the next would be a width of 4.
+    /// </summary>
+    [DataField]
+    public int GlyphWidth = 6;
+
+    /// <summary>
+    /// Whether the numbers should be centered on the glyph or just follow a static position.
+    /// </summary>
+    [DataField]
+    public bool CenterGlyph = true;
+
+    /// <summary>
+    /// Whether leading zeros should be hidden.
+    /// If true, "005" would display as "5".
+    /// </summary>
+    [DataField]
+    public bool HideLeadingZeroes = true;
+
+    /// <summary>
+    /// The size of the alert sprite.
+    /// Used to calculate offsets.
+    /// </summary>
+    [DataField]
+    public Vector2i AlertSize = new(32, 32);
+
+    /// <summary>
+    /// Digits that can be displayed by the alert, represented by their sprite layer.
+    /// Order defined corresponds to the digit it affects. 1st defined will affect 1st digit, 2nd affect 2nd digit and so on.
+    /// In this case ones would be on layer "1", tens on layer "10" etc.
+    /// </summary>
+    [DataField]
+    public List<string> DigitKeys = new()
+    {
+        "1",
+        "10",
+        "100",
+        "1000",
+        "10000"
+    };
+}
+
+/// <summary>
+/// Event raised to gather the amount the alert will display.
+/// </summary>
+/// <param name="Alert">The alert which is currently requesting an update.</param>
+/// <param name="Amount">The number to display on the alert.</param>
+[ByRefEvent]
+public record struct GetGenericAlertCounterAmountEvent(AlertPrototype Alert, int? Amount = null)
+{
+    public bool Handled => Amount.HasValue;
+}
index 485ad26dd2c9fd08c90ff93e0a2fd9e6c5d4cc01..c44e4408aaf31fea5c0590639c9184f6ee81bcae 100644 (file)
@@ -70,11 +70,3 @@ public enum RevenantVisuals : byte
     Stunned,
     Harvesting,
 }
-
-[NetSerializable, Serializable]
-public enum RevenantVisualLayers : byte
-{
-    Digit1,
-    Digit2,
-    Digit3
-}
index 38933df4fe0cedef563fa4eb1db7cdfd25df4bb8..ab2b13905d9cf205786a364c98c5d5c617cac727 100644 (file)
   id: AlertEssenceSpriteView
   categories: [ HideSpawnMenu ]
   components:
+  - type: GenericCounterAlert
+    centerGlyph: false
+    hideLeadingZeroes: false
   - type: Sprite
     sprite: /Textures/Interface/Alerts/essence_counter.rsi
     layers:
     - map: [ "enum.AlertVisualLayers.Base" ]
-    - map: [ "enum.RevenantVisualLayers.Digit1" ]
-    - map: [ "enum.RevenantVisualLayers.Digit2" ]
-      offset: 0.125, 0
-    - map: [ "enum.RevenantVisualLayers.Digit3" ]
+    - map: [ "1" ]
       offset: 0.25, 0
+    - map: [ "10" ]
+      offset: 0.125, 0
+    - map: [ "100" ]
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/0.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/0.png
new file mode 100644 (file)
index 0000000..8eb85f3
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/0.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/1.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/1.png
new file mode 100644 (file)
index 0000000..8a9a17b
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/1.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/2.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/2.png
new file mode 100644 (file)
index 0000000..8a0fd90
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/2.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/3.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/3.png
new file mode 100644 (file)
index 0000000..181f425
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/3.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/4.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/4.png
new file mode 100644 (file)
index 0000000..fe5680e
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/4.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/5.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/5.png
new file mode 100644 (file)
index 0000000..2361ca7
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/5.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/6.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/6.png
new file mode 100644 (file)
index 0000000..a636e78
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/6.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/7.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/7.png
new file mode 100644 (file)
index 0000000..d29d619
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/7.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/8.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/8.png
new file mode 100644 (file)
index 0000000..90deae2
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/8.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/9.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/9.png
new file mode 100644 (file)
index 0000000..6325fbd
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/9.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/base.png b/Resources/Textures/Interface/Alerts/generic_counter.rsi/base.png
new file mode 100644 (file)
index 0000000..cedd5f7
Binary files /dev/null and b/Resources/Textures/Interface/Alerts/generic_counter.rsi/base.png differ
diff --git a/Resources/Textures/Interface/Alerts/generic_counter.rsi/meta.json b/Resources/Textures/Interface/Alerts/generic_counter.rsi/meta.json
new file mode 100644 (file)
index 0000000..16cc276
--- /dev/null
@@ -0,0 +1,44 @@
+{
+    "version": 1,
+    "license": "CC-BY-SA-3.0",
+    "copyright": "Created by EmoGarbage404",
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "states": [
+        {
+            "name": "base"
+        },
+        {
+            "name": "0"
+        },
+        {
+            "name": "1"
+        },
+        {
+            "name": "2"
+        },
+        {
+            "name": "3"
+        },
+        {
+            "name": "4"
+        },
+        {
+            "name": "5"
+        },
+        {
+            "name": "6"
+        },
+        {
+            "name": "7"
+        },
+        {
+            "name": "8"
+        },
+        {
+            "name": "9"
+        }
+    ]
+}