diff --git a/Content.Client/Alerts/GenericCounterAlertSystem.cs b/Content.Client/Alerts/GenericCounterAlertSystem.cs
new file mode 100644
index 0000000000..de9d97d063
--- /dev/null
+++ b/Content.Client/Alerts/GenericCounterAlertSystem.cs
@@ -0,0 +1,90 @@
+using System.Numerics;
+using Content.Shared.Alert.Components;
+using Robust.Client.GameObjects;
+using Robust.Client.Graphics;
+
+namespace Content.Client.Alerts;
+
+///
+/// This handles
+///
+public sealed class GenericCounterAlertSystem : EntitySystem
+{
+ [Dependency] private readonly SpriteSystem _sprite = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnUpdateAlertSprite);
+ }
+
+ private void OnUpdateAlertSprite(Entity 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));
+ }
+ }
+ }
+
+ ///
+ /// Gets the number of digits that we can display.
+ ///
+ /// The number of digits.
+ private int GetMaxDigitCount(Entity 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;
+ }
+}
diff --git a/Content.Client/Alerts/UpdateAlertSpriteEvent.cs b/Content.Client/Alerts/UpdateAlertSpriteEvent.cs
index 4f182c458c..d8222c2340 100644
--- a/Content.Client/Alerts/UpdateAlertSpriteEvent.cs
+++ b/Content.Client/Alerts/UpdateAlertSpriteEvent.cs
@@ -11,11 +11,14 @@ public record struct UpdateAlertSpriteEvent
{
public Entity SpriteViewEnt;
+ public EntityUid ViewerEnt;
+
public AlertPrototype Alert;
- public UpdateAlertSpriteEvent(Entity spriteViewEnt, AlertPrototype alert)
+ public UpdateAlertSpriteEvent(Entity spriteViewEnt, EntityUid viewerEnt, AlertPrototype alert)
{
SpriteViewEnt = spriteViewEnt;
+ ViewerEnt = viewerEnt;
Alert = alert;
}
}
diff --git a/Content.Client/Revenant/RevenantSystem.cs b/Content.Client/Revenant/RevenantSystem.cs
index 0534522b40..21d2d7888d 100644
--- a/Content.Client/Revenant/RevenantSystem.cs
+++ b/Content.Client/Revenant/RevenantSystem.cs
@@ -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(OnAppearanceChange);
- SubscribeLocalEvent(OnUpdateAlert);
+ SubscribeLocalEvent(OnGetCounterAmount);
}
private void OnAppearanceChange(EntityUid uid, RevenantComponent component, ref AppearanceChangeEvent args)
@@ -40,14 +42,14 @@ public sealed class RevenantSystem : EntitySystem
}
}
- private void OnUpdateAlert(Entity ent, ref UpdateAlertSpriteEvent args)
+ private void OnGetCounterAmount(Entity 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();
}
}
diff --git a/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs b/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
index 5c19512038..3fe553be3b 100644
--- a/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
+++ b/Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
@@ -98,7 +98,8 @@ public sealed class AlertsUIController : UIController, IOnStateEntered(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);
}
}
diff --git a/Content.Client/UserInterface/Systems/Alerts/Controls/AlertControl.cs b/Content.Client/UserInterface/Systems/Alerts/Controls/AlertControl.cs
index 847b253586..fe22ebba40 100644
--- a/Content.Client/UserInterface/Systems/Alerts/Controls/AlertControl.cs
+++ b/Content.Client/UserInterface/Systems/Alerts/Controls/AlertControl.cs
@@ -57,10 +57,15 @@ namespace Content.Client.UserInterface.Systems.Alerts.Controls
_sprite = _entityManager.System();
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
index 0000000000..d0c7fc1ad1
--- /dev/null
+++ b/Content.Shared/Alert/Components/GenericCounterAlertComponent.cs
@@ -0,0 +1,63 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Alert.Components;
+
+///
+/// This is used for an alert which simply displays a generic number over a texture.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class GenericCounterAlertComponent : Component
+{
+ ///
+ /// 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.
+ ///
+ [DataField]
+ public int GlyphWidth = 6;
+
+ ///
+ /// Whether the numbers should be centered on the glyph or just follow a static position.
+ ///
+ [DataField]
+ public bool CenterGlyph = true;
+
+ ///
+ /// Whether leading zeros should be hidden.
+ /// If true, "005" would display as "5".
+ ///
+ [DataField]
+ public bool HideLeadingZeroes = true;
+
+ ///
+ /// The size of the alert sprite.
+ /// Used to calculate offsets.
+ ///
+ [DataField]
+ public Vector2i AlertSize = new(32, 32);
+
+ ///
+ /// 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.
+ ///
+ [DataField]
+ public List DigitKeys = new()
+ {
+ "1",
+ "10",
+ "100",
+ "1000",
+ "10000"
+ };
+}
+
+///
+/// Event raised to gather the amount the alert will display.
+///
+/// The alert which is currently requesting an update.
+/// The number to display on the alert.
+[ByRefEvent]
+public record struct GetGenericAlertCounterAmountEvent(AlertPrototype Alert, int? Amount = null)
+{
+ public bool Handled => Amount.HasValue;
+}
diff --git a/Content.Shared/Revenant/SharedRevenant.cs b/Content.Shared/Revenant/SharedRevenant.cs
index 485ad26dd2..c44e4408aa 100644
--- a/Content.Shared/Revenant/SharedRevenant.cs
+++ b/Content.Shared/Revenant/SharedRevenant.cs
@@ -70,11 +70,3 @@ public enum RevenantVisuals : byte
Stunned,
Harvesting,
}
-
-[NetSerializable, Serializable]
-public enum RevenantVisualLayers : byte
-{
- Digit1,
- Digit2,
- Digit3
-}
diff --git a/Resources/Prototypes/Alerts/revenant.yml b/Resources/Prototypes/Alerts/revenant.yml
index 38933df4fe..ab2b13905d 100644
--- a/Resources/Prototypes/Alerts/revenant.yml
+++ b/Resources/Prototypes/Alerts/revenant.yml
@@ -18,12 +18,15 @@
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
index 0000000000..8eb85f36dc
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
index 0000000000..8a9a17bc02
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
index 0000000000..8a0fd90ff3
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
index 0000000000..181f425acc
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
index 0000000000..fe5680eb41
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
index 0000000000..2361ca7f1d
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
index 0000000000..a636e7890b
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
index 0000000000..d29d6192de
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
index 0000000000..90deae2876
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
index 0000000000..6325fbdabc
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
index 0000000000..cedd5f78fa
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
index 0000000000..16cc2761e3
--- /dev/null
+++ b/Resources/Textures/Interface/Alerts/generic_counter.rsi/meta.json
@@ -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"
+ }
+ ]
+}