using Content.Shared.GameObjects.Components.Power; using SS14.Shared.GameObjects; using SS14.Shared.Interfaces.GameObjects; using SS14.Shared.IoC; using SS14.Shared.Serialization; using SS14.Shared.Utility; using System; using SS14.Shared.ViewVariables; using YamlDotNet.RepresentationModel; namespace Content.Server.GameObjects.Components.Power { /// /// Stores electrical energy. Used by power cells and SMESes. /// public abstract class PowerStorageComponent : Component { [ViewVariables] public ChargeState LastChargeState { get; private set; } = ChargeState.Still; public DateTime LastChargeStateChange { get; private set; } /// /// Maximum amount of energy the internal battery can store. /// In Joules. /// [ViewVariables] public float Capacity => _capacity; private float _capacity = 10000; // Arbitrary value, replace. /// /// Energy the battery is currently storing. /// In Joules. /// In most cases you should use and to modify this. /// [ViewVariables(VVAccess.ReadWrite)] public virtual float Charge { get => _charge; set => _charge = value; } private float _charge = 0; /// /// Rate at which energy will be taken to charge internal battery. /// In Watts. /// [ViewVariables] public float ChargeRate => _chargeRate; private float _chargeRate = 1000; /// /// Rate at which energy will be distributed to the powernet if needed. /// In Watts. /// [ViewVariables] public float DistributionRate => _distributionRate; private float _distributionRate = 1000; [ViewVariables] public bool Full => Charge >= Capacity; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); serializer.DataField(ref _capacity, "capacity", 10000); serializer.DataField(ref _charge, "charge", 0); serializer.DataField(ref _chargeRate, "chargerate", 1000); serializer.DataField(ref _distributionRate, "distributionrate", 1000); } /// /// Checks if the storage can supply the amount of charge directly requested /// public bool CanDeductCharge(float toDeduct) { if (Charge > toDeduct) return true; return false; } /// /// Deducts the requested charge from the energy storage /// public virtual void DeductCharge(float toDeduct) { _charge = Math.Max(0, Charge - toDeduct); LastChargeState = ChargeState.Discharging; LastChargeStateChange = DateTime.Now; } public virtual void AddCharge(float charge) { _charge = Math.Min(Capacity, Charge + charge); LastChargeState = ChargeState.Charging; LastChargeStateChange = DateTime.Now; } /// /// Returns the amount of energy that can be taken in by this storage in the specified amount of time. /// public float RequestCharge(float frameTime) { return Math.Min(ChargeRate * frameTime, Capacity - Charge); } /// /// Returns the amount of energy available for discharge in the specified amount of time. /// public float AvailableCharge(float frameTime) { 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)); } public ChargeState GetChargeState(TimeSpan timeout) { if (LastChargeStateChange + timeout > DateTime.Now) { return LastChargeState; } return ChargeState.Still; } public void ChargePowerTick(float frameTime) { if (Full) { return; } AddCharge(RequestCharge(frameTime)); } } }