From c33daddda2a9e1df235ee69559100736a853b007 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 21 Sep 2018 08:21:40 +0200 Subject: [PATCH] Power cells --- Content.Client/Content.Client.csproj | 1 + .../Components/Power/PowerCellVisualizer2D.cs | 48 +++++++ Content.Server/Content.Server.csproj | 2 + Content.Server/EntryPoint.cs | 5 +- .../Components/Power/PowerCellComponent.cs | 48 +++++++ .../Components/Power/PowerDebugTool.cs | 2 +- .../Components/Power/PowerStorageComponent.cs | 127 +++++------------- .../Power/PowerStorageNetComponent.cs | 100 ++++++++++++++ .../GameObjects/Components/Power/Powernet.cs | 10 +- Content.Shared/Content.Shared.csproj | 1 + .../Power/SharedPowerCellComponent.cs | 11 ++ Resources/Prototypes/Entities/powercells.yml | 94 +++++++++++++ 12 files changed, 349 insertions(+), 100 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Power/PowerCellVisualizer2D.cs create mode 100644 Content.Server/GameObjects/Components/Power/PowerCellComponent.cs create mode 100644 Content.Server/GameObjects/Components/Power/PowerStorageNetComponent.cs create mode 100644 Content.Shared/GameObjects/Components/Power/SharedPowerCellComponent.cs create mode 100644 Resources/Prototypes/Entities/powercells.yml diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index e53fbe21b1..dd5acffae4 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -72,6 +72,7 @@ + diff --git a/Content.Client/GameObjects/Components/Power/PowerCellVisualizer2D.cs b/Content.Client/GameObjects/Components/Power/PowerCellVisualizer2D.cs new file mode 100644 index 0000000000..c2d4769143 --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/PowerCellVisualizer2D.cs @@ -0,0 +1,48 @@ +using Content.Shared.GameObjects.Components.Power; +using Content.Shared.Utility; +using SS14.Client.GameObjects; +using SS14.Client.Interfaces.GameObjects.Components; +using SS14.Shared.Interfaces.GameObjects; +using SS14.Shared.Utility; +using YamlDotNet.RepresentationModel; + +namespace Content.Client.GameObjects.Components.Power +{ + public class PowerCellVisualizer2D : AppearanceVisualizer + { + private string _prefix; + + public override void LoadData(YamlMappingNode node) + { + base.LoadData(node); + + _prefix = node.GetNode("prefix").AsString(); + } + + public override void InitializeEntity(IEntity entity) + { + base.InitializeEntity(entity); + + var sprite = entity.GetComponent(); + + sprite.LayerMapSet(Layers.Charge, sprite.AddLayerState($"{_prefix}_100")); + sprite.LayerSetShader(Layers.Charge, "unshaded"); + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + + var sprite = component.Owner.GetComponent(); + if (component.TryGetData(PowerCellVisuals.ChargeLevel, out float fraction)) + { + sprite.LayerSetState(Layers.Charge, $"{_prefix}_{ContentHelpers.RoundToLevels(fraction, 1, 5) * 25}"); + } + } + + private enum Layers + { + Charge + } + } +} diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj index 8da4a3565c..5635a0e5ee 100644 --- a/Content.Server/Content.Server.csproj +++ b/Content.Server/Content.Server.csproj @@ -80,12 +80,14 @@ + + diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 974015ee5e..757e709fb0 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -86,7 +86,10 @@ namespace Content.Server factory.Register(); factory.RegisterReference(); factory.Register(); - factory.Register(); + factory.Register(); + factory.RegisterReference(); + factory.Register(); + factory.RegisterReference(); factory.Register(); factory.Register(); diff --git a/Content.Server/GameObjects/Components/Power/PowerCellComponent.cs b/Content.Server/GameObjects/Components/Power/PowerCellComponent.cs new file mode 100644 index 0000000000..ae53d48de9 --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/PowerCellComponent.cs @@ -0,0 +1,48 @@ +using Content.Shared.GameObjects.Components.Power; +using SS14.Server.GameObjects; + +namespace Content.Server.GameObjects.Components.Power +{ + public class PowerCellComponent : PowerStorageComponent + { + public override string Name => "PowerCell"; + + private AppearanceComponent _appearance; + + public override float Charge + { + get => base.Charge; + set + { + base.Charge = value; + _updateAppearance(); + } + } + + public override void Initialize() + { + base.Initialize(); + + Owner.TryGetComponent(out _appearance); + } + + public override void DeductCharge(float toDeduct) + { + base.DeductCharge(toDeduct); + + _updateAppearance(); + } + + public override void AddCharge(float charge) + { + base.AddCharge(charge); + + _updateAppearance(); + } + + private void _updateAppearance() + { + _appearance?.SetData(PowerCellVisuals.ChargeLevel, Charge / Capacity); + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs b/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs index 2b3f238c5c..ea6f70a78a 100644 --- a/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs +++ b/Content.Server/GameObjects/Components/Power/PowerDebugTool.cs @@ -75,7 +75,7 @@ namespace Content.Server.GameObjects.Components.Power } } - if (attacked.TryGetComponent(out var storage)) + if (attacked.TryGetComponent(out var storage)) { var stateSeconds = (DateTime.Now - storage.LastChargeStateChange).TotalSeconds; builder.AppendFormat(@"Power Storage: diff --git a/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs b/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs index 0880c9cdc5..d108a76cea 100644 --- a/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerStorageComponent.cs @@ -11,12 +11,11 @@ using YamlDotNet.RepresentationModel; namespace Content.Server.GameObjects.Components.Power { /// - /// Feeds energy from the powernet and may have the ability to supply back into it + /// Stores electrical energy. Used by power cells and SMESes. /// - public class PowerStorageComponent : Component + public abstract class PowerStorageComponent : Component { - public override string Name => "PowerStorage"; - + [ViewVariables] public ChargeState LastChargeState { get; private set; } = ChargeState.Still; public DateTime LastChargeStateChange { get; private set; } @@ -31,9 +30,15 @@ namespace Content.Server.GameObjects.Components.Power /// /// Energy the battery is currently storing. /// In Joules. + /// In most cases you should use and to modify this. /// - [ViewVariables] - public float Charge => _charge; + [ViewVariables(VVAccess.ReadWrite)] + public virtual float Charge + { + get => _charge; + set => _charge = value; + } + private float _charge = 0; /// @@ -55,26 +60,6 @@ namespace Content.Server.GameObjects.Components.Power [ViewVariables] public bool Full => Charge >= Capacity; - private bool _chargepowernet = false; - - /// - /// Do we distribute power into the powernet from our stores if the powernet requires it? - /// - [ViewVariables(VVAccess.ReadWrite)] - public bool ChargePowernet - { - get => _chargepowernet; - set - { - _chargepowernet = value; - if (Owner.TryGetComponent(out PowerNodeComponent node)) - { - if (node.Parent != null) - node.Parent.UpdateStorageType(this); - } - } - } - public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); @@ -83,46 +68,14 @@ namespace Content.Server.GameObjects.Components.Power serializer.DataField(ref _charge, "charge", 0); serializer.DataField(ref _chargeRate, "chargerate", 1000); serializer.DataField(ref _distributionRate, "distributionrate", 1000); - serializer.DataField(ref _chargepowernet, "chargepowernet", false); - } - - public override void OnAdd() - { - base.OnAdd(); - - if (!Owner.TryGetComponent(out PowerNodeComponent node)) - { - Owner.AddComponent(); - node = Owner.GetComponent(); - } - node.OnPowernetConnect += PowernetConnect; - node.OnPowernetDisconnect += PowernetDisconnect; - node.OnPowernetRegenerate += PowernetRegenerate; - } - - public override void OnRemove() - { - if (Owner.TryGetComponent(out PowerNodeComponent node)) - { - if (node.Parent != null) - { - node.Parent.RemovePowerStorage(this); - } - - node.OnPowernetConnect -= PowernetConnect; - node.OnPowernetDisconnect -= PowernetDisconnect; - node.OnPowernetRegenerate -= PowernetRegenerate; - } - - base.OnRemove(); } /// /// Checks if the storage can supply the amount of charge directly requested /// - public bool CanDeductCharge(float todeduct) + public bool CanDeductCharge(float toDeduct) { - if (Charge > todeduct) + if (Charge > toDeduct) return true; return false; } @@ -130,14 +83,14 @@ namespace Content.Server.GameObjects.Components.Power /// /// Deducts the requested charge from the energy storage /// - public void DeductCharge(float todeduct) + public virtual void DeductCharge(float toDeduct) { - _charge = Math.Max(0, Charge - todeduct); + _charge = Math.Max(0, Charge - toDeduct); LastChargeState = ChargeState.Discharging; LastChargeStateChange = DateTime.Now; } - public void AddCharge(float charge) + public virtual void AddCharge(float charge) { _charge = Math.Min(Capacity, Charge + charge); LastChargeState = ChargeState.Charging; @@ -160,6 +113,24 @@ namespace Content.Server.GameObjects.Components.Power return Math.Min(DistributionRate * frameTime, Charge); } + /// + /// Tries to deduct a wattage over a certain amount of time. + /// + /// The wattage of the power drain. + /// The amount of time in this "frame". + /// True if the amount of energy was deducted, false. + public bool TryDeductWattage(float wattage, float frameTime) + { + var avail = AvailableCharge(frameTime); + if (avail < wattage * frameTime) + { + return false; + } + + DeductCharge(wattage * frameTime); + return true; + } + public ChargeState GetChargeState() { return GetChargeState(TimeSpan.FromSeconds(1)); @@ -182,35 +153,5 @@ namespace Content.Server.GameObjects.Components.Power } AddCharge(RequestCharge(frameTime)); } - - /// - /// Node has become anchored to a powernet - /// - /// - /// - private void PowernetConnect(object sender, PowernetEventArgs eventarg) - { - eventarg.Powernet.AddPowerStorage(this); - } - - /// - /// Node has had its powernet regenerated - /// - /// - /// - private void PowernetRegenerate(object sender, PowernetEventArgs eventarg) - { - eventarg.Powernet.AddPowerStorage(this); - } - - /// - /// Node has become unanchored from a powernet - /// - /// - /// - private void PowernetDisconnect(object sender, PowernetEventArgs eventarg) - { - eventarg.Powernet.RemovePowerStorage(this); - } } } diff --git a/Content.Server/GameObjects/Components/Power/PowerStorageNetComponent.cs b/Content.Server/GameObjects/Components/Power/PowerStorageNetComponent.cs new file mode 100644 index 0000000000..bb28c110db --- /dev/null +++ b/Content.Server/GameObjects/Components/Power/PowerStorageNetComponent.cs @@ -0,0 +1,100 @@ +using SS14.Shared.Serialization; +using SS14.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Power +{ + /// + /// Feeds energy from the powernet and may have the ability to supply back into it + /// + public class PowerStorageNetComponent : PowerStorageComponent + { + public override string Name => "PowerStorage"; + + private bool _chargePowernet = false; + + /// + /// Do we distribute power into the powernet from our stores if the powernet requires it? + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool ChargePowernet + { + get => _chargePowernet; + set + { + _chargePowernet = value; + if (Owner.TryGetComponent(out PowerNodeComponent node)) + { + node.Parent?.UpdateStorageType(this); + } + } + } + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(ref _chargePowernet, "chargepowernet", false); + } + + public override void OnAdd() + { + base.OnAdd(); + + if (!Owner.TryGetComponent(out PowerNodeComponent node)) + { + Owner.AddComponent(); + node = Owner.GetComponent(); + } + node.OnPowernetConnect += PowernetConnect; + node.OnPowernetDisconnect += PowernetDisconnect; + node.OnPowernetRegenerate += PowernetRegenerate; + } + + public override void OnRemove() + { + if (Owner.TryGetComponent(out PowerNodeComponent node)) + { + if (node.Parent != null) + { + node.Parent.RemovePowerStorage(this); + } + + node.OnPowernetConnect -= PowernetConnect; + node.OnPowernetDisconnect -= PowernetDisconnect; + node.OnPowernetRegenerate -= PowernetRegenerate; + } + + base.OnRemove(); + } + + /// + /// Node has become anchored to a powernet + /// + /// + /// + private void PowernetConnect(object sender, PowernetEventArgs eventarg) + { + eventarg.Powernet.AddPowerStorage(this); + } + + /// + /// Node has had its powernet regenerated + /// + /// + /// + private void PowernetRegenerate(object sender, PowernetEventArgs eventarg) + { + eventarg.Powernet.AddPowerStorage(this); + } + + /// + /// Node has become unanchored from a powernet + /// + /// + /// + private void PowernetDisconnect(object sender, PowernetEventArgs eventarg) + { + eventarg.Powernet.RemovePowerStorage(this); + } + } +} diff --git a/Content.Server/GameObjects/Components/Power/Powernet.cs b/Content.Server/GameObjects/Components/Power/Powernet.cs index 2e8796181d..d30a266418 100644 --- a/Content.Server/GameObjects/Components/Power/Powernet.cs +++ b/Content.Server/GameObjects/Components/Power/Powernet.cs @@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// A list of the energy storage components that will feed the powernet if necessary, and if there is enough power feed itself /// - private readonly List PowerStorageSupplierList = new List(); + private readonly List PowerStorageSupplierList = new List(); [ViewVariables] public int PowerStorageSupplierCount => PowerStorageSupplierList.Count; @@ -71,7 +71,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// A list of energy storage components that will never feed the powernet, will try to draw energy to feed themselves if possible /// - private readonly List PowerStorageConsumerList = new List(); + private readonly List PowerStorageConsumerList = new List(); [ViewVariables] public int PowerStorageConsumerCount => PowerStorageConsumerList.Count; @@ -473,7 +473,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// Register a power supply from a generator connected to the powernet /// - public void AddPowerStorage(PowerStorageComponent storage) + public void AddPowerStorage(PowerStorageNetComponent storage) { if (storage.ChargePowernet) PowerStorageSupplierList.Add(storage); @@ -482,7 +482,7 @@ namespace Content.Server.GameObjects.Components.Power } //How do I even call this? TODO: fix - public void UpdateStorageType(PowerStorageComponent storage) + public void UpdateStorageType(PowerStorageNetComponent storage) { //If our chargepowernet settings change we need to tell the powernet of this new setting and remove traces of our old setting if (PowerStorageSupplierList.Contains(storage)) @@ -500,7 +500,7 @@ namespace Content.Server.GameObjects.Components.Power /// /// Remove a power supply from a generator connected to the powernet /// - public void RemovePowerStorage(PowerStorageComponent storage) + public void RemovePowerStorage(PowerStorageNetComponent storage) { if (PowerStorageSupplierList.Contains(storage)) { diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj index 2601de9536..3de89ebeb9 100644 --- a/Content.Shared/Content.Shared.csproj +++ b/Content.Shared/Content.Shared.csproj @@ -67,6 +67,7 @@ + diff --git a/Content.Shared/GameObjects/Components/Power/SharedPowerCellComponent.cs b/Content.Shared/GameObjects/Components/Power/SharedPowerCellComponent.cs new file mode 100644 index 0000000000..ed5f81469b --- /dev/null +++ b/Content.Shared/GameObjects/Components/Power/SharedPowerCellComponent.cs @@ -0,0 +1,11 @@ +using System; +using SS14.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Power +{ + [Serializable, NetSerializable] + public enum PowerCellVisuals + { + ChargeLevel + } +} diff --git a/Resources/Prototypes/Entities/powercells.yml b/Resources/Prototypes/Entities/powercells.yml new file mode 100644 index 0000000000..7e50d9e86e --- /dev/null +++ b/Resources/Prototypes/Entities/powercells.yml @@ -0,0 +1,94 @@ +- type: entity + id: PowerCellSmallBase + abstract: true + parent: BaseItem + components: + - type: BoundingBox + aabb: -0.15,-0.3,0.2,0.3 + - type: PowerCell + - type: Appearance + - type: Sprite + netsync: false + +- type: entity + name: Small Standard Power Cell + id: PowerCellSmallStandard + parent: PowerCellSmallBase + components: + - type: Sprite + sprite: Objects/PowerCells/power_cell_small_st.rsi + layers: + - state: s_st + - type: Icon + sprite: Objects/PowerCells/power_cell_small_st.rsi + state: s_st + - type: PowerCell + capacity: 1500 + charge: 1500 + - type: Appearance + visuals: + - type: PowerCellVisualizer2D + prefix: s_st + + +- type: entity + name: Small High-Capacity Power Cell + id: PowerCellSmallHigh + parent: PowerCellSmallBase + components: + - type: Sprite + sprite: Objects/PowerCells/power_cell_small_hi.rsi + layers: + - state: s_hi + - type: Icon + sprite: Objects/PowerCells/power_cell_small_hi.rsi + state: s_hi + - type: PowerCell + capacity: 3000 + charge: 3000 + - type: Appearance + visuals: + - type: PowerCellVisualizer2D + prefix: s_hi + + +- type: entity + name: Small Super-Capacity Power Cell + id: PowerCellSmallSuper + parent: PowerCellSmallBase + components: + - type: Sprite + sprite: Objects/PowerCells/power_cell_small_sup.rsi + layers: + - state: s_sup + - type: Icon + sprite: Objects/PowerCells/power_cell_small_sup.rsi + state: s_sup + - type: PowerCell + capacity: 6000 + charge: 6000 + - type: Appearance + visuals: + - type: PowerCellVisualizer2D + prefix: s_sup + + +- type: entity + name: Small Hyper-Capacity Power Cell + id: PowerCellSmallHyper + parent: PowerCellSmallBase + components: + - type: Sprite + sprite: Objects/PowerCells/power_cell_small_hy.rsi + layers: + - state: s_hy + - type: Icon + sprite: Objects/PowerCells/power_cell_small_hy.rsi + state: s_hy + - type: PowerCell + capacity: 10000 + charge: 10000 + - type: Appearance + visuals: + - type: PowerCellVisualizer2D + prefix: s_hy