using System.Collections.Generic; using Content.Client.GameObjects.Components.Actor; using Content.Client.Graphics.Overlays; using Content.Client.UserInterface; using Content.Client.Utility; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Mobs; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Graphics.Overlays; using Robust.Client.Interfaces.Graphics.Overlays; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.Interfaces.UserInterface; using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Renderable; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; namespace Content.Client.GameObjects { /// /// A character UI component which shows the current damage state of the mob (living/dead) /// [RegisterComponent] public class SpeciesUI : SharedSpeciesComponent//, ICharacterUI { private StatusEffectsUI _ui; /// /// Holds the godot control for the species window /// private SpeciesWindow _window; /// /// An enum representing the current state being applied to the user /// private ScreenEffects _currentEffect = ScreenEffects.None; #pragma warning disable 649 // Required dependencies [Dependency] private readonly IOverlayManager _overlayManager; [Dependency] private readonly IPlayerManager _playerManager; [Dependency] private readonly IUserInterfaceManager _userInterfaceManager; [Dependency] private readonly IResourceCache _resourceCache; #pragma warning restore 649 //Relevant interface implementation for the character UI controller public Control Scene => _window; public UIPriority Priority => UIPriority.Species; /// /// Allows calculating if we need to act due to this component being controlled by the current mob /// private bool CurrentlyControlled => _playerManager.LocalPlayer.ControlledEntity == Owner; /// /// Holds the screen effects that can be applied mapped ot their relevant overlay /// private Dictionary EffectsDictionary; public override void OnRemove() { base.OnRemove(); _window.Dispose(); } public override void OnAdd() { base.OnAdd(); _window = new SpeciesWindow(); _ui = new StatusEffectsUI(); EffectsDictionary = new Dictionary() { { ScreenEffects.CircleMask, new CircleMaskOverlay() }, { ScreenEffects.GradientCircleMask, new GradientCircleMask() } }; } public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null) { switch (message) { case HudStateChange msg: if (CurrentlyControlled) { ChangeHudIcon(msg); } break; case PlayerAttachedMsg _: _ui.Parent?.RemoveChild(_ui); _userInterfaceManager.StateRoot.AddChild(_ui); ApplyOverlay(); break; case PlayerDetachedMsg _: _ui.Parent?.RemoveChild(_ui); RemoveOverlay(); break; } } private void ChangeHudIcon(HudStateChange changeMessage) { var path = SharedSpriteComponent.TextureRoot / changeMessage.StateSprite; var texture = _resourceCache.GetTexture(path); _window.SetIcon(texture); _ui.SetHealthIcon(texture); SetOverlay(changeMessage); } private void SetOverlay(HudStateChange message) { RemoveOverlay(); _currentEffect = message.effect; ApplyOverlay(); } private void RemoveOverlay() { if (_currentEffect != ScreenEffects.None) { var appliedEffect = EffectsDictionary[_currentEffect]; _overlayManager.RemoveOverlay(appliedEffect.ID); } _currentEffect = ScreenEffects.None; } private void ApplyOverlay() { if (_currentEffect != ScreenEffects.None) { var overlay = EffectsDictionary[_currentEffect]; if (_overlayManager.HasOverlay(overlay.ID)) { return; } _overlayManager.AddOverlay(overlay); } } private class SpeciesWindow : TextureRect { public SpeciesWindow() { SizeFlagsHorizontal = SizeFlags.ShrinkCenter; SizeFlagsVertical = SizeFlags.None; Texture = IoCManager.Resolve().GetTexture("/Textures/Mob/UI/Human/human0.png"); } public void SetIcon(Texture texture) { Texture = texture; } } } }