Skip to content

Commit

Permalink
dynamic alert sprites (space-wizards#25452)
Browse files Browse the repository at this point in the history
* dynamic alert sprite

* fix fat cooldowns
  • Loading branch information
EmoGarbage404 authored Mar 28, 2024
1 parent 6863a7c commit d576f5c
Show file tree
Hide file tree
Showing 38 changed files with 153 additions and 83 deletions.
21 changes: 21 additions & 0 deletions Content.Client/Alerts/UpdateAlertSpriteEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Content.Shared.Alert;
using Robust.Client.GameObjects;

namespace Content.Client.Alerts;

/// <summary>
/// Event raised on an entity with alerts in order to allow it to update visuals for the alert sprite entity.
/// </summary>
[ByRefEvent]
public record struct UpdateAlertSpriteEvent
{
public Entity<SpriteComponent> SpriteViewEnt;

public AlertPrototype Alert;

public UpdateAlertSpriteEvent(Entity<SpriteComponent> spriteViewEnt, AlertPrototype alert)
{
SpriteViewEnt = spriteViewEnt;
Alert = alert;
}
}
15 changes: 15 additions & 0 deletions Content.Client/Revenant/RevenantSystem.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Content.Client.Alerts;
using Content.Shared.Alert;
using Content.Shared.Revenant;
using Content.Shared.Revenant.Components;
using Robust.Client.GameObjects;
Expand All @@ -13,6 +15,7 @@ public override void Initialize()
base.Initialize();

SubscribeLocalEvent<RevenantComponent, AppearanceChangeEvent>(OnAppearanceChange);
SubscribeLocalEvent<RevenantComponent, UpdateAlertSpriteEvent>(OnUpdateAlert);
}

private void OnAppearanceChange(EntityUid uid, RevenantComponent component, ref AppearanceChangeEvent args)
Expand All @@ -36,4 +39,16 @@ private void OnAppearanceChange(EntityUid uid, RevenantComponent component, ref
args.Sprite.LayerSetState(0, component.State);
}
}

private void OnUpdateAlert(Entity<RevenantComponent> ent, ref UpdateAlertSpriteEvent args)
{
if (args.Alert.AlertType != AlertType.Essence)
return;

var sprite = args.SpriteViewEnt.Comp;
var essence = Math.Clamp(ent.Comp.Essence.Int(), 0, 999);
sprite.LayerSetState(RevenantVisualLayers.Digit1, $"{(essence / 100) % 10}");
sprite.LayerSetState(RevenantVisualLayers.Digit2, $"{(essence / 10) % 10}");
sprite.LayerSetState(RevenantVisualLayers.Digit3, $"{essence % 10}");
}
}
16 changes: 16 additions & 0 deletions Content.Client/UserInterface/Systems/Alerts/AlertsUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
using Content.Client.UserInterface.Systems.Alerts.Widgets;
using Content.Client.UserInterface.Systems.Gameplay;
using Content.Shared.Alert;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;

namespace Content.Client.UserInterface.Systems.Alerts;

public sealed class AlertsUIController : UIController, IOnStateEntered<GameplayState>, IOnSystemChanged<ClientAlertsSystem>
{
[Dependency] private readonly IPlayerManager _player = default!;

[UISystemDependency] private readonly ClientAlertsSystem? _alertsSystem = default;

private AlertsUI? UI => UIManager.GetActiveUIWidgetOrNull<AlertsUI>();
Expand Down Expand Up @@ -84,4 +88,16 @@ public void SyncAlerts()
SystemOnSyncAlerts(_alertsSystem, alerts);
}
}

public void UpdateAlertSpriteEntity(EntityUid spriteViewEnt, AlertPrototype alert)
{
if (_player.LocalEntity is not { } player)
return;

if (!EntityManager.TryGetComponent<SpriteComponent>(spriteViewEnt, out var sprite))
return;

var ev = new UpdateAlertSpriteEvent((spriteViewEnt, sprite), alert);
EntityManager.EventBus.RaiseLocalEvent(player, ref ev);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Content.Client.Actions.UI;
using Content.Client.Cooldown;
using Content.Shared.Alert;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
Expand Down Expand Up @@ -33,9 +35,12 @@ public sealed class AlertControl : BaseButton

private short? _severity;
private readonly IGameTiming _gameTiming;
private readonly AnimatedTextureRect _icon;
private readonly IEntityManager _entityManager;
private readonly SpriteView _icon;
private readonly CooldownGraphic _cooldownGraphic;

private EntityUid _spriteViewEntity;

/// <summary>
/// Creates an alert control reflecting the indicated alert + state
/// </summary>
Expand All @@ -44,19 +49,30 @@ public sealed class AlertControl : BaseButton
public AlertControl(AlertPrototype alert, short? severity)
{
_gameTiming = IoCManager.Resolve<IGameTiming>();
_entityManager = IoCManager.Resolve<IEntityManager>();
TooltipSupplier = SupplyTooltip;
Alert = alert;
_severity = severity;
var specifier = alert.GetIcon(_severity);
_icon = new AnimatedTextureRect

_spriteViewEntity = _entityManager.Spawn(Alert.AlertViewEntity);
if (_entityManager.TryGetComponent<SpriteComponent>(_spriteViewEntity, out var sprite))
{
DisplayRect = {TextureScale = new Vector2(2, 2)}
};
var icon = Alert.GetIcon(_severity);
if (sprite.LayerMapTryGet(AlertVisualLayers.Base, out var layer))
sprite.LayerSetSprite(layer, icon);
}

_icon.SetFromSpriteSpecifier(specifier);
_icon = new SpriteView
{
Scale = new Vector2(2, 2)
};
_icon.SetEntity(_spriteViewEntity);

Children.Add(_icon);
_cooldownGraphic = new CooldownGraphic();
_cooldownGraphic = new CooldownGraphic
{
MaxSize = new Vector2(64, 64)
};
Children.Add(_cooldownGraphic);
}

Expand All @@ -72,16 +88,22 @@ private Control SupplyTooltip(Control? sender)
/// </summary>
public void SetSeverity(short? severity)
{
if (_severity != severity)
{
_severity = severity;
_icon.SetFromSpriteSpecifier(Alert.GetIcon(_severity));
}
if (_severity == severity)
return;
_severity = severity;

if (!_entityManager.TryGetComponent<SpriteComponent>(_spriteViewEntity, out var sprite))
return;
var icon = Alert.GetIcon(_severity);
if (sprite.LayerMapTryGet(AlertVisualLayers.Base, out var layer))
sprite.LayerSetSprite(layer, icon);
}

protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UserInterfaceManager.GetUIController<AlertsUIController>().UpdateAlertSpriteEntity(_spriteViewEntity, Alert);

if (!Cooldown.HasValue)
{
_cooldownGraphic.Visible = false;
Expand All @@ -91,5 +113,17 @@ protected override void FrameUpdate(FrameEventArgs args)

_cooldownGraphic.FromTime(Cooldown.Value.Start, Cooldown.Value.End);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

_entityManager.DeleteEntity(_spriteViewEntity);
}
}

public enum AlertVisualLayers : byte
{
Base
}
}
3 changes: 2 additions & 1 deletion Content.Server/Revenant/EntitySystems/RevenantSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,15 @@ public bool ChangeEssenceAmount(EntityUid uid, FixedPoint2 amount, RevenantCompo
return false;

component.Essence += amount;
Dirty(uid, component);

if (regenCap)
FixedPoint2.Min(component.Essence, component.EssenceRegenCap);

if (TryComp<StoreComponent>(uid, out var store))
_store.UpdateUserInterface(uid, uid, store);

_alerts.ShowAlert(uid, AlertType.Essence, (short) Math.Clamp(Math.Round(component.Essence.Float() / 10f), 0, 16));
_alerts.ShowAlert(uid, AlertType.Essence);

if (component.Essence <= 0)
{
Expand Down
14 changes: 8 additions & 6 deletions Content.Shared/Alert/AlertPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public sealed partial class AlertPrototype : IPrototype
[DataField("icons", required: true)]
public List<SpriteSpecifier> Icons = new();

/// <summary>
/// An entity used for displaying the <see cref="Icons"/> in the UI control.
/// </summary>
[DataField]
public EntProtoId AlertViewEntity = "AlertSpriteView";

/// <summary>
/// Name to show in tooltip window. Accepts formatting.
/// </summary>
Expand Down Expand Up @@ -83,13 +89,9 @@ public sealed partial class AlertPrototype : IPrototype
/// <returns>the icon path to the texture for the provided severity level</returns>
public SpriteSpecifier GetIcon(short? severity = null)
{
if (!SupportsSeverity && severity != null)
{
throw new InvalidOperationException($"This alert ({AlertKey}) does not support severity");
}

var minIcons = SupportsSeverity
? MaxSeverity - MinSeverity : 1;
? MaxSeverity - MinSeverity
: 1;

if (Icons.Count < minIcons)
throw new InvalidOperationException($"Insufficient number of icons given for alert {AlertType}");
Expand Down
4 changes: 3 additions & 1 deletion Content.Shared/Revenant/Components/RevenantComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
namespace Content.Shared.Revenant.Components;

[RegisterComponent, NetworkedComponent]
[AutoGenerateComponentState]
public sealed partial class RevenantComponent : Component
{
/// <summary>
/// The total amount of Essence the revenant has. Functions
/// as health and is regenerated.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField, ViewVariables(VVAccess.ReadWrite)]
[AutoNetworkedField]
public FixedPoint2 Essence = 75;

[DataField("stolenEssenceCurrencyPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<CurrencyPrototype>))]
Expand Down
8 changes: 8 additions & 0 deletions Content.Shared/Revenant/SharedRevenant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,11 @@ public enum RevenantVisuals : byte
Stunned,
Harvesting,
}

[NetSerializable, Serializable]
public enum RevenantVisualLayers : byte
{
Digit1,
Digit2,
Digit3
}
8 changes: 8 additions & 0 deletions Resources/Prototypes/Alerts/alerts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
- alertType: Magboots
- alertType: Pacified

- type: entity
id: AlertSpriteView
categories: [ hideSpawnMenu ]
components:
- type: Sprite
layers:
- map: [ "enum.AlertVisualLayers.Base" ]

- type: alert
id: LowOxygen
category: Breathing
Expand Down
51 changes: 16 additions & 35 deletions Resources/Prototypes/Alerts/revenant.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,26 @@
icons:
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence0
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence1
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence2
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence3
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence4
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence5
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence6
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence7
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence8
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence9
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence10
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence11
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence12
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence13
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence14
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence15
- sprite: /Textures/Interface/Alerts/essence_counter.rsi
state: essence16
alertViewEntity: AlertEssenceSpriteView
name: alerts-revenant-essence-name
description: alerts-revenant-essence-desc
minSeverity: 0
maxSeverity: 16

- type: alert
id: Corporeal
icons: [ /Textures/Mobs/Ghosts/revenant.rsi/icon.png ]
name: alerts-revenant-corporeal-name
description: alerts-revenant-corporeal-desc
description: alerts-revenant-corporeal-desc

- type: entity
id: AlertEssenceSpriteView
categories: [ hideSpawnMenu ]
components:
- 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" ]
offset: 0.25, 0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Diff not rendered.
Diff not rendered.
Loading

0 comments on commit d576f5c

Please sign in to comment.