From 7155d0d291f083e56b6d1029649799fe813dd984 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:55:02 +0100 Subject: [PATCH] Cleanup BatterySystem (#41298) * cleanup * fix fixtures * this belongs into the next PR * review * misc --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> --- .../Tests/Power/PowerTest.cs | 44 +-- .../Systems/AdminVerbSystem.Tools.cs | 14 +- .../EntitySystems/EmergencyLightSystem.cs | 6 +- .../EntitySystems/HandheldLightSystem.cs | 2 +- Content.Server/Mech/Systems/MechSystem.cs | 2 +- .../Ninja/Systems/BatteryDrainerSystem.cs | 6 +- .../Ninja/Systems/SpaceNinjaSystem.cs | 2 +- .../BatterySelfRechargerComponent.cs | 36 -- .../Power/EntitySystems/BatterySystem.API.cs | 104 ++++++ .../Power/EntitySystems/BatterySystem.cs | 311 ++++++------------ .../Power/EntitySystems/ChargerSystem.cs | 4 +- .../Power/EntitySystems/PowerNetSystem.cs | 6 +- .../Power/SetBatteryPercentCommand.cs | 2 +- .../PowerCell/PowerCellSystem.Draw.cs | 2 +- Content.Server/PowerCell/PowerCellSystem.cs | 2 +- Content.Server/PowerSink/PowerSinkSystem.cs | 2 +- .../Radio/EntitySystems/JammerSystem.cs | 2 +- .../Silicons/StationAi/StationAiSystem.cs | 2 +- .../Stunnable/Systems/StunbatonSystem.cs | 2 +- .../Tesla/EntitySystem/TeslaCoilSystem.cs | 2 +- .../Ranged/Systems/GunSystem.Battery.cs | 1 + .../Artifact/XAE/XAEChargeBatterySystem.cs | 2 +- Content.Shared/Power/ChargeEvents.cs | 32 +- .../Power/Components/BatteryComponent.cs | 8 +- .../BatterySelfRechargerComponent.cs | 36 ++ .../EntitySystems/SharedBatterySystem.cs | 56 +++- Resources/Maps/Lavaland/grasslanddome.yml | 1 - Resources/Maps/Lavaland/snowydome.yml | 1 - Resources/Maps/Misc/terminal.yml | 6 - Resources/Maps/Nonstations/wizardsden.yml | 1 - Resources/Maps/Ruins/ruined_prison_ship.yml | 1 - Resources/Maps/Shuttles/arrivals.yml | 1 - .../Clothing/Head/base_clothinghead.yml | 1 - .../Entities/Clothing/OuterClothing/armor.yml | 1 - .../Entities/Mobs/NPCs/behonker.yml | 1 - .../Entities/Mobs/NPCs/lavaland.yml | 1 - .../Entities/Mobs/NPCs/living_light.yml | 1 - .../Entities/Mobs/NPCs/miscellaneous.yml | 1 - .../Entities/Objects/Power/powercells.yml | 4 - .../Weapons/Guns/Battery/battery_guns.yml | 5 - .../Objects/Weapons/Guns/LMGs/lmgs.yml | 1 - .../Objects/Weapons/Guns/Pistols/pistols.yml | 1 - .../Objects/Weapons/Guns/SMGs/smgs.yml | 1 - .../Objects/Weapons/Guns/pneumatic_cannon.yml | 1 - .../Entities/Structures/Power/debug_power.yml | 4 - 45 files changed, 356 insertions(+), 366 deletions(-) delete mode 100644 Content.Server/Power/Components/BatterySelfRechargerComponent.cs create mode 100644 Content.Server/Power/EntitySystems/BatterySystem.API.cs create mode 100644 Content.Shared/Power/Components/BatterySelfRechargerComponent.cs diff --git a/Content.IntegrationTests/Tests/Power/PowerTest.cs b/Content.IntegrationTests/Tests/Power/PowerTest.cs index ab8a421c03..85bd366697 100644 --- a/Content.IntegrationTests/Tests/Power/PowerTest.cs +++ b/Content.IntegrationTests/Tests/Power/PowerTest.cs @@ -402,8 +402,8 @@ namespace Content.IntegrationTests.Tests.Power battery = entityManager.GetComponent(generatorEnt); consumer = entityManager.GetComponent(consumerEnt); - batterySys.SetMaxCharge(generatorEnt, startingCharge, battery); - batterySys.SetCharge(generatorEnt, startingCharge, battery); + batterySys.SetMaxCharge((generatorEnt, battery), startingCharge); + batterySys.SetCharge((generatorEnt, battery), startingCharge); netBattery.MaxSupply = 400; netBattery.SupplyRampRate = 400; netBattery.SupplyRampTolerance = 100; @@ -513,8 +513,8 @@ namespace Content.IntegrationTests.Tests.Power supplier.SupplyRampRate = rampRate; supplier.SupplyRampTolerance = rampTol; - batterySys.SetMaxCharge(batteryEnt, 100_000, battery); - batterySys.SetCharge(batteryEnt, 100_000, battery); + batterySys.SetMaxCharge((batteryEnt, battery), 100_000); + batterySys.SetCharge((batteryEnt, battery), 100_000); netBattery.MaxSupply = draw / 2; netBattery.SupplyRampRate = rampRate; netBattery.SupplyRampTolerance = rampTol; @@ -600,7 +600,7 @@ namespace Content.IntegrationTests.Tests.Power supplier.MaxSupply = 500; supplier.SupplyRampTolerance = 500; - batterySys.SetMaxCharge(batteryEnt, 100_000, battery); + batterySys.SetMaxCharge((batteryEnt, battery), 100_000); netBattery.MaxChargeRate = 1_000; netBattery.Efficiency = 0.5f; }); @@ -670,8 +670,8 @@ namespace Content.IntegrationTests.Tests.Power netBattery.MaxSupply = 400; netBattery.SupplyRampTolerance = 400; netBattery.SupplyRampRate = 100_000; - batterySys.SetMaxCharge(batteryEnt, 100_000, battery); - batterySys.SetCharge(batteryEnt, 100_000, battery); + batterySys.SetMaxCharge((batteryEnt, battery), 100_000); + batterySys.SetCharge((batteryEnt, battery), 100_000); }); // Run some ticks so everything is stable. @@ -750,8 +750,8 @@ namespace Content.IntegrationTests.Tests.Power netBattery.SupplyRampTolerance = 400; netBattery.SupplyRampRate = 100_000; netBattery.Efficiency = 0.5f; - batterySys.SetMaxCharge(batteryEnt, 1_000_000, battery); - batterySys.SetCharge(batteryEnt, 1_000_000, battery); + batterySys.SetMaxCharge((batteryEnt, battery), 1_000_000); + batterySys.SetCharge((batteryEnt, battery), 1_000_000); }); // Run some ticks so everything is stable. @@ -841,8 +841,8 @@ namespace Content.IntegrationTests.Tests.Power supplier.MaxSupply = 1000; supplier.SupplyRampTolerance = 1000; - batterySys.SetMaxCharge(batteryEnt1, 1_000_000, battery1); - batterySys.SetMaxCharge(batteryEnt2, 1_000_000, battery2); + batterySys.SetMaxCharge((batteryEnt1, battery1), 1_000_000); + batterySys.SetMaxCharge((batteryEnt2, battery2), 1_000_000); netBattery1.MaxChargeRate = 1_000; netBattery2.MaxChargeRate = 1_000; @@ -945,10 +945,10 @@ namespace Content.IntegrationTests.Tests.Power netBattery2.SupplyRampTolerance = 1000; netBattery1.SupplyRampRate = 100_000; netBattery2.SupplyRampRate = 100_000; - batterySys.SetMaxCharge(batteryEnt1, 100_000, battery1); - batterySys.SetMaxCharge(batteryEnt2, 100_000, battery2); - batterySys.SetCharge(batteryEnt1, 100_000, battery1); - batterySys.SetCharge(batteryEnt2, 100_000, battery2); + batterySys.SetMaxCharge((batteryEnt1, battery1), 100_000); + batterySys.SetMaxCharge((batteryEnt2, battery2), 100_000); + batterySys.SetCharge((batteryEnt1, battery1), 100_000); + batterySys.SetCharge((batteryEnt2, battery2), 100_000); }); // Run some ticks so everything is stable. @@ -1031,8 +1031,8 @@ namespace Content.IntegrationTests.Tests.Power supplier.MaxSupply = 1000; supplier.SupplyRampTolerance = 1000; - batterySys.SetMaxCharge(batteryEnt1, 1_000_000, battery1); - batterySys.SetMaxCharge(batteryEnt2, 1_000_000, battery2); + batterySys.SetMaxCharge((batteryEnt1, battery1), 1_000_000); + batterySys.SetMaxCharge((batteryEnt2, battery2), 1_000_000); netBattery1.MaxChargeRate = 20; netBattery2.MaxChargeRate = 20; @@ -1107,8 +1107,8 @@ namespace Content.IntegrationTests.Tests.Power netBattery.MaxSupply = 1000; netBattery.SupplyRampTolerance = 200; netBattery.SupplyRampRate = 10; - batterySys.SetMaxCharge(batteryEnt, 100_000, battery); - batterySys.SetCharge(batteryEnt, 100_000, battery); + batterySys.SetMaxCharge((batteryEnt, battery), 100_000); + batterySys.SetCharge((batteryEnt, battery), 100_000); }); // Run some ticks so everything is stable. @@ -1253,7 +1253,7 @@ namespace Content.IntegrationTests.Tests.Power generatorSupplier.MaxSupply = 1000; generatorSupplier.SupplyRampTolerance = 1000; - batterySys.SetCharge(apcEnt, 0, apcBattery); + batterySys.SetCharge((apcEnt, apcBattery), 0); }); server.RunTicks(5); //let run a few ticks for PowerNets to reevaluate and start charging apc @@ -1314,8 +1314,8 @@ namespace Content.IntegrationTests.Tests.Power extensionCableSystem.SetProviderTransferRange(apcExtensionEnt, range); extensionCableSystem.SetReceiverReceptionRange(powerReceiverEnt, range); - batterySys.SetMaxCharge(apcEnt, 10000, battery); //arbitrary nonzero amount of charge - batterySys.SetCharge(apcEnt, battery.MaxCharge, battery); //fill battery + batterySys.SetMaxCharge((apcEnt, battery), 10000); //arbitrary nonzero amount of charge + batterySys.SetCharge((apcEnt, battery), battery.MaxCharge); //fill battery receiver.Load = 1; //arbitrary small amount of power }); diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs index 41228b5ac8..4f96a25a5c 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs @@ -169,7 +169,7 @@ public sealed partial class AdminVerbSystem Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")), Act = () => { - _batterySystem.SetCharge(args.Target, battery.MaxCharge, battery); + _batterySystem.SetCharge((args.Target, battery), battery.MaxCharge); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-refill-battery-description"), @@ -184,7 +184,7 @@ public sealed partial class AdminVerbSystem Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")), Act = () => { - _batterySystem.SetCharge(args.Target, 0, battery); + _batterySystem.SetCharge((args.Target, battery), 0); }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-drain-battery-description"), @@ -200,9 +200,8 @@ public sealed partial class AdminVerbSystem Act = () => { var recharger = EnsureComp(args.Target); - recharger.AutoRecharge = true; recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill. - recharger.AutoRechargePause = false; // No delay. + recharger.AutoRechargePauseTime = TimeSpan.Zero; // No delay. }, Impact = LogImpact.Medium, Message = Loc.GetString("admin-trick-infinite-battery-object-description"), @@ -553,7 +552,7 @@ public sealed partial class AdminVerbSystem if (!HasComp(ent)) continue; var battery = EnsureComp(ent); - _batterySystem.SetCharge(ent, battery.MaxCharge, battery); + _batterySystem.SetCharge((ent, battery), battery.MaxCharge); } }, Impact = LogImpact.Extreme, @@ -574,7 +573,7 @@ public sealed partial class AdminVerbSystem if (!HasComp(ent)) continue; var battery = EnsureComp(ent); - _batterySystem.SetCharge(ent, 0, battery); + _batterySystem.SetCharge((ent, battery), 0); } }, Impact = LogImpact.Extreme, @@ -599,9 +598,8 @@ public sealed partial class AdminVerbSystem var recharger = EnsureComp(ent); var battery = EnsureComp(ent); - recharger.AutoRecharge = true; recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill. - recharger.AutoRechargePause = false; // No delay. + recharger.AutoRechargePauseTime = TimeSpan.Zero; // No delay. } }, Impact = LogImpact.Extreme, diff --git a/Content.Server/Light/EntitySystems/EmergencyLightSystem.cs b/Content.Server/Light/EntitySystems/EmergencyLightSystem.cs index 0aea245c79..eddef87853 100644 --- a/Content.Server/Light/EntitySystems/EmergencyLightSystem.cs +++ b/Content.Server/Light/EntitySystems/EmergencyLightSystem.cs @@ -145,7 +145,7 @@ public sealed class EmergencyLightSystem : SharedEmergencyLightSystem { if (entity.Comp.State == EmergencyLightState.On) { - if (!_battery.TryUseCharge(entity.Owner, entity.Comp.Wattage * frameTime, battery)) + if (!_battery.TryUseCharge((entity.Owner, battery), entity.Comp.Wattage * frameTime)) { SetState(entity.Owner, entity.Comp, EmergencyLightState.Empty); TurnOff(entity); @@ -153,8 +153,8 @@ public sealed class EmergencyLightSystem : SharedEmergencyLightSystem } else { - _battery.SetCharge(entity.Owner, battery.CurrentCharge + entity.Comp.ChargingWattage * frameTime * entity.Comp.ChargingEfficiency, battery); - if (_battery.IsFull(entity, battery)) + _battery.SetCharge((entity.Owner, battery), battery.CurrentCharge + entity.Comp.ChargingWattage * frameTime * entity.Comp.ChargingEfficiency); + if (_battery.IsFull((entity.Owner, battery))) { if (TryComp(entity.Owner, out var receiver)) { diff --git a/Content.Server/Light/EntitySystems/HandheldLightSystem.cs b/Content.Server/Light/EntitySystems/HandheldLightSystem.cs index 2c8d18539f..7167aa4963 100644 --- a/Content.Server/Light/EntitySystems/HandheldLightSystem.cs +++ b/Content.Server/Light/EntitySystems/HandheldLightSystem.cs @@ -253,7 +253,7 @@ namespace Content.Server.Light.EntitySystems _appearance.SetData(uid, HandheldLightVisuals.Power, HandheldLightPowerStates.Dying, appearanceComponent); } - if (component.Activated && !_battery.TryUseCharge(batteryUid.Value, component.Wattage * frameTime, battery)) + if (component.Activated && !_battery.TryUseCharge((batteryUid.Value, battery), component.Wattage * frameTime)) TurnOff(uid, false); UpdateLevel(uid); diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs index 923c701868..89297a6e86 100644 --- a/Content.Server/Mech/Systems/MechSystem.cs +++ b/Content.Server/Mech/Systems/MechSystem.cs @@ -340,7 +340,7 @@ public sealed partial class MechSystem : SharedMechSystem if (!TryComp(battery, out var batteryComp)) return false; - _battery.SetCharge(battery!.Value, batteryComp.CurrentCharge + delta.Float(), batteryComp); + _battery.SetCharge((battery.Value, batteryComp), batteryComp.CurrentCharge + delta.Float()); if (batteryComp.CurrentCharge != component.Energy) //if there's a discrepency, we have to resync them { Log.Debug($"Battery charge was not equal to mech charge. Battery {batteryComp.CurrentCharge}. Mech {component.Energy}"); diff --git a/Content.Server/Ninja/Systems/BatteryDrainerSystem.cs b/Content.Server/Ninja/Systems/BatteryDrainerSystem.cs index e563386608..7b9d229d73 100644 --- a/Content.Server/Ninja/Systems/BatteryDrainerSystem.cs +++ b/Content.Server/Ninja/Systems/BatteryDrainerSystem.cs @@ -95,17 +95,17 @@ public sealed class BatteryDrainerSystem : SharedBatteryDrainerSystem // higher tier storages can charge more var maxDrained = pnb.MaxSupply * comp.DrainTime; var input = Math.Min(Math.Min(available, required / comp.DrainEfficiency), maxDrained); - if (!_battery.TryUseCharge(target, input, targetBattery)) + if (!_battery.TryUseCharge((target, targetBattery), input)) return false; var output = input * comp.DrainEfficiency; - _battery.SetCharge(comp.BatteryUid.Value, battery.CurrentCharge + output, battery); + _battery.SetCharge((comp.BatteryUid.Value, battery), battery.CurrentCharge + output); // TODO: create effect message or something Spawn("EffectSparks", Transform(target).Coordinates); _audio.PlayPvs(comp.SparkSound, target); _popup.PopupEntity(Loc.GetString("battery-drainer-success", ("battery", target)), uid, uid); // repeat the doafter until battery is full - return !_battery.IsFull(comp.BatteryUid.Value, battery); + return !_battery.IsFull((comp.BatteryUid.Value, battery)); } } diff --git a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs index ff88926723..fd7f908738 100644 --- a/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs +++ b/Content.Server/Ninja/Systems/SpaceNinjaSystem.cs @@ -106,7 +106,7 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem /// public override bool TryUseCharge(EntityUid user, float charge) { - return GetNinjaBattery(user, out var uid, out var battery) && _battery.TryUseCharge(uid.Value, charge, battery); + return GetNinjaBattery(user, out var uid, out var battery) && _battery.TryUseCharge((uid.Value, battery), charge); } /// diff --git a/Content.Server/Power/Components/BatterySelfRechargerComponent.cs b/Content.Server/Power/Components/BatterySelfRechargerComponent.cs deleted file mode 100644 index 1cb92d9cd6..0000000000 --- a/Content.Server/Power/Components/BatterySelfRechargerComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace Content.Server.Power.Components -{ - /// - /// Self-recharging battery. - /// - [RegisterComponent] - public sealed partial class BatterySelfRechargerComponent : Component - { - /// - /// Does the entity auto recharge? - /// - [DataField] public bool AutoRecharge; - - /// - /// At what rate does the entity automatically recharge? - /// - [DataField] public float AutoRechargeRate; - - /// - /// Should this entity stop automatically recharging if a charge is used? - /// - [DataField] public bool AutoRechargePause = false; - - /// - /// How long should the entity stop automatically recharging if a charge is used? - /// - [DataField] public float AutoRechargePauseTime = 0f; - - /// - /// Do not auto recharge if this timestamp has yet to happen, set for the auto recharge pause system. - /// - [DataField] public TimeSpan NextAutoRecharge = TimeSpan.FromSeconds(0f); - } -} diff --git a/Content.Server/Power/EntitySystems/BatterySystem.API.cs b/Content.Server/Power/EntitySystems/BatterySystem.API.cs new file mode 100644 index 0000000000..6ddf1f4bbc --- /dev/null +++ b/Content.Server/Power/EntitySystems/BatterySystem.API.cs @@ -0,0 +1,104 @@ +using Content.Shared.Power; +using Content.Shared.Power.Components; + +namespace Content.Server.Power.EntitySystems; + +public sealed partial class BatterySystem +{ + public override float ChangeCharge(Entity ent, float amount) + { + if (!Resolve(ent, ref ent.Comp)) + return 0; + + var newValue = Math.Clamp(ent.Comp.CurrentCharge + amount, 0, ent.Comp.MaxCharge); + var delta = newValue - ent.Comp.CurrentCharge; + ent.Comp.CurrentCharge = newValue; + + TrySetChargeCooldown(ent.Owner); + + var ev = new ChargeChangedEvent(ent.Comp.CurrentCharge, ent.Comp.MaxCharge); + RaiseLocalEvent(ent, ref ev); + return delta; + } + + public override float UseCharge(Entity ent, float amount) + { + if (amount <= 0 || !Resolve(ent, ref ent.Comp) || ent.Comp.CurrentCharge == 0) + return 0; + + return ChangeCharge(ent, -amount); + } + + public override bool TryUseCharge(Entity ent, float amount) + { + if (!Resolve(ent, ref ent.Comp, false) || amount > ent.Comp.CurrentCharge) + return false; + + UseCharge(ent, amount); + return true; + } + + public override void SetCharge(Entity ent, float value) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + var oldCharge = ent.Comp.CurrentCharge; + ent.Comp.CurrentCharge = MathHelper.Clamp(value, 0, ent.Comp.MaxCharge); + if (MathHelper.CloseTo(ent.Comp.CurrentCharge, oldCharge) && + !(oldCharge != ent.Comp.CurrentCharge && ent.Comp.CurrentCharge == ent.Comp.MaxCharge)) + { + return; + } + + var ev = new ChargeChangedEvent(ent.Comp.CurrentCharge, ent.Comp.MaxCharge); + RaiseLocalEvent(ent, ref ev); + } + public override void SetMaxCharge(Entity ent, float value) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + var old = ent.Comp.MaxCharge; + ent.Comp.MaxCharge = Math.Max(value, 0); + ent.Comp.CurrentCharge = Math.Min(ent.Comp.CurrentCharge, ent.Comp.MaxCharge); + if (MathHelper.CloseTo(ent.Comp.MaxCharge, old)) + return; + + var ev = new ChargeChangedEvent(ent.Comp.CurrentCharge, ent.Comp.MaxCharge); + RaiseLocalEvent(ent, ref ev); + } + + public override void TrySetChargeCooldown(Entity ent) + { + if (!Resolve(ent, ref ent.Comp, false)) + return; + + if (ent.Comp.AutoRechargePauseTime == TimeSpan.Zero) + return; // no recharge pause + + if (_timing.CurTime + ent.Comp.AutoRechargePauseTime <= ent.Comp.NextAutoRecharge) + return; // the current pause is already longer + + SetChargeCooldown(ent, ent.Comp.AutoRechargePauseTime); + } + + public override void SetChargeCooldown(Entity ent, TimeSpan cooldown) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + ent.Comp.NextAutoRecharge = _timing.CurTime + cooldown; + } + + /// + /// Returns whether the battery is full. + /// + public bool IsFull(Entity ent) + { + if (!Resolve(ent, ref ent.Comp)) + return false; + + return ent.Comp.CurrentCharge >= ent.Comp.MaxCharge; + } +} diff --git a/Content.Server/Power/EntitySystems/BatterySystem.cs b/Content.Server/Power/EntitySystems/BatterySystem.cs index c49a2f0f6b..4b6a52c0f1 100644 --- a/Content.Server/Power/EntitySystems/BatterySystem.cs +++ b/Content.Server/Power/EntitySystems/BatterySystem.cs @@ -9,232 +9,115 @@ using JetBrains.Annotations; using Robust.Shared.Utility; using Robust.Shared.Timing; -namespace Content.Server.Power.EntitySystems +namespace Content.Server.Power.EntitySystems; + +[UsedImplicitly] +public sealed partial class BatterySystem : SharedBatterySystem { - [UsedImplicitly] - public sealed class BatterySystem : SharedBatterySystem + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() { - [Dependency] private readonly IGameTiming _timing = default!; + base.Initialize(); - public override void Initialize() + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnBatteryRejuvenate); + SubscribeLocalEvent(OnNetBatteryRejuvenate); + SubscribeLocalEvent(CalculateBatteryPrice); + SubscribeLocalEvent(OnChangeCharge); + SubscribeLocalEvent(OnGetCharge); + + SubscribeLocalEvent(PreSync); + SubscribeLocalEvent(PostSync); + } + + private void OnNetBatteryRejuvenate(Entity ent, ref RejuvenateEvent args) + { + ent.Comp.NetworkBattery.CurrentStorage = ent.Comp.NetworkBattery.Capacity; + } + + private void OnBatteryRejuvenate(Entity ent, ref RejuvenateEvent args) + { + SetCharge(ent.AsNullable(), ent.Comp.MaxCharge); + } + + private void OnExamine(Entity ent, ref ExaminedEvent args) + { + if (!args.IsInDetailsRange) + return; + + if (!TryComp(ent, out var battery)) + return; + + var chargePercentRounded = 0; + if (battery.MaxCharge != 0) + chargePercentRounded = (int)(100 * battery.CurrentCharge / battery.MaxCharge); + args.PushMarkup( + Loc.GetString( + "examinable-battery-component-examine-detail", + ("percent", chargePercentRounded), + ("markupPercentColor", "green") + ) + ); + } + + private void PreSync(NetworkBatteryPreSync ev) + { + // Ignoring entity pausing. If the entity was paused, neither component's data should have been changed. + var enumerator = AllEntityQuery(); + while (enumerator.MoveNext(out var netBat, out var bat)) { - base.Initialize(); - - SubscribeLocalEvent(OnExamine); - SubscribeLocalEvent(OnNetBatteryRejuvenate); - SubscribeLocalEvent(OnBatteryRejuvenate); - SubscribeLocalEvent(CalculateBatteryPrice); - SubscribeLocalEvent(OnChangeCharge); - SubscribeLocalEvent(OnGetCharge); - - SubscribeLocalEvent(PreSync); - SubscribeLocalEvent(PostSync); + DebugTools.Assert(bat.CurrentCharge <= bat.MaxCharge && bat.CurrentCharge >= 0); + netBat.NetworkBattery.Capacity = bat.MaxCharge; + netBat.NetworkBattery.CurrentStorage = bat.CurrentCharge; } + } - private void OnNetBatteryRejuvenate(EntityUid uid, PowerNetworkBatteryComponent component, RejuvenateEvent args) + private void PostSync(NetworkBatteryPostSync ev) + { + // Ignoring entity pausing. If the entity was paused, neither component's data should have been changed. + var enumerator = AllEntityQuery(); + while (enumerator.MoveNext(out var uid, out var netBat, out var bat)) { - component.NetworkBattery.CurrentStorage = component.NetworkBattery.Capacity; + SetCharge((uid, bat), netBat.NetworkBattery.CurrentStorage); } + } - private void OnBatteryRejuvenate(EntityUid uid, BatteryComponent component, RejuvenateEvent args) + /// + /// Gets the price for the power contained in an entity's battery. + /// + private void CalculateBatteryPrice(Entity ent, ref PriceCalculationEvent args) + { + args.Price += ent.Comp.CurrentCharge * ent.Comp.PricePerJoule; + } + + private void OnChangeCharge(Entity ent, ref ChangeChargeEvent args) + { + if (args.ResidualValue == 0) + return; + + args.ResidualValue -= ChangeCharge(ent.AsNullable(), args.ResidualValue); + } + + private void OnGetCharge(Entity entity, ref GetChargeEvent args) + { + args.CurrentCharge += entity.Comp.CurrentCharge; + args.MaxCharge += entity.Comp.MaxCharge; + } + + public override void Update(float frameTime) + { + var query = EntityQueryEnumerator(); + var curTime = _timing.CurTime; + while (query.MoveNext(out var uid, out var comp, out var bat)) { - SetCharge(uid, component.MaxCharge, component); - } + if (!comp.AutoRecharge || IsFull((uid, bat))) + continue; - private void OnExamine(EntityUid uid, ExaminableBatteryComponent component, ExaminedEvent args) - { - if (!TryComp(uid, out var batteryComponent)) - return; - if (args.IsInDetailsRange) - { - var effectiveMax = batteryComponent.MaxCharge; - if (effectiveMax == 0) - effectiveMax = 1; - var chargeFraction = batteryComponent.CurrentCharge / effectiveMax; - var chargePercentRounded = (int)(chargeFraction * 100); - args.PushMarkup( - Loc.GetString( - "examinable-battery-component-examine-detail", - ("percent", chargePercentRounded), - ("markupPercentColor", "green") - ) - ); - } - } + if (comp.NextAutoRecharge > curTime) + continue; - private void PreSync(NetworkBatteryPreSync ev) - { - // Ignoring entity pausing. If the entity was paused, neither component's data should have been changed. - var enumerator = AllEntityQuery(); - while (enumerator.MoveNext(out var netBat, out var bat)) - { - DebugTools.Assert(bat.CurrentCharge <= bat.MaxCharge && bat.CurrentCharge >= 0); - netBat.NetworkBattery.Capacity = bat.MaxCharge; - netBat.NetworkBattery.CurrentStorage = bat.CurrentCharge; - } - } - - private void PostSync(NetworkBatteryPostSync ev) - { - // Ignoring entity pausing. If the entity was paused, neither component's data should have been changed. - var enumerator = AllEntityQuery(); - while (enumerator.MoveNext(out var uid, out var netBat, out var bat)) - { - SetCharge(uid, netBat.NetworkBattery.CurrentStorage, bat); - } - } - - public override void Update(float frameTime) - { - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var comp, out var batt)) - { - if (!comp.AutoRecharge || IsFull(uid, batt)) - continue; - - if (comp.AutoRechargePause) - { - if (comp.NextAutoRecharge > _timing.CurTime) - continue; - } - - SetCharge(uid, batt.CurrentCharge + comp.AutoRechargeRate * frameTime, batt); - } - } - - /// - /// Gets the price for the power contained in an entity's battery. - /// - private void CalculateBatteryPrice(EntityUid uid, BatteryComponent component, ref PriceCalculationEvent args) - { - args.Price += component.CurrentCharge * component.PricePerJoule; - } - private void OnChangeCharge(Entity entity, ref ChangeChargeEvent args) - { - if (args.ResidualValue == 0) - return; - - args.ResidualValue -= ChangeCharge(entity, args.ResidualValue); - } - - private void OnGetCharge(Entity entity, ref GetChargeEvent args) - { - args.CurrentCharge += entity.Comp.CurrentCharge; - args.MaxCharge += entity.Comp.MaxCharge; - } - - public override float UseCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - if (value <= 0 || !Resolve(uid, ref battery) || battery.CurrentCharge == 0) - return 0; - - return ChangeCharge(uid, -value, battery); - } - - public override void SetMaxCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - if (!Resolve(uid, ref battery)) - return; - - var old = battery.MaxCharge; - battery.MaxCharge = Math.Max(value, 0); - battery.CurrentCharge = Math.Min(battery.CurrentCharge, battery.MaxCharge); - if (MathHelper.CloseTo(battery.MaxCharge, old)) - return; - - var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge); - RaiseLocalEvent(uid, ref ev); - } - - public void SetCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - if (!Resolve(uid, ref battery)) - return; - - var old = battery.CurrentCharge; - battery.CurrentCharge = MathHelper.Clamp(value, 0, battery.MaxCharge); - if (MathHelper.CloseTo(battery.CurrentCharge, old) && - !(old != battery.CurrentCharge && battery.CurrentCharge == battery.MaxCharge)) - { - return; - } - - var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge); - RaiseLocalEvent(uid, ref ev); - } - - /// - /// Changes the current battery charge by some value - /// - public override float ChangeCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - if (!Resolve(uid, ref battery)) - return 0; - - var newValue = Math.Clamp(battery.CurrentCharge + value, 0, battery.MaxCharge); - var delta = newValue - battery.CurrentCharge; - battery.CurrentCharge = newValue; - - TrySetChargeCooldown(uid); - - var ev = new ChargeChangedEvent(battery.CurrentCharge, battery.MaxCharge); - RaiseLocalEvent(uid, ref ev); - return delta; - } - - public override void TrySetChargeCooldown(EntityUid uid, float value = -1) - { - if (!TryComp(uid, out var batteryself)) - return; - - if (!batteryself.AutoRechargePause) - return; - - // If no answer or a negative is given for value, use the default from AutoRechargePauseTime. - if (value < 0) - value = batteryself.AutoRechargePauseTime; - - if (_timing.CurTime + TimeSpan.FromSeconds(value) <= batteryself.NextAutoRecharge) - return; - - SetChargeCooldown(uid, batteryself.AutoRechargePauseTime, batteryself); - } - - /// - /// Puts the entity's self recharge on cooldown for the specified time. - /// - public void SetChargeCooldown(EntityUid uid, float value, BatterySelfRechargerComponent? batteryself = null) - { - if (!Resolve(uid, ref batteryself)) - return; - - if (value >= 0) - batteryself.NextAutoRecharge = _timing.CurTime + TimeSpan.FromSeconds(value); - else - batteryself.NextAutoRecharge = _timing.CurTime; - } - - /// - /// If sufficient charge is available on the battery, use it. Otherwise, don't. - /// - public override bool TryUseCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - if (!Resolve(uid, ref battery, false) || value > battery.CurrentCharge) - return false; - - UseCharge(uid, value, battery); - return true; - } - - /// - /// Returns whether the battery is full. - /// - public bool IsFull(EntityUid uid, BatteryComponent? battery = null) - { - if (!Resolve(uid, ref battery)) - return false; - - return battery.CurrentCharge >= battery.MaxCharge; + SetCharge((uid, bat), bat.CurrentCharge + comp.AutoRechargeRate * frameTime); } } } diff --git a/Content.Server/Power/EntitySystems/ChargerSystem.cs b/Content.Server/Power/EntitySystems/ChargerSystem.cs index e8dc9e9962..d523de65db 100644 --- a/Content.Server/Power/EntitySystems/ChargerSystem.cs +++ b/Content.Server/Power/EntitySystems/ChargerSystem.cs @@ -221,7 +221,7 @@ public sealed class ChargerSystem : SharedChargerSystem if (!SearchForBattery(container.ContainedEntities[0], out var heldEnt, out var heldBattery)) return CellChargerStatus.Off; - if (_battery.IsFull(heldEnt.Value, heldBattery)) + if (_battery.IsFull((heldEnt.Value, heldBattery))) return CellChargerStatus.Charged; return CellChargerStatus.Charging; @@ -241,7 +241,7 @@ public sealed class ChargerSystem : SharedChargerSystem if (!SearchForBattery(targetEntity, out var batteryUid, out var heldBattery)) return; - _battery.SetCharge(batteryUid.Value, heldBattery.CurrentCharge + component.ChargeRate * frameTime, heldBattery); + _battery.SetCharge((batteryUid.Value, heldBattery), heldBattery.CurrentCharge + component.ChargeRate * frameTime); UpdateStatus(uid, component); } diff --git a/Content.Server/Power/EntitySystems/PowerNetSystem.cs b/Content.Server/Power/EntitySystems/PowerNetSystem.cs index 6a69550fcf..5b6b922ddf 100644 --- a/Content.Server/Power/EntitySystems/PowerNetSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerNetSystem.cs @@ -358,13 +358,13 @@ namespace Content.Server.Power.EntitySystems if (requireBattery) { - _battery.SetCharge(uid, battery.CurrentCharge - apcBattery.IdleLoad * frameTime, battery); + _battery.SetCharge((uid, battery), battery.CurrentCharge - apcBattery.IdleLoad * frameTime); } // Otherwise try to charge the battery - else if (powered && !_battery.IsFull(uid, battery)) + else if (powered && !_battery.IsFull((uid, battery))) { apcReceiver.Load += apcBattery.BatteryRechargeRate * apcBattery.BatteryRechargeEfficiency; - _battery.SetCharge(uid, battery.CurrentCharge + apcBattery.BatteryRechargeRate * frameTime, battery); + _battery.SetCharge((uid, battery), battery.CurrentCharge + apcBattery.BatteryRechargeRate * frameTime); } // Enable / disable the battery if the state changed diff --git a/Content.Server/Power/SetBatteryPercentCommand.cs b/Content.Server/Power/SetBatteryPercentCommand.cs index 03d6d30f8a..a6123382fd 100644 --- a/Content.Server/Power/SetBatteryPercentCommand.cs +++ b/Content.Server/Power/SetBatteryPercentCommand.cs @@ -40,7 +40,7 @@ namespace Content.Server.Power shell.WriteLine(Loc.GetString($"cmd-setbatterypercent-battery-not-found", ("id", id))); return; } - _batterySystem.SetCharge(id.Value, battery.MaxCharge * percent / 100, battery); + _batterySystem.SetCharge((id.Value, battery), battery.MaxCharge * percent / 100); // Don't acknowledge b/c people WILL forall this } } diff --git a/Content.Server/PowerCell/PowerCellSystem.Draw.cs b/Content.Server/PowerCell/PowerCellSystem.Draw.cs index 40e54ba13a..d0dafb1ef6 100644 --- a/Content.Server/PowerCell/PowerCellSystem.Draw.cs +++ b/Content.Server/PowerCell/PowerCellSystem.Draw.cs @@ -28,7 +28,7 @@ public sealed partial class PowerCellSystem if (!TryGetBatteryFromSlot(uid, out var batteryEnt, out var battery, slot)) continue; - if (_battery.TryUseCharge(batteryEnt.Value, comp.DrawRate * (float)comp.Delay.TotalSeconds, battery)) + if (_battery.TryUseCharge((batteryEnt.Value, battery), comp.DrawRate * (float)comp.Delay.TotalSeconds)) continue; var ev = new PowerCellSlotEmptyEvent(); diff --git a/Content.Server/PowerCell/PowerCellSystem.cs b/Content.Server/PowerCell/PowerCellSystem.cs index 6c00cdd300..f358e1bc34 100644 --- a/Content.Server/PowerCell/PowerCellSystem.cs +++ b/Content.Server/PowerCell/PowerCellSystem.cs @@ -174,7 +174,7 @@ public sealed partial class PowerCellSystem : SharedPowerCellSystem return false; } - if (!_battery.TryUseCharge(batteryEnt.Value, charge, battery)) + if (!_battery.TryUseCharge((batteryEnt.Value, battery), charge)) { if (user != null) _popup.PopupEntity(Loc.GetString("power-cell-insufficient"), uid, user.Value); diff --git a/Content.Server/PowerSink/PowerSinkSystem.cs b/Content.Server/PowerSink/PowerSinkSystem.cs index d1071d3e38..328bff89f4 100644 --- a/Content.Server/PowerSink/PowerSinkSystem.cs +++ b/Content.Server/PowerSink/PowerSinkSystem.cs @@ -66,7 +66,7 @@ namespace Content.Server.PowerSink if (!transform.Anchored) continue; - _battery.ChangeCharge(entity, networkLoad.NetworkLoad.ReceivingPower * frameTime, battery); + _battery.ChangeCharge((entity, battery), networkLoad.NetworkLoad.ReceivingPower * frameTime); var currentBatteryThreshold = battery.CurrentCharge / battery.MaxCharge; diff --git a/Content.Server/Radio/EntitySystems/JammerSystem.cs b/Content.Server/Radio/EntitySystems/JammerSystem.cs index 02c9c64c6e..3ec2e9c38c 100644 --- a/Content.Server/Radio/EntitySystems/JammerSystem.cs +++ b/Content.Server/Radio/EntitySystems/JammerSystem.cs @@ -34,7 +34,7 @@ public sealed class JammerSystem : SharedJammerSystem if (_powerCell.TryGetBatteryFromSlot(uid, out var batteryUid, out var battery)) { - if (!_battery.TryUseCharge(batteryUid.Value, GetCurrentWattage((uid, jam)) * frameTime, battery)) + if (!_battery.TryUseCharge((batteryUid.Value, battery), GetCurrentWattage((uid, jam)) * frameTime)) { ChangeLEDState(uid, false); RemComp(uid); diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index a9198d5816..0045b921e5 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -125,7 +125,7 @@ public sealed class StationAiSystem : SharedStationAiSystem // into an AI core that has a full battery and full integrity. if (TryComp(ent, out var battery)) { - _battery.SetCharge(ent, battery.MaxCharge); + _battery.SetCharge((ent, battery), battery.MaxCharge); } _damageable.ClearAllDamage(ent.Owner); diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs index 7f8aa37036..a22a4c09fa 100644 --- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs +++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs @@ -33,7 +33,7 @@ namespace Content.Server.Stunnable.Systems private void OnStaminaHitAttempt(Entity entity, ref StaminaDamageOnHitAttemptEvent args) { if (!_itemToggle.IsActivated(entity.Owner) || - !TryComp(entity.Owner, out var battery) || !_battery.TryUseCharge(entity.Owner, entity.Comp.EnergyPerUse, battery)) + !TryComp(entity.Owner, out var battery) || !_battery.TryUseCharge((entity.Owner, battery), entity.Comp.EnergyPerUse)) { args.Cancelled = true; } diff --git a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs index f3cae90b40..988ade86ce 100644 --- a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs +++ b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs @@ -24,7 +24,7 @@ public sealed class TeslaCoilSystem : EntitySystem { if (TryComp(coil, out var batteryComponent)) { - _battery.SetCharge(coil, batteryComponent.CurrentCharge + coil.Comp.ChargeFromLightning); + _battery.SetCharge((coil, batteryComponent), batteryComponent.CurrentCharge + coil.Comp.ChargeFromLightning); } } } diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs index 700a15e1b0..c1e442c24b 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.Battery.cs @@ -68,6 +68,7 @@ public sealed partial class GunSystem protected override void TakeCharge(Entity entity) { + // Take charge from either the BatteryComponent or PowerCellSlotComponent. var ev = new ChangeChargeEvent(-entity.Comp.FireCost); RaiseLocalEvent(entity, ref ev); } diff --git a/Content.Server/Xenoarchaeology/Artifact/XAE/XAEChargeBatterySystem.cs b/Content.Server/Xenoarchaeology/Artifact/XAE/XAEChargeBatterySystem.cs index 85ffc75627..21952912d7 100644 --- a/Content.Server/Xenoarchaeology/Artifact/XAE/XAEChargeBatterySystem.cs +++ b/Content.Server/Xenoarchaeology/Artifact/XAE/XAEChargeBatterySystem.cs @@ -25,7 +25,7 @@ public sealed class XAEChargeBatterySystem : BaseXAESystem @@ -7,27 +10,36 @@ namespace Content.Shared.Power; public readonly record struct ChargeChangedEvent(float Charge, float MaxCharge); /// +/// Event that supports multiple battery types. /// Raised when it is necessary to get information about battery charges. +/// Works with either or . +/// If there are multiple batteries then the results will be summed up. /// [ByRefEvent] -public sealed class GetChargeEvent : EntityEventArgs +public record struct GetChargeEvent { public float CurrentCharge; public float MaxCharge; } /// -/// Raised when it is necessary to change the current battery charge to a some value. +/// Method event that supports multiple battery types. +/// Raised when it is necessary to change the current battery charge by some value. +/// Works with either or . +/// If there are multiple batteries then they will be changed in order of subscription until the total value was reached. /// [ByRefEvent] -public sealed class ChangeChargeEvent : EntityEventArgs +public record struct ChangeChargeEvent(float Amount) { - public float OriginalValue; - public float ResidualValue; + /// + /// The total amount of charge to change the battery's storage by (in joule). + /// A positive value adds charge, a negative value removes charge. + /// + public readonly float Amount = Amount; - public ChangeChargeEvent(float value) - { - OriginalValue = value; - ResidualValue = value; - } + /// + /// The amount of charge that still has to be removed. + /// For cases where there are multiple batteries. + /// + public float ResidualValue = Amount; } diff --git a/Content.Shared/Power/Components/BatteryComponent.cs b/Content.Shared/Power/Components/BatteryComponent.cs index 6a2d2a5051..6a65405115 100644 --- a/Content.Shared/Power/Components/BatteryComponent.cs +++ b/Content.Shared/Power/Components/BatteryComponent.cs @@ -11,10 +11,8 @@ namespace Content.Shared.Power.Components; [Access(typeof(SharedBatterySystem))] public partial class BatteryComponent : Component { - public string SolutionName = "battery"; - /// - /// Maximum charge of the battery in joules (ie. watt seconds) + /// Maximum charge of the battery in joules (i.e. watt seconds) /// [DataField] [GuidebookData] @@ -23,11 +21,11 @@ public partial class BatteryComponent : Component /// /// Current charge of the battery in joules (ie. watt seconds) /// - [DataField("startingCharge")] + [DataField("startingCharge")] // TODO: rename this datafield to currentCharge public float CurrentCharge; /// - /// The price per one joule. Default is 1 credit for 10kJ. + /// The price per one joule. Default is 1 speso for 10kJ. /// [DataField] public float PricePerJoule = 0.0001f; diff --git a/Content.Shared/Power/Components/BatterySelfRechargerComponent.cs b/Content.Shared/Power/Components/BatterySelfRechargerComponent.cs new file mode 100644 index 0000000000..3881980382 --- /dev/null +++ b/Content.Shared/Power/Components/BatterySelfRechargerComponent.cs @@ -0,0 +1,36 @@ +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Power.Components; + +/// +/// Self-recharging battery. +/// To be used in combination with . +/// +[RegisterComponent, AutoGenerateComponentPause] +public sealed partial class BatterySelfRechargerComponent : Component +{ + /// + /// Is the component currently enabled? + /// + [DataField] + public bool AutoRecharge = true; + + /// + /// At what rate does the entity automatically recharge? + /// + [DataField] + public float AutoRechargeRate; + + /// + /// How long should the entity stop automatically recharging if charge is used? + /// + [DataField] + public TimeSpan AutoRechargePauseTime = TimeSpan.FromSeconds(0); + + /// + /// Do not auto recharge if this timestamp has yet to happen, set for the auto recharge pause system. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan NextAutoRecharge = TimeSpan.FromSeconds(0); +} diff --git a/Content.Shared/Power/EntitySystems/SharedBatterySystem.cs b/Content.Shared/Power/EntitySystems/SharedBatterySystem.cs index a9d5db3f33..d067a685d4 100644 --- a/Content.Shared/Power/EntitySystems/SharedBatterySystem.cs +++ b/Content.Shared/Power/EntitySystems/SharedBatterySystem.cs @@ -12,33 +12,61 @@ public abstract class SharedBatterySystem : EntitySystem SubscribeLocalEvent(OnEmpPulse); } - private void OnEmpPulse(Entity entity, ref EmpPulseEvent args) + private void OnEmpPulse(Entity ent, ref EmpPulseEvent args) { args.Affected = true; - UseCharge(entity, args.EnergyConsumption, entity.Comp); + UseCharge(ent.AsNullable(), args.EnergyConsumption); // Apply a cooldown to the entity's self recharge if needed to avoid it immediately self recharging after an EMP. - TrySetChargeCooldown(entity); + TrySetChargeCooldown(ent.Owner); } - public virtual float UseCharge(EntityUid uid, float value, BatteryComponent? battery = null) - { - return 0f; - } - - public virtual void SetMaxCharge(EntityUid uid, float value, BatteryComponent? battery = null) { } - - public virtual float ChangeCharge(EntityUid uid, float value, BatteryComponent? battery = null) + /// + /// Changes the battery's charge by the given amount. + /// A positive value will add charge, a negative value will remove charge. + /// + /// The actually changed amount. + public virtual float ChangeCharge(Entity ent, float amount) { return 0f; } /// - /// Checks if the entity has a self recharge and puts it on cooldown if applicable. + /// Removes the given amount of charge from the battery. /// - public virtual void TrySetChargeCooldown(EntityUid uid, float value = -1) { } + /// The actually changed amount. + public virtual float UseCharge(Entity ent, float amount) + { + return 0f; + } - public virtual bool TryUseCharge(EntityUid uid, float value, BatteryComponent? battery = null) + /// + /// If sufficient charge is available on the battery, use it. Otherwise, don't. + /// Always returns false on the client. + /// + /// If the full amount was able to be removed. + public virtual bool TryUseCharge(Entity ent, float amount) { return false; } + + /// + /// Sets the battery's charge. + /// + public virtual void SetCharge(Entity ent, float value) { } + + /// + /// Sets the battery's maximum charge. + /// + public virtual void SetMaxCharge(Entity ent, float value) { } + + /// + /// Checks if the entity has a self recharge and puts it on cooldown if applicable. + /// Uses the cooldown time given in the component. + /// + public virtual void TrySetChargeCooldown(Entity ent) { } + + /// + /// Puts the entity's self recharge on cooldown for the specified time. + /// + public virtual void SetChargeCooldown(Entity ent, TimeSpan cooldown) { } } diff --git a/Resources/Maps/Lavaland/grasslanddome.yml b/Resources/Maps/Lavaland/grasslanddome.yml index 800176593e..9d92c7b108 100644 --- a/Resources/Maps/Lavaland/grasslanddome.yml +++ b/Resources/Maps/Lavaland/grasslanddome.yml @@ -494,7 +494,6 @@ entities: parent: 1 - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - proto: BasaltOne entities: - uid: 353 diff --git a/Resources/Maps/Lavaland/snowydome.yml b/Resources/Maps/Lavaland/snowydome.yml index d9c12c724b..6c2f55049d 100644 --- a/Resources/Maps/Lavaland/snowydome.yml +++ b/Resources/Maps/Lavaland/snowydome.yml @@ -363,7 +363,6 @@ entities: parent: 1 - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - proto: AtmosFixFreezerMarker entities: - uid: 348 diff --git a/Resources/Maps/Misc/terminal.yml b/Resources/Maps/Misc/terminal.yml index 68897953f7..bb0491e9ce 100644 --- a/Resources/Maps/Misc/terminal.yml +++ b/Resources/Maps/Misc/terminal.yml @@ -1381,7 +1381,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: @@ -1398,7 +1397,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: @@ -1415,7 +1413,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: @@ -1432,7 +1429,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: @@ -1450,7 +1446,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: @@ -1467,7 +1462,6 @@ entities: - type: Godmode - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Fixtures fixtures: {} missingComponents: diff --git a/Resources/Maps/Nonstations/wizardsden.yml b/Resources/Maps/Nonstations/wizardsden.yml index b08dac6b68..7846b2596b 100644 --- a/Resources/Maps/Nonstations/wizardsden.yml +++ b/Resources/Maps/Nonstations/wizardsden.yml @@ -504,7 +504,6 @@ entities: parent: 1 - type: BatterySelfRecharger autoRechargeRate: 200000 - autoRecharge: True - proto: BarberScissors entities: - uid: 649 diff --git a/Resources/Maps/Ruins/ruined_prison_ship.yml b/Resources/Maps/Ruins/ruined_prison_ship.yml index d953e10700..89ae5e5171 100644 --- a/Resources/Maps/Ruins/ruined_prison_ship.yml +++ b/Resources/Maps/Ruins/ruined_prison_ship.yml @@ -584,7 +584,6 @@ entities: parent: 2 - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - uid: 362 components: - type: Transform diff --git a/Resources/Maps/Shuttles/arrivals.yml b/Resources/Maps/Shuttles/arrivals.yml index 3c853ef739..f419f26a1f 100644 --- a/Resources/Maps/Shuttles/arrivals.yml +++ b/Resources/Maps/Shuttles/arrivals.yml @@ -297,7 +297,6 @@ entities: parent: 292 - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: Godmode missingComponents: - Construction diff --git a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml index 53772f6215..3b85ce94c9 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/base_clothinghead.yml @@ -247,7 +247,6 @@ maxCharge: 600 #lights drain 3/s but recharge of 2 makes this 1/s. Therefore 600 is 10 minutes of light. startingCharge: 600 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 2 #recharge of 2 makes total drain 1w / s so max charge is 1:1 with time. Time to fully charge should be 5 minutes. Having recharge gives light an extended flicker period which gives you some warning to return to light area. - type: entity diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml index 5cc78d90b0..341404af2b 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml @@ -300,7 +300,6 @@ maxCharge: 600 startingCharge: 600 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 2 - type: Item size: Normal diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml index 8229b103e7..65cc71aaa8 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml @@ -26,7 +26,6 @@ maxCharge: 1000 startingCharge: 1000 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 40 - type: Gun fireRate: 0.75 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/lavaland.yml b/Resources/Prototypes/Entities/Mobs/NPCs/lavaland.yml index 7d6c28fc95..b4add804ae 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/lavaland.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/lavaland.yml @@ -54,7 +54,6 @@ proto: WatcherBolt fireCost: 50 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 50 - type: Battery maxCharge: 1000 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/living_light.yml b/Resources/Prototypes/Entities/Mobs/NPCs/living_light.yml index 4717e200dd..1531e348f7 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/living_light.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/living_light.yml @@ -175,7 +175,6 @@ maxCharge: 1000 startingCharge: 1000 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 50 - type: Gun fireRate: 0.3 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml index 64fa4e2292..173c5ad165 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml @@ -51,7 +51,6 @@ proto: RedLightLaser fireCost: 50 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 50 - type: Battery maxCharge: 1000 diff --git a/Resources/Prototypes/Entities/Objects/Power/powercells.yml b/Resources/Prototypes/Entities/Objects/Power/powercells.yml index e4651a5875..4ce96419bf 100644 --- a/Resources/Prototypes/Entities/Objects/Power/powercells.yml +++ b/Resources/Prototypes/Entities/Objects/Power/powercells.yml @@ -98,9 +98,7 @@ description: A self rechargeable power cell, designed for fast recharge rate at the expense of capacity. components: - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 36 # 10 seconds to recharge - autoRechargePause: true autoRechargePauseTime: 30 - type: entity @@ -226,7 +224,6 @@ maxCharge: 720 startingCharge: 720 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 12 # takes 1 minute to charge itself back to full - type: entity @@ -262,7 +259,6 @@ maxCharge: 1200 startingCharge: 1200 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 40 # Power cage (big heavy power cell for big devices) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index 8e2650b5fe..10181b54e7 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -664,7 +664,6 @@ proto: RedMediumLaser fireCost: 100 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 40 - type: MagazineVisuals magState: mag @@ -712,7 +711,6 @@ proto: RedMediumLaser fireCost: 100 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 30 - type: MagazineVisuals magState: mag @@ -808,7 +806,6 @@ proto: RedMediumLaser fireCost: 100 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 40 - type: StaticPrice price: 750 @@ -901,9 +898,7 @@ fireCost: 62.5 pacifismAllowedMode: true - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 48 - autoRechargePause: true autoRechargePauseTime: 10 - type: entity diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml index 80d71669a7..be57d5f0f9 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml @@ -124,6 +124,5 @@ maxCharge: 10000 startingCharge: 10000 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 25 - type: AmmoCounter diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml index ec3fa31297..ca40d1940d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml @@ -135,7 +135,6 @@ maxCharge: 1000 startingCharge: 1000 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 25 - type: AmmoCounter diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml index 2ecaaec89e..15ddb7b38e 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml @@ -160,7 +160,6 @@ maxCharge: 3000 startingCharge: 3000 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 25 - type: AmmoCounter diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml index ec7e4b3e7f..6b8c4eebe1 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/pneumatic_cannon.yml @@ -132,7 +132,6 @@ maxCharge: 90 startingCharge: 90 - type: BatterySelfRecharger - autoRecharge: true autoRechargeRate: 1 - type: AmmoCounter - type: Item diff --git a/Resources/Prototypes/Entities/Structures/Power/debug_power.yml b/Resources/Prototypes/Entities/Structures/Power/debug_power.yml index a2e1c585fb..a9c3671c33 100644 --- a/Resources/Prototypes/Entities/Structures/Power/debug_power.yml +++ b/Resources/Prototypes/Entities/Structures/Power/debug_power.yml @@ -124,7 +124,6 @@ components: - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: entity parent: BaseSubstation @@ -138,7 +137,6 @@ components: - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: entity parent: BaseSubstationWall @@ -152,7 +150,6 @@ components: - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: entity parent: BaseAPC @@ -166,7 +163,6 @@ components: - type: BatterySelfRecharger autoRechargeRate: 50000 - autoRecharge: True - type: entity id: DebugPowerReceiver