Cleanup BatterySystem (#41298)
* cleanup * fix fixtures * this belongs into the next PR * review * misc --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
@@ -402,8 +402,8 @@ namespace Content.IntegrationTests.Tests.Power
|
||||
battery = entityManager.GetComponent<BatteryComponent>(generatorEnt);
|
||||
consumer = entityManager.GetComponent<PowerConsumerComponent>(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
|
||||
});
|
||||
|
||||
@@ -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<BatterySelfRechargerComponent>(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<StationInfiniteBatteryTargetComponent>(ent))
|
||||
continue;
|
||||
var battery = EnsureComp<BatteryComponent>(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<StationInfiniteBatteryTargetComponent>(ent))
|
||||
continue;
|
||||
var battery = EnsureComp<BatteryComponent>(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<BatterySelfRechargerComponent>(ent);
|
||||
var battery = EnsureComp<BatteryComponent>(ent);
|
||||
|
||||
recharger.AutoRecharge = true;
|
||||
recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
|
||||
recharger.AutoRechargePause = false; // No delay.
|
||||
recharger.AutoRechargePauseTime = TimeSpan.Zero; // No delay.
|
||||
}
|
||||
},
|
||||
Impact = LogImpact.Extreme,
|
||||
|
||||
@@ -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<ApcPowerReceiverComponent>(entity.Owner, out var receiver))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -340,7 +340,7 @@ public sealed partial class MechSystem : SharedMechSystem
|
||||
if (!TryComp<BatteryComponent>(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}");
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public sealed class SpaceNinjaSystem : SharedSpaceNinjaSystem
|
||||
/// <inheritdoc/>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.Power.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Self-recharging battery.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class BatterySelfRechargerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Does the entity auto recharge?
|
||||
/// </summary>
|
||||
[DataField] public bool AutoRecharge;
|
||||
|
||||
/// <summary>
|
||||
/// At what rate does the entity automatically recharge?
|
||||
/// </summary>
|
||||
[DataField] public float AutoRechargeRate;
|
||||
|
||||
/// <summary>
|
||||
/// Should this entity stop automatically recharging if a charge is used?
|
||||
/// </summary>
|
||||
[DataField] public bool AutoRechargePause = false;
|
||||
|
||||
/// <summary>
|
||||
/// How long should the entity stop automatically recharging if a charge is used?
|
||||
/// </summary>
|
||||
[DataField] public float AutoRechargePauseTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Do not auto recharge if this timestamp has yet to happen, set for the auto recharge pause system.
|
||||
/// </summary>
|
||||
[DataField] public TimeSpan NextAutoRecharge = TimeSpan.FromSeconds(0f);
|
||||
}
|
||||
}
|
||||
104
Content.Server/Power/EntitySystems/BatterySystem.API.cs
Normal file
104
Content.Server/Power/EntitySystems/BatterySystem.API.cs
Normal file
@@ -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<BatteryComponent?> 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<BatteryComponent?> 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<BatteryComponent?> 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<BatteryComponent?> 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<BatteryComponent?> 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<BatterySelfRechargerComponent?> 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<BatterySelfRechargerComponent?> ent, TimeSpan cooldown)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
return;
|
||||
|
||||
ent.Comp.NextAutoRecharge = _timing.CurTime + cooldown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the battery is full.
|
||||
/// </summary>
|
||||
public bool IsFull(Entity<BatteryComponent?> ent)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
return false;
|
||||
|
||||
return ent.Comp.CurrentCharge >= ent.Comp.MaxCharge;
|
||||
}
|
||||
}
|
||||
@@ -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<ExaminableBatteryComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<BatteryComponent, RejuvenateEvent>(OnBatteryRejuvenate);
|
||||
SubscribeLocalEvent<PowerNetworkBatteryComponent, RejuvenateEvent>(OnNetBatteryRejuvenate);
|
||||
SubscribeLocalEvent<BatteryComponent, PriceCalculationEvent>(CalculateBatteryPrice);
|
||||
SubscribeLocalEvent<BatteryComponent, ChangeChargeEvent>(OnChangeCharge);
|
||||
SubscribeLocalEvent<BatteryComponent, GetChargeEvent>(OnGetCharge);
|
||||
|
||||
SubscribeLocalEvent<NetworkBatteryPreSync>(PreSync);
|
||||
SubscribeLocalEvent<NetworkBatteryPostSync>(PostSync);
|
||||
}
|
||||
|
||||
private void OnNetBatteryRejuvenate(Entity<PowerNetworkBatteryComponent> ent, ref RejuvenateEvent args)
|
||||
{
|
||||
ent.Comp.NetworkBattery.CurrentStorage = ent.Comp.NetworkBattery.Capacity;
|
||||
}
|
||||
|
||||
private void OnBatteryRejuvenate(Entity<BatteryComponent> ent, ref RejuvenateEvent args)
|
||||
{
|
||||
SetCharge(ent.AsNullable(), ent.Comp.MaxCharge);
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<ExaminableBatteryComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange)
|
||||
return;
|
||||
|
||||
if (!TryComp<BatteryComponent>(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<PowerNetworkBatteryComponent, BatteryComponent>();
|
||||
while (enumerator.MoveNext(out var netBat, out var bat))
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ExaminableBatteryComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<PowerNetworkBatteryComponent, RejuvenateEvent>(OnNetBatteryRejuvenate);
|
||||
SubscribeLocalEvent<BatteryComponent, RejuvenateEvent>(OnBatteryRejuvenate);
|
||||
SubscribeLocalEvent<BatteryComponent, PriceCalculationEvent>(CalculateBatteryPrice);
|
||||
SubscribeLocalEvent<BatteryComponent, ChangeChargeEvent>(OnChangeCharge);
|
||||
SubscribeLocalEvent<BatteryComponent, GetChargeEvent>(OnGetCharge);
|
||||
|
||||
SubscribeLocalEvent<NetworkBatteryPreSync>(PreSync);
|
||||
SubscribeLocalEvent<NetworkBatteryPostSync>(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<PowerNetworkBatteryComponent, BatteryComponent>();
|
||||
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)
|
||||
/// <summary>
|
||||
/// Gets the price for the power contained in an entity's battery.
|
||||
/// </summary>
|
||||
private void CalculateBatteryPrice(Entity<BatteryComponent> ent, ref PriceCalculationEvent args)
|
||||
{
|
||||
args.Price += ent.Comp.CurrentCharge * ent.Comp.PricePerJoule;
|
||||
}
|
||||
|
||||
private void OnChangeCharge(Entity<BatteryComponent> ent, ref ChangeChargeEvent args)
|
||||
{
|
||||
if (args.ResidualValue == 0)
|
||||
return;
|
||||
|
||||
args.ResidualValue -= ChangeCharge(ent.AsNullable(), args.ResidualValue);
|
||||
}
|
||||
|
||||
private void OnGetCharge(Entity<BatteryComponent> entity, ref GetChargeEvent args)
|
||||
{
|
||||
args.CurrentCharge += entity.Comp.CurrentCharge;
|
||||
args.MaxCharge += entity.Comp.MaxCharge;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<BatterySelfRechargerComponent, BatteryComponent>();
|
||||
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<BatteryComponent>(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<PowerNetworkBatteryComponent, BatteryComponent>();
|
||||
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<PowerNetworkBatteryComponent, BatteryComponent>();
|
||||
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<BatterySelfRechargerComponent, BatteryComponent>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the price for the power contained in an entity's battery.
|
||||
/// </summary>
|
||||
private void CalculateBatteryPrice(EntityUid uid, BatteryComponent component, ref PriceCalculationEvent args)
|
||||
{
|
||||
args.Price += component.CurrentCharge * component.PricePerJoule;
|
||||
}
|
||||
private void OnChangeCharge(Entity<BatteryComponent> entity, ref ChangeChargeEvent args)
|
||||
{
|
||||
if (args.ResidualValue == 0)
|
||||
return;
|
||||
|
||||
args.ResidualValue -= ChangeCharge(entity, args.ResidualValue);
|
||||
}
|
||||
|
||||
private void OnGetCharge(Entity<BatteryComponent> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current battery charge by some value
|
||||
/// </summary>
|
||||
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<BatterySelfRechargerComponent>(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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts the entity's self recharge on cooldown for the specified time.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If sufficient charge is available on the battery, use it. Otherwise, don't.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the battery is full.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<ActiveRadioJammerComponent>(uid);
|
||||
|
||||
@@ -125,7 +125,7 @@ public sealed class StationAiSystem : SharedStationAiSystem
|
||||
// into an AI core that has a full battery and full integrity.
|
||||
if (TryComp<BatteryComponent>(ent, out var battery))
|
||||
{
|
||||
_battery.SetCharge(ent, battery.MaxCharge);
|
||||
_battery.SetCharge((ent, battery), battery.MaxCharge);
|
||||
}
|
||||
|
||||
_damageable.ClearAllDamage(ent.Owner);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Content.Server.Stunnable.Systems
|
||||
private void OnStaminaHitAttempt(Entity<StunbatonComponent> entity, ref StaminaDamageOnHitAttemptEvent args)
|
||||
{
|
||||
if (!_itemToggle.IsActivated(entity.Owner) ||
|
||||
!TryComp<BatteryComponent>(entity.Owner, out var battery) || !_battery.TryUseCharge(entity.Owner, entity.Comp.EnergyPerUse, battery))
|
||||
!TryComp<BatteryComponent>(entity.Owner, out var battery) || !_battery.TryUseCharge((entity.Owner, battery), entity.Comp.EnergyPerUse))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public sealed class TeslaCoilSystem : EntitySystem
|
||||
{
|
||||
if (TryComp<BatteryComponent>(coil, out var batteryComponent))
|
||||
{
|
||||
_battery.SetCharge(coil, batteryComponent.CurrentCharge + coil.Comp.ChargeFromLightning);
|
||||
_battery.SetCharge((coil, batteryComponent), batteryComponent.CurrentCharge + coil.Comp.ChargeFromLightning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public sealed partial class GunSystem
|
||||
|
||||
protected override void TakeCharge(Entity<BatteryAmmoProviderComponent> entity)
|
||||
{
|
||||
// Take charge from either the BatteryComponent or PowerCellSlotComponent.
|
||||
var ev = new ChangeChargeEvent(-entity.Comp.FireCost);
|
||||
RaiseLocalEvent(entity, ref ev);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public sealed class XAEChargeBatterySystem : BaseXAESystem<XAEChargeBatteryCompo
|
||||
_lookup.GetEntitiesInRange(args.Coordinates, chargeBatteryComponent.Radius, _batteryEntities);
|
||||
foreach (var battery in _batteryEntities)
|
||||
{
|
||||
_battery.SetCharge(battery, battery.Comp.MaxCharge, battery);
|
||||
_battery.SetCharge(battery.AsNullable(), battery.Comp.MaxCharge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using Content.Shared.Power.Components;
|
||||
using Content.Shared.PowerCell.Components;
|
||||
|
||||
namespace Content.Shared.Power;
|
||||
|
||||
/// <summary>
|
||||
@@ -7,27 +10,36 @@ namespace Content.Shared.Power;
|
||||
public readonly record struct ChargeChangedEvent(float Charge, float MaxCharge);
|
||||
|
||||
/// <summary>
|
||||
/// Event that supports multiple battery types.
|
||||
/// Raised when it is necessary to get information about battery charges.
|
||||
/// Works with either <see cref="BatteryComponent"/> or <see cref="PowerCellSlotComponent"/>.
|
||||
/// If there are multiple batteries then the results will be summed up.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public sealed class GetChargeEvent : EntityEventArgs
|
||||
public record struct GetChargeEvent
|
||||
{
|
||||
public float CurrentCharge;
|
||||
public float MaxCharge;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 <see cref="BatteryComponent"/> or <see cref="PowerCellSlotComponent"/>.
|
||||
/// If there are multiple batteries then they will be changed in order of subscription until the total value was reached.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public sealed class ChangeChargeEvent : EntityEventArgs
|
||||
public record struct ChangeChargeEvent(float Amount)
|
||||
{
|
||||
public float OriginalValue;
|
||||
public float ResidualValue;
|
||||
/// <summary>
|
||||
/// The total amount of charge to change the battery's storage by (in joule).
|
||||
/// A positive value adds charge, a negative value removes charge.
|
||||
/// </summary>
|
||||
public readonly float Amount = Amount;
|
||||
|
||||
public ChangeChargeEvent(float value)
|
||||
{
|
||||
OriginalValue = value;
|
||||
ResidualValue = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// The amount of charge that still has to be removed.
|
||||
/// For cases where there are multiple batteries.
|
||||
/// </summary>
|
||||
public float ResidualValue = Amount;
|
||||
}
|
||||
|
||||
@@ -11,10 +11,8 @@ namespace Content.Shared.Power.Components;
|
||||
[Access(typeof(SharedBatterySystem))]
|
||||
public partial class BatteryComponent : Component
|
||||
{
|
||||
public string SolutionName = "battery";
|
||||
|
||||
/// <summary>
|
||||
/// Maximum charge of the battery in joules (ie. watt seconds)
|
||||
/// Maximum charge of the battery in joules (i.e. watt seconds)
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[GuidebookData]
|
||||
@@ -23,11 +21,11 @@ public partial class BatteryComponent : Component
|
||||
/// <summary>
|
||||
/// Current charge of the battery in joules (ie. watt seconds)
|
||||
/// </summary>
|
||||
[DataField("startingCharge")]
|
||||
[DataField("startingCharge")] // TODO: rename this datafield to currentCharge
|
||||
public float CurrentCharge;
|
||||
|
||||
/// <summary>
|
||||
/// The price per one joule. Default is 1 credit for 10kJ.
|
||||
/// The price per one joule. Default is 1 speso for 10kJ.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float PricePerJoule = 0.0001f;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Power.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Self-recharging battery.
|
||||
/// To be used in combination with <see cref="BatteryComponent"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent, AutoGenerateComponentPause]
|
||||
public sealed partial class BatterySelfRechargerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Is the component currently enabled?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool AutoRecharge = true;
|
||||
|
||||
/// <summary>
|
||||
/// At what rate does the entity automatically recharge?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float AutoRechargeRate;
|
||||
|
||||
/// <summary>
|
||||
/// How long should the entity stop automatically recharging if charge is used?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan AutoRechargePauseTime = TimeSpan.FromSeconds(0);
|
||||
|
||||
/// <summary>
|
||||
/// Do not auto recharge if this timestamp has yet to happen, set for the auto recharge pause system.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
[AutoPausedField]
|
||||
public TimeSpan NextAutoRecharge = TimeSpan.FromSeconds(0);
|
||||
}
|
||||
@@ -12,33 +12,61 @@ public abstract class SharedBatterySystem : EntitySystem
|
||||
SubscribeLocalEvent<BatteryComponent, EmpPulseEvent>(OnEmpPulse);
|
||||
}
|
||||
|
||||
private void OnEmpPulse(Entity<BatteryComponent> entity, ref EmpPulseEvent args)
|
||||
private void OnEmpPulse(Entity<BatteryComponent> 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)
|
||||
/// <summary>
|
||||
/// Changes the battery's charge by the given amount.
|
||||
/// A positive value will add charge, a negative value will remove charge.
|
||||
/// </summary>
|
||||
/// <returns>The actually changed amount.</returns>
|
||||
public virtual float ChangeCharge(Entity<BatteryComponent?> ent, float amount)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity has a self recharge and puts it on cooldown if applicable.
|
||||
/// Removes the given amount of charge from the battery.
|
||||
/// </summary>
|
||||
public virtual void TrySetChargeCooldown(EntityUid uid, float value = -1) { }
|
||||
/// <returns>The actually changed amount.</returns>
|
||||
public virtual float UseCharge(Entity<BatteryComponent?> ent, float amount)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public virtual bool TryUseCharge(EntityUid uid, float value, BatteryComponent? battery = null)
|
||||
/// <summary>
|
||||
/// If sufficient charge is available on the battery, use it. Otherwise, don't.
|
||||
/// Always returns false on the client.
|
||||
/// </summary>
|
||||
/// <returns>If the full amount was able to be removed.</returns>
|
||||
public virtual bool TryUseCharge(Entity<BatteryComponent?> ent, float amount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the battery's charge.
|
||||
/// </summary>
|
||||
public virtual void SetCharge(Entity<BatteryComponent?> ent, float value) { }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the battery's maximum charge.
|
||||
/// </summary>
|
||||
public virtual void SetMaxCharge(Entity<BatteryComponent?> ent, float value) { }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity has a self recharge and puts it on cooldown if applicable.
|
||||
/// Uses the cooldown time given in the component.
|
||||
/// </summary>
|
||||
public virtual void TrySetChargeCooldown(Entity<BatterySelfRechargerComponent?> ent) { }
|
||||
|
||||
/// <summary>
|
||||
/// Puts the entity's self recharge on cooldown for the specified time.
|
||||
/// </summary>
|
||||
public virtual void SetChargeCooldown(Entity<BatterySelfRechargerComponent?> ent, TimeSpan cooldown) { }
|
||||
}
|
||||
|
||||
@@ -494,7 +494,6 @@ entities:
|
||||
parent: 1
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 50000
|
||||
autoRecharge: True
|
||||
- proto: BasaltOne
|
||||
entities:
|
||||
- uid: 353
|
||||
|
||||
@@ -363,7 +363,6 @@ entities:
|
||||
parent: 1
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 50000
|
||||
autoRecharge: True
|
||||
- proto: AtmosFixFreezerMarker
|
||||
entities:
|
||||
- uid: 348
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -504,7 +504,6 @@ entities:
|
||||
parent: 1
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 200000
|
||||
autoRecharge: True
|
||||
- proto: BarberScissors
|
||||
entities:
|
||||
- uid: 649
|
||||
|
||||
@@ -584,7 +584,6 @@ entities:
|
||||
parent: 2
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 50000
|
||||
autoRecharge: True
|
||||
- uid: 362
|
||||
components:
|
||||
- type: Transform
|
||||
|
||||
@@ -297,7 +297,6 @@ entities:
|
||||
parent: 292
|
||||
- type: BatterySelfRecharger
|
||||
autoRechargeRate: 50000
|
||||
autoRecharge: True
|
||||
- type: Godmode
|
||||
missingComponents:
|
||||
- Construction
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -300,7 +300,6 @@
|
||||
maxCharge: 600
|
||||
startingCharge: 600
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 2
|
||||
- type: Item
|
||||
size: Normal
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
maxCharge: 1000
|
||||
startingCharge: 1000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 40
|
||||
- type: Gun
|
||||
fireRate: 0.75
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
proto: WatcherBolt
|
||||
fireCost: 50
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 50
|
||||
- type: Battery
|
||||
maxCharge: 1000
|
||||
|
||||
@@ -175,7 +175,6 @@
|
||||
maxCharge: 1000
|
||||
startingCharge: 1000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 50
|
||||
- type: Gun
|
||||
fireRate: 0.3
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
proto: RedLightLaser
|
||||
fireCost: 50
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 50
|
||||
- type: Battery
|
||||
maxCharge: 1000
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -124,6 +124,5 @@
|
||||
maxCharge: 10000
|
||||
startingCharge: 10000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 25
|
||||
- type: AmmoCounter
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
maxCharge: 1000
|
||||
startingCharge: 1000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 25
|
||||
- type: AmmoCounter
|
||||
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
maxCharge: 3000
|
||||
startingCharge: 3000
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 25
|
||||
- type: AmmoCounter
|
||||
|
||||
|
||||
@@ -132,7 +132,6 @@
|
||||
maxCharge: 90
|
||||
startingCharge: 90
|
||||
- type: BatterySelfRecharger
|
||||
autoRecharge: true
|
||||
autoRechargeRate: 1
|
||||
- type: AmmoCounter
|
||||
- type: Item
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user