diff --git a/Content.Client/UserInterface/Controls/RadialMenu.cs b/Content.Client/UserInterface/Controls/RadialMenu.cs index 5f56ad7f866..bbe3c0e1e35 100644 --- a/Content.Client/UserInterface/Controls/RadialMenu.cs +++ b/Content.Client/UserInterface/Controls/RadialMenu.cs @@ -3,6 +3,7 @@ using Robust.Client.UserInterface.CustomControls; using System.Linq; using System.Numerics; +using Robust.Client.Graphics; namespace Content.Client.UserInterface.Controls; @@ -16,7 +17,7 @@ public class RadialMenu : BaseWindow /// /// Set a style class to be applied to the contextual button when it is set to move the user back through previous layers of the radial menu - /// + /// public string? BackButtonStyleClass { get @@ -60,8 +61,8 @@ public string? CloseButtonStyleClass /// A free floating menu which enables the quick display of one or more radial containers /// /// - /// Only one radial container is visible at a time (each container forming a separate 'layer' within - /// the menu), along with a contextual button at the menu center, which will either return the user + /// Only one radial container is visible at a time (each container forming a separate 'layer' within + /// the menu), along with a contextual button at the menu center, which will either return the user /// to the previous layer or close the menu if there are no previous layers left to traverse. /// To create a functional radial menu, simply parent one or more named radial containers to it, /// and populate the radial containers with RadialMenuButtons. Setting the TargetLayer field of these diff --git a/Content.Client/_Sunrise/BloodCult/CultPentagramSystem.cs b/Content.Client/_Sunrise/BloodCult/CultPentagramSystem.cs new file mode 100644 index 00000000000..61442b9fb95 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/CultPentagramSystem.cs @@ -0,0 +1,65 @@ +using System.Numerics; +using Robust.Client.GameObjects; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Client._Sunrise.BloodCult; + +public sealed class CultPentagramSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _robustRandom = default!; + + private const string Rsi = "_Sunrise/BloodCult/pentagram.rsi"; + private static readonly string[] States = + { + "halo1", + "halo2", + "halo3", + "halo4", + "halo5", + "halo6" + }; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(PentagramAdded); + SubscribeLocalEvent(PentagramRemoved); + } + + private void PentagramAdded(EntityUid uid, PentagramComponent component, ComponentStartup args) + { + if (!TryComp(uid, out var sprite)) + return; + + if (sprite.LayerMapTryGet(PentagramKey.Key, out var _)) + return; + + var adj = sprite.Bounds.Height / 2 + ((1.0f/32) * 10.0f); + + var randomIndex = _robustRandom.Next(0, States.Length); + + var randomState = States[randomIndex]; + + var layer = sprite.AddLayer(new SpriteSpecifier.Rsi(new ResPath(Rsi), randomState)); + + sprite.LayerMapSet(PentagramKey.Key, layer); + sprite.LayerSetOffset(layer, new Vector2(0.0f, adj)); + } + + private void PentagramRemoved(EntityUid uid, PentagramComponent component, ComponentShutdown args) + { + if (!TryComp(uid, out var sprite)) + return; + + if (!sprite.LayerMapTryGet(PentagramKey.Key, out var layer)) + return; + + sprite.RemoveLayer(layer); + } + + private enum PentagramKey + { + Key + } +} diff --git a/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualizerSystem.cs b/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualizerSystem.cs new file mode 100644 index 00000000000..1d98e6e9de1 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualizerSystem.cs @@ -0,0 +1,40 @@ +using Content.Shared._Sunrise.BloodCult.Items; +using Robust.Client.GameObjects; + +namespace Content.Client._Sunrise.BloodCult.Items.VeilShifter; + +public sealed class VeilVisualizerSystem : VisualizerSystem +{ + private const string StateOn = "icon-on"; + private const string StateOff = "icon"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + } + + private void OnInit(EntityUid uid, VoidTeleportComponent component, ComponentInit args) + { + if (!TryComp(uid, out var sprite) + || !AppearanceSystem.TryGetData(uid, VeilVisuals.Activated, out var activated)) + return; + + sprite.LayerSetState(VeilVisualsLayers.Activated, activated ? StateOn : StateOff); + } + + protected override void OnAppearanceChange(EntityUid uid, VeilVisualsComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null + || !AppearanceSystem.TryGetData(uid, VeilVisuals.Activated, out var activated)) + return; + + args.Sprite.LayerSetState(VeilVisualsLayers.Activated, activated ? component.StateOn : component.StateOff); + } +} + +public enum VeilVisualsLayers : byte +{ + Activated +} diff --git a/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualsComponent.cs b/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualsComponent.cs new file mode 100644 index 00000000000..bad151df58a --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Items/VeilShifter/VeilVisualsComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Client._Sunrise.BloodCult.Items.VeilShifter; + +[RegisterComponent] +public sealed partial class VeilVisualsComponent : Component +{ + [DataField("stateOn")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOn = "icon-on"; + + [DataField("stateOff")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOff = "icon"; +} diff --git a/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualizerSystem.cs b/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualizerSystem.cs new file mode 100644 index 00000000000..0d61250eb48 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualizerSystem.cs @@ -0,0 +1,23 @@ +using Content.Shared._Sunrise.BloodCult.Items; +using Robust.Client.GameObjects; + +namespace Content.Client._Sunrise.BloodCult.Items.VoidTorch; + +public sealed class VoidTorchVisualizerSystem : VisualizerSystem +{ + protected override void OnAppearanceChange(EntityUid uid, VoidTorchVisualsComponent component, ref AppearanceChangeEvent args) + { + base.OnAppearanceChange(uid, component, ref args); + + if (args.Sprite == null + || !AppearanceSystem.TryGetData(uid, VoidTorchVisuals.Activated, out var activated)) + return; + + args.Sprite.LayerSetState(VoidTorchVisualsLayers.Activated, activated ? component.StateOn : component.StateOff); + } +} + +public enum VoidTorchVisualsLayers : byte +{ + Activated +} diff --git a/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualsComponent.cs b/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualsComponent.cs new file mode 100644 index 00000000000..add595d2b36 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Items/VoidTorch/VoidTorchVisualsComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Client._Sunrise.BloodCult.Items.VoidTorch; + +[RegisterComponent] +public sealed partial class VoidTorchVisualsComponent : Component +{ + [DataField("stateOn")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOn = "icon-on"; + + [DataField("stateOff")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOff = "icon"; +} diff --git a/Content.Client/_Sunrise/BloodCult/Narsie/NarsieLayer.cs b/Content.Client/_Sunrise/BloodCult/Narsie/NarsieLayer.cs new file mode 100644 index 00000000000..86f10f081a7 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Narsie/NarsieLayer.cs @@ -0,0 +1,6 @@ +namespace Content.Client._Sunrise.BloodCult.Narsie; + +public enum NarsieLayer +{ + Default +} diff --git a/Content.Client/_Sunrise/BloodCult/Narsie/NarsieVisualizer.cs b/Content.Client/_Sunrise/BloodCult/Narsie/NarsieVisualizer.cs new file mode 100644 index 00000000000..a5c51bb0930 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Narsie/NarsieVisualizer.cs @@ -0,0 +1,69 @@ +using Content.Shared._Sunrise.BloodCult; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; + +namespace Content.Client._Sunrise.BloodCult.Narsie; + +public sealed class NarsieVisualizer : VisualizerSystem +{ + [Dependency] private readonly AnimationPlayerSystem _animationSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAnimationCompleted); + } + + private void OnAnimationCompleted(EntityUid uid, NarsieComponent component, AnimationCompletedEvent args) + { + SetDefaultState(Comp(uid)); + } + + protected override void OnAppearanceChange(EntityUid uid, NarsieComponent component, ref AppearanceChangeEvent args) + { + base.OnAppearanceChange(uid, component, ref args); + + if(args.Sprite == null) return; + + if (!args.AppearanceData.TryGetValue(NarsieVisualState.VisualState, out var narsieVisualsObject) || narsieVisualsObject is not NarsieVisuals narsieVisual) + return; + + switch (narsieVisual) + { + case NarsieVisuals.Spawning: + PlaySpawnAnimation(uid); + break; + case NarsieVisuals.Spawned: + if(_animationSystem.HasRunningAnimation(uid, "narsie_spawn")) break; + SetDefaultState(args.Sprite); + break; + } + + } + + private void PlaySpawnAnimation(EntityUid uid) + { + _animationSystem.Play(uid, NarsieSpawnAnimation, "narsie_spawn"); + } + + private void SetDefaultState(SpriteComponent component) + { + component.LayerSetVisible(NarsieLayer.Default, true); + component.LayerSetState(NarsieLayer.Default, new RSI.StateId("narsie")); + component.LayerSetAutoAnimated(NarsieLayer.Default, true); + } + + private static readonly Animation NarsieSpawnAnimation = new() + { + Length = TimeSpan.FromSeconds(3.5), + AnimationTracks = + { + new AnimationTrackSpriteFlick() + { + LayerKey = NarsieLayer.Default, + KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(new RSI.StateId("narsie_spawn_anim"), 0f)} + } + } + }; +} diff --git a/Content.Client/_Sunrise/BloodCult/PentagramComponent.cs b/Content.Client/_Sunrise/BloodCult/PentagramComponent.cs new file mode 100644 index 00000000000..37579a0578a --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/PentagramComponent.cs @@ -0,0 +1,9 @@ +using Content.Shared._Sunrise.BloodCult.Pentagram; +using Robust.Shared.GameStates; + +namespace Content.Client._Sunrise.BloodCult; + +[NetworkedComponent, RegisterComponent] +public sealed partial class PentagramComponent : SharedPentagramComponent +{ +} diff --git a/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualizerSystem.cs b/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualizerSystem.cs new file mode 100644 index 00000000000..d787bccd5a2 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualizerSystem.cs @@ -0,0 +1,41 @@ +using Content.Shared._Sunrise.BloodCult.Pylon; +using Robust.Client.GameObjects; +using SharedPylonComponent = Content.Shared._Sunrise.BloodCult.Pylon.SharedPylonComponent; + +namespace Content.Client._Sunrise.BloodCult.Pylon; + +public sealed class PylonVisualizerSystem : VisualizerSystem +{ + private const string StateOn = "pylon"; + private const string StateOff = "pylon_off"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + } + + private void OnInit(EntityUid uid, SharedPylonComponent component, ComponentInit args) + { + if (!TryComp(uid, out var sprite) + || !AppearanceSystem.TryGetData(uid, PylonVisualsLayers.Activated, out var activated)) + return; + + sprite.LayerSetState(PylonVisualsLayers.Activated, activated ? StateOn : StateOff); + } + + protected override void OnAppearanceChange(EntityUid uid, PylonVisualsComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null + || !AppearanceSystem.TryGetData(uid, PylonVisuals.Activated, out var activated)) + return; + + args.Sprite.LayerSetState(PylonVisualsLayers.Activated, activated ? component.StateOn : component.StateOff); + } +} + +public enum PylonVisualsLayers : byte +{ + Activated +} diff --git a/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualsComponent.cs b/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualsComponent.cs new file mode 100644 index 00000000000..f5c63e906c9 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Pylon/PylonVisualsComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Client._Sunrise.BloodCult.Pylon; + +[RegisterComponent] +public sealed partial class PylonVisualsComponent : Component +{ + [DataField("stateOn")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOn = "pylon"; + + [DataField("stateOff")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOff = "pylon_off"; +} diff --git a/Content.Client/_Sunrise/BloodCult/ShowCultHudSystem.cs b/Content.Client/_Sunrise/BloodCult/ShowCultHudSystem.cs new file mode 100644 index 00000000000..47745109ca8 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/ShowCultHudSystem.cs @@ -0,0 +1,29 @@ +using Content.Shared._Sunrise.BloodCult.Components; +using Content.Shared.StatusIcon.Components; +using Robust.Client.Player; +using Robust.Shared.Prototypes; + +namespace Content.Client._Sunrise.BloodCult; +public sealed class ShowCultHudSystem : EntitySystem +{ + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + private void OnGetStatusIconsEvent(EntityUid uid, BloodCultistComponent bloodCultistComponent, ref GetStatusIconsEvent args) + { + var ent = _player.LocalSession?.AttachedEntity; + if (!HasComp(ent)) + return; + + if (_prototype.TryIndex(bloodCultistComponent.StatusIcon, out var iconPrototype)) + args.StatusIcons.Add(iconPrototype); + } +} + diff --git a/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualizerSystem.cs b/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualizerSystem.cs new file mode 100644 index 00000000000..f22cccc4fd2 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualizerSystem.cs @@ -0,0 +1,23 @@ +using Content.Shared._Sunrise.BloodCult; +using Robust.Client.GameObjects; + +namespace Content.Client._Sunrise.BloodCult.Structures; + +public sealed class CultCraftStructureVisualizerSystem : VisualizerSystem +{ + protected override void OnAppearanceChange(EntityUid uid, CultCraftStructureVisualsComponent component, ref AppearanceChangeEvent args) + { + base.OnAppearanceChange(uid, component, ref args); + + if (args.Sprite == null + || !AppearanceSystem.TryGetData(uid, CultCraftStructureVisuals.Activated, out var activated)) + return; + + args.Sprite.LayerSetState(CultCraftStructureVisualsLayers.Activated, activated ? component.StateOn : component.StateOff); + } +} + +public enum CultCraftStructureVisualsLayers : byte +{ + Activated +} diff --git a/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualsComponent.cs b/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualsComponent.cs new file mode 100644 index 00000000000..26368afbd75 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/Structures/CultCraftStructureVisualsComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Client._Sunrise.BloodCult.Structures; + +[RegisterComponent] +public sealed partial class CultCraftStructureVisualsComponent : Component +{ + [DataField("stateOn")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOn = "icon"; + + [DataField("stateOff")] + [ViewVariables(VVAccess.ReadWrite)] + public string? StateOff = "icon-off"; +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarBUI.cs b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarBUI.cs new file mode 100644 index 00000000000..5c701673cc4 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarBUI.cs @@ -0,0 +1,53 @@ +using Content.Shared._Sunrise.BloodCult.UI; +using JetBrains.Annotations; + +namespace Content.Client._Sunrise.BloodCult.UI.Altar; + +[UsedImplicitly] +public sealed class AltarBUI : BoundUserInterface +{ + private AltarWindow? _window; + + public AltarBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + IoCManager.InjectDependencies(this); + } + + protected override void Open() + { + base.Open(); + + _window = new AltarWindow(); + + _window.OnClose += Close; + _window.OnItemSelected += OnItemSelected; + } + + private void OnItemSelected(string item) + { + var evt = new AltarBuyRequest(item); + SendMessage(evt); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (!disposing) return; + _window?.Dispose(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is AltarListingBUIState listingState) + { + _window?.SetListing(listingState.Items); + } + else if(state is AltarTimerBUIState timerState) + { + _window?.SetTimer(timerState.NextTimeUse); + } + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml new file mode 100644 index 00000000000..04353875206 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml.cs b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml.cs new file mode 100644 index 00000000000..56a9be69c1b --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarListingControl.xaml.cs @@ -0,0 +1,20 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client._Sunrise.BloodCult.UI.Altar; + +[GenerateTypedNameReferences] +public partial class AltarListingControl : Control +{ + public AltarListingControl(EntityPrototype prototype, Robust.Client.Graphics.Texture icon, Action? clickAction) + { + RobustXamlLoader.Load(this); + + ToolTip = $"{prototype.Name}\n{prototype.Description}"; + + BuyListingButton.TextureNormal = icon; + BuyListingButton.OnButtonDown += _ => clickAction?.Invoke(prototype.ID); + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml new file mode 100644 index 00000000000..715cfdfd930 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml @@ -0,0 +1,7 @@ + + + + + diff --git a/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml.cs b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml.cs new file mode 100644 index 00000000000..4b20e55faa2 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/Altar/AltarWindow.xaml.cs @@ -0,0 +1,89 @@ +using Content.Client.TextScreen; +using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Client._Sunrise.BloodCult.UI.Altar; + +[GenerateTypedNameReferences] +public partial class AltarWindow : DefaultWindow +{ + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + [Dependency] private readonly PrototypeManager _prototypeManager = default!; + + + public event Action? OnItemSelected; + private TimeSpan? _nextTimeUse = null!; + + private List _listingControls = new(); + + public AltarWindow() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + if (_nextTimeUse == null) return; + + var remainingTime = _nextTimeUse.Value - _gameTiming.CurTime; + + if (remainingTime.TotalSeconds < 0) + { + remainingTime = TimeSpan.Zero; + } + + var remainingTimeText = TextScreenSystem.TimeToString(remainingTime); + + TimerLabel.SetMessage(remainingTimeText); + } + + public void SetListing(List prototypes) + { + foreach (var prototypeId in prototypes) + { + var prototype = _prototypeManager.Index(prototypeId); + if(prototype == null) return; + var prototypeIcon = _spriteSystem.GetPrototypeIcon(prototype).Default; + AddListingControl(prototype); + } + } + + public void AddListingControl(EntityPrototype entityPrototype) + { + var icon = _spriteSystem.GetPrototypeIcon(entityPrototype).Default; + var control = new AltarListingControl(entityPrototype, icon, OnItemSelected); + + ListingContainer.AddChild(control); + _listingControls.Add(control); + } + + public void SetTimer(TimeSpan? timer) + { + _nextTimeUse = timer; + + if (timer == null) + { + TimerLabel.SetMessage("Алтарь готов к использованию"); + SetListingButtonsState(true); + return; + } + + SetListingButtonsState(false); + } + + private void SetListingButtonsState(bool enabled) + { + foreach (var listingControl in _listingControls) + { + listingControl.BuyListingButton.Disabled = enabled; + } + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml b/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml new file mode 100644 index 00000000000..d56fc832898 --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml.cs b/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml.cs new file mode 100644 index 00000000000..8440f7fdcfc --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/BloodCultMenu.xaml.cs @@ -0,0 +1,70 @@ +using System.Numerics; +using Content.Client.UserInterface.Controls; +using Content.Shared.Chat.Prototypes; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client._Sunrise.BloodCult.UI; + +[GenerateTypedNameReferences] +public sealed partial class BloodCultMenu : RadialMenu +{ + [Dependency] private readonly EntityManager _entManager = default!; + + private EntityUid _owner; + + public BloodCultMenu() + { + IoCManager.InjectDependencies(this); + RobustXamlLoader.Load(this); + } + + public void SetEntity(EntityUid uid) + { + _owner = uid; + + if (!_entManager.EntityExists(_owner)) + { + Close(); + return; + } + } + + public RadialMenuTextureButton AddButton(string tooltip, Robust.Client.Graphics.Texture texture) + { + var button = new RadialMenuTextureButton() + { + StyleClasses = { "RadialMenuButton" }, + SetSize = new Vector2(64f, 64f), + ToolTip = tooltip, + }; + var scale = Vector2.One; + + if (texture.Width <= 32) + { + scale *= 2; + } + + var tex = new TextureRect + { + VerticalAlignment = VAlignment.Center, + HorizontalAlignment = HAlignment.Center, + Texture = texture, + TextureScale = scale, + }; + + button.AddChild(tex); + var main = FindControl("Main"); + main.AddChild(button); + + return button; + } +} + + +public sealed class EmoteMenuButton : RadialMenuTextureButton +{ + public ProtoId ProtoId { get; set; } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/BloodSpellSelector/BloodSpellSelectorBUI.cs b/Content.Client/_Sunrise/BloodCult/UI/BloodSpellSelector/BloodSpellSelectorBUI.cs new file mode 100644 index 00000000000..8d39b2478bd --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/BloodSpellSelector/BloodSpellSelectorBUI.cs @@ -0,0 +1,63 @@ +using Content.Shared._Sunrise.BloodCult.Items; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Input; +using Robust.Client.UserInterface; +using Robust.Shared.Prototypes; + +namespace Content.Client._Sunrise.BloodCult.UI.BloodSpellSelector; + +public sealed class BloodSpellSelectorBUI : BoundUserInterface +{ + [Dependency] private readonly IClyde _displayManager = default!; + [Dependency] private readonly IInputManager _inputManager = default!; + private BloodCultMenu? _menu; + + public BloodSpellSelectorBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + IoCManager.InjectDependencies(this); + } + + protected override void Open() + { + base.Open(); + _menu = this.CreateWindow(); + + var protoMan = IoCManager.Resolve(); + var entityMan = IoCManager.Resolve(); + var sprite = entityMan.System(); + + if (protoMan.TryIndex("CultBloodOrb", out EntityPrototype? bloodOrb)) + { + var texture = sprite.GetPrototypeIcon(bloodOrb); + var button = _menu.AddButton($"{bloodOrb.Name} (50)", texture.Default); + + button.OnPressed += _ => + { + SendMessage(new CultBloodSpellCreateOrbBuiMessage()); + Close(); + }; + } + + if (protoMan.TryIndex("BloodSpear", out EntityPrototype? bloodSpear)) + { + var texture = sprite.GetPrototypeIcon(bloodSpear); + var button = _menu.AddButton($"{bloodSpear.Name} (150)", texture.Default); + + button.OnPressed += _ => + { + SendMessage(new CultBloodSpellCreateBloodSpearBuiMessage()); + Close(); + }; + } + + var vpSize = _displayManager.ScreenSize; + _menu.OpenCenteredAt(_inputManager.MouseScreenPosition.Position / vpSize); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _menu?.Close(); + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/ConstructSelector/ConstructSelectorBui.cs b/Content.Client/_Sunrise/BloodCult/UI/ConstructSelector/ConstructSelectorBui.cs new file mode 100644 index 00000000000..1fd6bb9d26e --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/ConstructSelector/ConstructSelectorBui.cs @@ -0,0 +1,58 @@ +using Content.Shared._Sunrise.BloodCult.Components; +using Content.Shared._Sunrise.BloodCult.UI; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Input; +using Robust.Client.UserInterface; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Client._Sunrise.BloodCult.UI.ConstructSelector; + +public sealed class ConstructSelectorBui : BoundUserInterface +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IClyde _displayManager = default!; + [Dependency] private readonly IInputManager _inputManager = default!; + private SpriteSystem _spriteSystem = default!; + + private bool _selected; + private BloodCultMenu? _menu; + + public ConstructSelectorBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } + + protected override void Open() + { + base.Open(); + _menu = this.CreateWindow(); + + _spriteSystem = _entityManager.EntitySysManager.GetEntitySystem(); + var shellComponent = _entityManager.GetComponent(Owner); + + _menu.OnClose += () => + { + if(_selected) + return; + + SendMessage(new ConstructFormSelectedEvent(_random.Pick(shellComponent.ConstructForms))); + }; + + foreach (var form in shellComponent.ConstructForms) + { + var formPrototype = _prototypeManager.Index(form); + var button = _menu.AddButton(formPrototype.Name, _spriteSystem.GetPrototypeIcon(formPrototype).Default); + + button.OnPressed += _ => + { + _selected = true; + SendMessage(new ConstructFormSelectedEvent(form)); + _menu.Close(); + }; + } + + var vpSize = _displayManager.ScreenSize; + _menu.OpenCenteredAt(_inputManager.MouseScreenPosition.Position / vpSize); + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorBUI.cs b/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorBUI.cs new file mode 100644 index 00000000000..2e11085468e --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorBUI.cs @@ -0,0 +1,47 @@ +using Content.Shared._Sunrise.BloodCult.Items; +namespace Content.Client._Sunrise.BloodCult.UI.CountSelector; + +public sealed class CountSelectorBUI : BoundUserInterface +{ + public CountSelectorBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + private CountSelectorWindow? _window; + + protected override void Open() + { + base.Open(); + + _window = new(); + _window.OpenCentered(); + _window.OnCountChange += OnNameSelected; + _window.OnClose += Close; + } + + private void OnNameSelected(string name) + { + if (int.TryParse(name, out var count) && count >= 50) + { + SendMessage(new CountSelectorMessage(count)); + Close(); + } + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + if (state is not CountSelectorBuiState cast || _window == null) + { + return; + } + + _window.UpdateState(cast.Count); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _window?.Close(); + } +} diff --git a/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorWindow.xaml b/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorWindow.xaml new file mode 100644 index 00000000000..5e5cc0e397f --- /dev/null +++ b/Content.Client/_Sunrise/BloodCult/UI/CountSelector/CountSelectorWindow.xaml @@ -0,0 +1,10 @@ + + +