fish-station/Content.Server/Ninja/Systems/NinjaSuitDrawSystem.cs
2026-01-03 19:39:41 +03:00

159 lines
5.2 KiB
C#

using Content.Server.Ninja.Events;
using Content.Shared.Clothing;
using Content.Shared.Item.ItemToggle;
using Content.Shared.Ninja.Components;
using Content.Shared.Ninja.Systems;
using Robust.Shared.Timing;
namespace Content.Server.Ninja.Systems;
/// <summary>
/// Server system for ninja equipment that draws power from the ninja suit's battery.
/// Handles the actual power draw logic using the ninja suit's battery.
/// </summary>
public sealed class NinjaSuitDrawSystem : SharedNinjaSuitDrawSystem
{
[Dependency] private readonly SpaceNinjaSystem _ninja = default!;
[Dependency] private readonly ItemToggleSystem _toggle = default!;
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NinjaSuitDrawComponent, NinjaBatteryChangedEvent>(OnBatteryChanged);
SubscribeLocalEvent<ToggleNinjaSuitDrawComponent, NinjaSuitPowerEmptyEvent>(OnPowerEmpty);
// Listen for clothing events to update power status when ninja suit is equipped/unequipped
SubscribeLocalEvent<NinjaSuitDrawComponent, ClothingGotEquippedEvent>(OnClothingEquipped);
SubscribeLocalEvent<NinjaSuitDrawComponent, ClothingGotUnequippedEvent>(OnClothingUnequipped);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<NinjaSuitDrawComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!comp.Enabled)
continue;
if (_timing.CurTime < comp.NextUpdateTime)
continue;
comp.NextUpdateTime += comp.Delay;
// Get the user wearing this equipment
var user = Transform(uid).ParentUid;
if (!_ninja.IsNinja(user))
continue;
// Try to draw power from the ninja suit
if (_ninja.GetNinjaBattery(user, out var batteryEnt, out var battery))
{
var powerToDraw = comp.DrawRate * (float)comp.Delay.TotalSeconds;
if (!_ninja.TryUseCharge(user, powerToDraw))
{
var ev = new NinjaSuitPowerEmptyEvent();
RaiseLocalEvent(uid, ref ev);
comp.Enabled = false;
}
}
else
{
// No ninja suit battery available
var ev = new NinjaSuitPowerEmptyEvent();
RaiseLocalEvent(uid, ref ev);
comp.Enabled = false;
}
}
}
private void OnBatteryChanged(Entity<NinjaSuitDrawComponent> ent, ref NinjaBatteryChangedEvent args)
{
UpdatePowerStatus(ent);
}
private void OnPowerEmpty(Entity<ToggleNinjaSuitDrawComponent> ent, ref NinjaSuitPowerEmptyEvent args)
{
_toggle.TryDeactivate(ent.Owner);
}
private void OnClothingEquipped(Entity<NinjaSuitDrawComponent> ent, ref ClothingGotEquippedEvent args)
{
UpdatePowerStatus(ent);
}
private void OnClothingUnequipped(Entity<NinjaSuitDrawComponent> ent, ref ClothingGotUnequippedEvent args)
{
UpdatePowerStatus(ent);
}
/// <summary>
/// Update the power status based on current battery state.
/// </summary>
private void UpdatePowerStatus(Entity<NinjaSuitDrawComponent> ent)
{
var user = Transform(ent).ParentUid;
if (!_ninja.IsNinja(user))
{
SetPowerStatus(ent, false, false);
return;
}
if (_ninja.GetNinjaBattery(user, out _, out var battery))
{
var canUse = ent.Comp.UseRate <= 0f || battery.LastCharge >= ent.Comp.UseRate;
var canDraw = ent.Comp.DrawRate <= 0f || battery.LastCharge > 0f;
SetPowerStatus(ent, canDraw, canUse);
if (!canUse)
{
var ev = new NinjaSuitPowerEmptyEvent();
RaiseLocalEvent(ent, ref ev);
}
}
else
{
SetPowerStatus(ent, false, false);
}
}
/// <summary>
/// Set the power status flags and dirty the component if changed.
/// </summary>
private void SetPowerStatus(Entity<NinjaSuitDrawComponent> ent, bool canDraw, bool canUse)
{
if (ent.Comp.CanDraw != canDraw || ent.Comp.CanUse != canUse)
{
ent.Comp.CanDraw = canDraw;
ent.Comp.CanUse = canUse;
Dirty(ent, ent.Comp);
}
}
public override bool CanDrawPower(Entity<NinjaSuitDrawComponent> ent)
{
var user = Transform(ent).ParentUid;
if (!_ninja.IsNinja(user))
return false;
return _ninja.GetNinjaBattery(user, out _, out var battery) && battery.LastCharge > 0f;
}
public override bool CanUse(Entity<NinjaSuitDrawComponent> ent)
{
var user = Transform(ent).ParentUid;
if (!_ninja.IsNinja(user))
return false;
return _ninja.GetNinjaBattery(user, out _, out var battery) &&
(ent.Comp.UseRate <= 0f || battery.LastCharge >= ent.Comp.UseRate);
}
}
/// <summary>
/// Event raised when ninja suit power is empty for equipment that depends on it.
/// </summary>
[ByRefEvent]
public readonly record struct NinjaSuitPowerEmptyEvent;