diff --git a/Content.Client/Power/SMES/SmesComponent.cs b/Content.Client/Power/SMES/SmesComponent.cs new file mode 100644 index 0000000000..155a40c8e2 --- /dev/null +++ b/Content.Client/Power/SMES/SmesComponent.cs @@ -0,0 +1,28 @@ +namespace Content.Client.Power.SMES; + +[RegisterComponent] +public sealed class SmesComponent : Component +{ + /// + /// The prefix used for the RSI states of the sprite layers indicating the charge level of the SMES. + /// + [DataField("chargeOverlayPrefix")] + [ViewVariables(VVAccess.ReadWrite)] + public string ChargeOverlayPrefix = "smes-og"; + + /// + /// The prefix used for the RSI states of the sprite layers indicating the input state of the SMES. + /// Actually bundled together with the output indicator light. + /// + [DataField("inputOverlayPrefix")] + [ViewVariables(VVAccess.ReadWrite)] + public string InputOverlayPrefix = "smes-oc"; + + /// + /// The prefix used for the RSI states of the sprite layers indicating the output state of the SMES. + /// Actually bundled together with the input indicator light. + /// + [DataField("outputOverlayPrefix")] + [ViewVariables(VVAccess.ReadWrite)] + public string OutputOverlayPrefix = "smes-op"; +} diff --git a/Content.Client/Power/SMES/SmesSystem.cs b/Content.Client/Power/SMES/SmesSystem.cs new file mode 100644 index 0000000000..a555bedcac --- /dev/null +++ b/Content.Client/Power/SMES/SmesSystem.cs @@ -0,0 +1,50 @@ +using Content.Shared.Power; +using Content.Shared.SMES; +using Robust.Client.GameObjects; + +namespace Content.Client.Power.SMES; + +public sealed class SmesVisualizerSystem : VisualizerSystem +{ + protected override void OnAppearanceChange(EntityUid uid, SmesComponent comp, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!AppearanceSystem.TryGetData(uid, SmesVisuals.LastChargeLevel, out var level, args.Component) || level == 0) + { + args.Sprite.LayerSetVisible(SmesVisualLayers.Charge, false); + } + else + { + args.Sprite.LayerSetVisible(SmesVisualLayers.Charge, true); + args.Sprite.LayerSetState(SmesVisualLayers.Charge, $"{comp.ChargeOverlayPrefix}{level}"); + } + + if (!AppearanceSystem.TryGetData(uid, SmesVisuals.LastChargeState, out var state, args.Component)) + state = ChargeState.Still; + + switch (state) + { + case ChargeState.Still: + args.Sprite.LayerSetState(SmesVisualLayers.Input, $"{comp.InputOverlayPrefix}0"); + args.Sprite.LayerSetState(SmesVisualLayers.Output, $"{comp.OutputOverlayPrefix}1"); + break; + case ChargeState.Charging: + args.Sprite.LayerSetState(SmesVisualLayers.Input, $"{comp.InputOverlayPrefix}1"); + args.Sprite.LayerSetState(SmesVisualLayers.Output, $"{comp.OutputOverlayPrefix}1"); + break; + case ChargeState.Discharging: + args.Sprite.LayerSetState(SmesVisualLayers.Input, $"{comp.InputOverlayPrefix}0"); + args.Sprite.LayerSetState(SmesVisualLayers.Output, $"{comp.OutputOverlayPrefix}2"); + break; + } + } +} + +enum SmesVisualLayers : byte +{ + Input, + Charge, + Output, +} diff --git a/Content.Client/Power/SMES/SmesVisualizer.cs b/Content.Client/Power/SMES/SmesVisualizer.cs deleted file mode 100644 index 7682671002..0000000000 --- a/Content.Client/Power/SMES/SmesVisualizer.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Content.Shared.Power; -using Content.Shared.SMES; -using JetBrains.Annotations; -using Robust.Client.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; - -namespace Content.Client.Power.SMES -{ - [UsedImplicitly] - public sealed class SmesVisualizer : AppearanceVisualizer - { - [Obsolete("Subscribe to your component being initialised instead.")] - public override void InitializeEntity(EntityUid entity) - { - base.InitializeEntity(entity); - - var sprite = IoCManager.Resolve().GetComponent(entity); - - sprite.LayerMapSet(Layers.Input, sprite.AddLayerState("smes-oc0")); - sprite.LayerSetShader(Layers.Input, "unshaded"); - sprite.LayerMapSet(Layers.Charge, sprite.AddLayerState("smes-og1")); - sprite.LayerSetShader(Layers.Charge, "unshaded"); - sprite.LayerSetVisible(Layers.Charge, false); - sprite.LayerMapSet(Layers.Output, sprite.AddLayerState("smes-op0")); - sprite.LayerSetShader(Layers.Output, "unshaded"); - } - - [Obsolete("Subscribe to AppearanceChangeEvent instead.")] - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - - var sprite = IoCManager.Resolve().GetComponent(component.Owner); - if (!component.TryGetData(SmesVisuals.LastChargeLevel, out var level) || level == 0) - { - sprite.LayerSetVisible(Layers.Charge, false); - } - else - { - sprite.LayerSetVisible(Layers.Charge, true); - sprite.LayerSetState(Layers.Charge, $"smes-og{level}"); - } - - if (component.TryGetData(SmesVisuals.LastChargeState, out var state)) - { - switch (state) - { - case ChargeState.Still: - sprite.LayerSetState(Layers.Input, "smes-oc0"); - sprite.LayerSetState(Layers.Output, "smes-op1"); - break; - case ChargeState.Charging: - sprite.LayerSetState(Layers.Input, "smes-oc1"); - sprite.LayerSetState(Layers.Output, "smes-op1"); - break; - case ChargeState.Discharging: - sprite.LayerSetState(Layers.Input, "smes-oc0"); - sprite.LayerSetState(Layers.Output, "smes-op2"); - break; - } - } - else - { - sprite.LayerSetState(Layers.Input, "smes-oc0"); - sprite.LayerSetState(Layers.Output, "smes-op1"); - } - } - - enum Layers : byte - { - Input, - Charge, - Output, - } - } -} diff --git a/Content.Server/Power/SMES/SmesComponent.cs b/Content.Server/Power/SMES/SmesComponent.cs index c812fc9836..29e1dbd7cb 100644 --- a/Content.Server/Power/SMES/SmesComponent.cs +++ b/Content.Server/Power/SMES/SmesComponent.cs @@ -1,16 +1,12 @@ using Content.Server.Power.Components; using Content.Shared.Power; -using Content.Shared.Rounding; -using Content.Shared.SMES; -using Robust.Server.GameObjects; -using Robust.Shared.Timing; namespace Content.Server.Power.SMES; /// /// Handles the "user-facing" side of the actual SMES object. /// This is operations that are specific to the SMES, like UI and visuals. -/// Logic is handled in +/// Logic is handled in /// Code interfacing with the powernet is handled in and . /// [RegisterComponent, Access(typeof(SmesSystem))] @@ -26,4 +22,23 @@ public sealed class SmesComponent : Component public TimeSpan LastChargeLevelTime; [ViewVariables] public TimeSpan VisualsChangeDelay = TimeSpan.FromSeconds(1); + + /// + /// The number of distinct charge levels a SMES has. + /// 0 is empty max is full. + /// + [DataField("numChargeLevels")] + public int NumChargeLevels = 6; + + /// + /// The charge level of the SMES as of the most recent update. + /// + [ViewVariables] + public int ChargeLevel = 0; + + /// + /// Whether the SMES is being charged/discharged/neither. + /// + [ViewVariables] + public ChargeState ChargeState = ChargeState.Still; } diff --git a/Content.Server/Power/SMES/SmesSystem.cs b/Content.Server/Power/SMES/SmesSystem.cs index e9a07fa03e..7da8eb0688 100644 --- a/Content.Server/Power/SMES/SmesSystem.cs +++ b/Content.Server/Power/SMES/SmesSystem.cs @@ -57,7 +57,7 @@ internal sealed class SmesSystem : EntitySystem private int CalcChargeLevel(EntityUid uid, BatteryComponent? battery = null) { - if (!Resolve(uid, ref battery)) + if (!Resolve(uid, ref battery)) return 0; return ContentHelpers.RoundToLevels(battery.CurrentCharge, battery.MaxCharge, 6); @@ -65,7 +65,7 @@ internal sealed class SmesSystem : EntitySystem private ChargeState CalcChargeState(EntityUid uid, PowerNetworkBatteryComponent? netBattery = null) { - if (!Resolve(uid, ref netBattery)) + if (!Resolve(uid, ref netBattery)) return ChargeState.Still; return (netBattery.CurrentSupply - netBattery.CurrentReceiving) switch diff --git a/Content.Shared/Power/SharedPower.cs b/Content.Shared/Power/SharedPower.cs index 481dcf7dc9..5dd366fd68 100644 --- a/Content.Shared/Power/SharedPower.cs +++ b/Content.Shared/Power/SharedPower.cs @@ -3,11 +3,11 @@ namespace Content.Shared.Power { [Serializable, NetSerializable] - public enum ChargeState + public enum ChargeState : byte { - Still, - Charging, - Discharging, + Still = 0, + Charging = 1, + Discharging = 2, } [Serializable, NetSerializable] diff --git a/Content.Shared/SMES/SharedSmesComponent.cs b/Content.Shared/SMES/SharedSmesComponent.cs index 720e346a79..3fe9dd8f5f 100644 --- a/Content.Shared/SMES/SharedSmesComponent.cs +++ b/Content.Shared/SMES/SharedSmesComponent.cs @@ -1,11 +1,10 @@ using Robust.Shared.Serialization; -namespace Content.Shared.SMES +namespace Content.Shared.SMES; + +[Serializable, NetSerializable] +public enum SmesVisuals { - [Serializable, NetSerializable] - public enum SmesVisuals - { - LastChargeState, - LastChargeLevel, - } + LastChargeState, + LastChargeLevel, } diff --git a/Resources/Prototypes/Entities/Structures/Power/smes.yml b/Resources/Prototypes/Entities/Structures/Power/smes.yml index 54f9270fd7..9b934dea02 100644 --- a/Resources/Prototypes/Entities/Structures/Power/smes.yml +++ b/Resources/Prototypes/Entities/Structures/Power/smes.yml @@ -19,13 +19,21 @@ snapCardinals: true layers: - state: smes + - map: ["enum.SmesVisualLayers.Charge"] + state: "smes-og1" # -og0 does not exist + shader: unshaded + visible: false + - map: ["enum.SmesVisualLayers.Input"] + state: "smes-oc0" + shader: unshaded + - map: ["enum.SmesVisualLayers.Output"] + state: "smes-op1" + shader: unshaded - type: Smes - type: UpgradeBattery maxChargeMultiplier: 2 baseMaxCharge: 8000000 - type: Appearance - visuals: - - type: SmesVisualizer - type: Battery startingCharge: 0 - type: ExaminableBattery