--- /dev/null
+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;
+ }
+}
{
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;
}
}
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;
base.Initialize();
SubscribeLocalEvent<RevenantComponent, AppearanceChangeEvent>(OnAppearanceChange);
- SubscribeLocalEvent<RevenantComponent, UpdateAlertSpriteEvent>(OnUpdateAlert);
+ SubscribeLocalEvent<RevenantComponent, GetGenericAlertCounterAmountEvent>(OnGetCounterAmount);
}
private void OnAppearanceChange(EntityUid uid, RevenantComponent component, ref AppearanceChangeEvent args)
}
}
- 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();
}
}
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);
}
}
_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();
--- /dev/null
+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;
+}
Stunned,
Harvesting,
}
-
-[NetSerializable, Serializable]
-public enum RevenantVisualLayers : byte
-{
- Digit1,
- Digit2,
- Digit3
-}
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" ]
--- /dev/null
+{
+ "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"
+ }
+ ]
+}