using Content.Server.Ninja.Events; using Content.Server.Power.EntitySystems; 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; /// /// 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. /// public sealed class NinjaSuitDrawSystem : SharedNinjaSuitDrawSystem { [Dependency] private readonly SpaceNinjaSystem _ninja = default!; [Dependency] private readonly ItemToggleSystem _toggle = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly BatterySystem _battery = default!; // Sunrise public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnBatteryChanged); SubscribeLocalEvent(OnPowerEmpty); // Listen for clothing events to update power status when ninja suit is equipped/unequipped SubscribeLocalEvent(OnClothingEquipped); SubscribeLocalEvent(OnClothingUnequipped); } public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); 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 ent, ref NinjaBatteryChangedEvent args) { UpdatePowerStatus(ent); } private void OnPowerEmpty(Entity ent, ref NinjaSuitPowerEmptyEvent args) { _toggle.TryDeactivate(ent.Owner); } private void OnClothingEquipped(Entity ent, ref ClothingGotEquippedEvent args) { UpdatePowerStatus(ent); } private void OnClothingUnequipped(Entity ent, ref ClothingGotUnequippedEvent args) { UpdatePowerStatus(ent); } /// /// Update the power status based on current battery state. /// private void UpdatePowerStatus(Entity 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.GetCharge((user, battery)) >= ent.Comp.UseRate; var canDraw = ent.Comp.DrawRate <= 0f || _battery.GetCharge((user, battery)) > 0f; SetPowerStatus(ent, canDraw, canUse); if (!canUse) { var ev = new NinjaSuitPowerEmptyEvent(); RaiseLocalEvent(ent, ref ev); } } else { SetPowerStatus(ent, false, false); } } /// /// Set the power status flags and dirty the component if changed. /// private void SetPowerStatus(Entity 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 ent) { var user = Transform(ent).ParentUid; if (!_ninja.IsNinja(user)) return false; return _ninja.GetNinjaBattery(user, out _, out var battery) && _battery.GetCharge((user, battery)) > 0f; } public override bool CanUse(Entity 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.GetCharge((user, battery)) >= ent.Comp.UseRate); } } /// /// Event raised when ninja suit power is empty for equipment that depends on it. /// [ByRefEvent] public readonly record struct NinjaSuitPowerEmptyEvent;