using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Overlays.Switchable; using Robust.Client.Graphics; namespace Content.Client.Overlays.Switchable; public sealed class ThermalVisionSystem : EquipmentHudSystem { [Dependency] private readonly IOverlayManager _overlayMan = default!; private ThermalVisionOverlay _thermalOverlay = default!; private BaseSwitchableOverlay _overlay = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnToggle); _thermalOverlay = new ThermalVisionOverlay(); _overlay = new BaseSwitchableOverlay(); } protected override void OnRefreshComponentHud(EntityUid uid, ThermalVisionComponent component, RefreshEquipmentHudEvent args) { if (component.IsEquipment) return; base.OnRefreshComponentHud(uid, component, args); } protected override void OnRefreshEquipmentHud(EntityUid uid, ThermalVisionComponent component, InventoryRelayedEvent> args) { if (!component.IsEquipment) return; base.OnRefreshEquipmentHud(uid, component, args); } private void OnToggle(Entity ent, ref SwitchableOverlayToggledEvent args) { RefreshOverlay(args.User); } protected override void UpdateInternal(RefreshEquipmentHudEvent args) { base.UpdateInternal(args); ThermalVisionComponent? tvComp = null; var lightRadius = 0f; foreach (var comp in args.Components) { if (!comp.IsActive && (comp.PulseTime <= 0f || comp.PulseAccumulator >= comp.PulseTime)) continue; if (tvComp == null) tvComp = comp; else if (!tvComp.DrawOverlay && comp.DrawOverlay) tvComp = comp; else if (tvComp.DrawOverlay == comp.DrawOverlay && tvComp.PulseTime > 0f && comp.PulseTime <= 0f) tvComp = comp; lightRadius = MathF.Max(lightRadius, comp.LightRadius); } UpdateThermalOverlay(tvComp, lightRadius); UpdateOverlay(tvComp); } protected override void DeactivateInternal() { base.DeactivateInternal(); _thermalOverlay.ResetLight(false); UpdateOverlay(null); UpdateThermalOverlay(null, 0f); } private void UpdateThermalOverlay(ThermalVisionComponent? comp, float lightRadius) { _thermalOverlay.LightRadius = lightRadius; _thermalOverlay.Comp = comp; switch (comp) { case not null when !_overlayMan.HasOverlay(): _overlayMan.AddOverlay(_thermalOverlay); break; case null: _overlayMan.RemoveOverlay(_thermalOverlay); _thermalOverlay.ResetLight(); break; } } private void UpdateOverlay(ThermalVisionComponent? tvComp) { _overlay.Comp = tvComp; switch (tvComp) { case { DrawOverlay: true } when !_overlayMan.HasOverlay>(): _overlayMan.AddOverlay(_overlay); break; case null or { DrawOverlay: false }: _overlayMan.RemoveOverlay(_overlay); break; } // Night vision overlay is prioritized _overlay.IsActive = !_overlayMan.HasOverlay>(); } }