diff --git a/Content.Shared/Charges/Components/LimitedChargesComponent.cs b/Content.Shared/Charges/Components/LimitedChargesComponent.cs
index e879e0f1df..7891857187 100644
--- a/Content.Shared/Charges/Components/LimitedChargesComponent.cs
+++ b/Content.Shared/Charges/Components/LimitedChargesComponent.cs
@@ -16,7 +16,7 @@ public sealed partial class LimitedChargesComponent : Component
///
/// The max charges this action has.
///
- [DataField, AutoNetworkedField, Access(Other = AccessPermissions.Read)]
+ [DataField, AutoNetworkedField]
public int MaxCharges = 3;
///
diff --git a/Content.Shared/Charges/Systems/SharedChargesSystem.cs b/Content.Shared/Charges/Systems/SharedChargesSystem.cs
index e915580bae..504648c41d 100644
--- a/Content.Shared/Charges/Systems/SharedChargesSystem.cs
+++ b/Content.Shared/Charges/Systems/SharedChargesSystem.cs
@@ -94,6 +94,12 @@ public abstract class SharedChargesSystem : EntitySystem
///
/// Adds the specified charges. Does not reset the accumulator.
///
+ ///
+ /// The action to add charges to. If it doesn't have , it will be added.
+ ///
+ ///
+ /// The number of charges to add. Can be negative. Resulting charge count is clamped to [0, MaxCharges].
+ ///
public void AddCharges(Entity action, int addCharges)
{
if (addCharges == 0)
@@ -170,9 +176,21 @@ public abstract class SharedChargesSystem : EntitySystem
Dirty(action);
}
+ ///
+ /// Set the number of charges an action has.
+ ///
+ /// The action in question
+ ///
+ /// The number of charges. Clamped to [0, MaxCharges].
+ ///
+ ///
+ /// This method doesn't implicitly add
+ /// unlike some other methods in this system.
+ ///
public void SetCharges(Entity action, int value)
{
- action.Comp ??= EnsureComp(action.Owner);
+ if (!Resolve(action, ref action.Comp))
+ return;
var adjusted = Math.Clamp(value, 0, action.Comp.MaxCharges);
@@ -186,6 +204,31 @@ public abstract class SharedChargesSystem : EntitySystem
Dirty(action);
}
+ ///
+ /// Sets the maximum charges of a given action.
+ ///
+ /// The action being modified.
+ /// The new maximum charges of the action. Clamped to zero.
+ ///
+ /// Does not change the current charge count, or adjust the
+ /// accumulator for auto-recharge. It also doesn't implicitly add
+ /// unlike some other methods
+ /// in this system.
+ ///
+ public void SetMaxCharges(Entity action, int value)
+ {
+ if (!Resolve(action, ref action.Comp))
+ return;
+
+ // You can't have negative max charges (even zero is a bit goofy but eh)
+ var adjusted = Math.Max(0, value);
+ if (action.Comp.MaxCharges == adjusted)
+ return;
+
+ action.Comp.MaxCharges = adjusted;
+ Dirty(action);
+ }
+
///
/// The next time a charge will be considered to be filled.
///
diff --git a/Content.Shared/Magic/SpellbookSystem.cs b/Content.Shared/Magic/SpellbookSystem.cs
index ca01819bce..90038fa9ba 100644
--- a/Content.Shared/Magic/SpellbookSystem.cs
+++ b/Content.Shared/Magic/SpellbookSystem.cs
@@ -1,5 +1,6 @@
using Content.Shared.Actions;
-using Content.Shared.Actions.Components;
+using Content.Shared.Actions.Components;
+using Content.Shared.Charges.Components;
using Content.Shared.Charges.Systems;
using Content.Shared.DoAfter;
using Content.Shared.Interaction.Events;
@@ -29,14 +30,19 @@ public sealed class SpellbookSystem : EntitySystem
{
foreach (var (id, charges) in ent.Comp.SpellActions)
{
- var spell = _actionContainer.AddAction(ent, id);
- if (spell == null)
+ var action = _actionContainer.AddAction(ent, id);
+ if (action is not { } spell)
continue;
// Null means infinite charges.
if (charges is { } count)
- _sharedCharges.SetCharges(spell.Value, count);
- ent.Comp.Spells.Add(spell.Value);
+ {
+ EnsureComp(spell, out var chargeComp);
+ _sharedCharges.SetMaxCharges((spell, chargeComp), count);
+ _sharedCharges.SetCharges((spell, chargeComp), count);
+ }
+
+ ent.Comp.Spells.Add(spell);
}
}
@@ -75,9 +81,13 @@ public sealed class SpellbookSystem : EntitySystem
foreach (var (id, charges) in ent.Comp.SpellActions)
{
EntityUid? actionId = null;
- if (_actions.AddAction(args.Args.User, ref actionId, id)
- && charges is { } count) // Null means infinite charges
- _sharedCharges.SetCharges(actionId.Value, count);
+ if (!_actions.AddAction(args.Args.User, ref actionId, id)
+ || charges is not { } count // Null means infinite charges
+ || !TryComp(actionId, out var chargeComp))
+ continue;
+
+ _sharedCharges.SetMaxCharges((actionId.Value, chargeComp), count);
+ _sharedCharges.SetCharges((actionId.Value, chargeComp), count);
}
}