diff --git a/Intersect.Client.Core/Entities/Player.cs b/Intersect.Client.Core/Entities/Player.cs index 04d7cff10c..1f1ed6a37d 100644 --- a/Intersect.Client.Core/Entities/Player.cs +++ b/Intersect.Client.Core/Entities/Player.cs @@ -4,6 +4,7 @@ using Intersect.Client.Entities.Projectiles; using Intersect.Client.Framework.Entities; using Intersect.Client.Framework.GenericClasses; +using Intersect.Client.Framework.Input; using Intersect.Client.Framework.Items; using Intersect.Client.General; using Intersect.Client.Interface.Game.Chat; @@ -1720,6 +1721,14 @@ private void AutoTurnToTarget(Entity en) PickLastDirection(Dir); } + private static void ToggleTargetContextMenu(Entity en) + { + if (Globals.InputManager.MouseButtonDown(MouseButtons.Right)) + { + Interface.Interface.GameUi.TargetContextMenu.ToggleHidden(en); + } + } + public bool TryBlock() { var shieldIndex = Options.ShieldIndex; @@ -2622,6 +2631,7 @@ public void DrawTargets() en.Value.DrawTarget((int)Enums.TargetType.Selected); AutoTurnToTarget(en.Value); + ToggleTargetContextMenu(en.Value); } foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values.Cast()) @@ -2660,6 +2670,7 @@ public void DrawTargets() en.Value.DrawTarget((int)Enums.TargetType.Selected); AutoTurnToTarget(en.Value); + ToggleTargetContextMenu(en.Value); } } @@ -2693,6 +2704,7 @@ public void DrawTargets() if (TargetType != 0 || TargetIndex != en.Value.Id) { en.Value.DrawTarget((int)Enums.TargetType.Hover); + ToggleTargetContextMenu(en.Value); } } } @@ -2717,6 +2729,7 @@ public void DrawTargets() if (TargetType != 1 || TargetIndex != en.Value.Id) { en.Value.DrawTarget((int)Enums.TargetType.Hover); + ToggleTargetContextMenu(en.Value); } } } diff --git a/Intersect.Client.Core/Interface/Game/EntityPanel/EntityBox.cs b/Intersect.Client.Core/Interface/Game/EntityPanel/EntityBox.cs index d93448c670..c3802b312e 100644 --- a/Intersect.Client.Core/Interface/Game/EntityPanel/EntityBox.cs +++ b/Intersect.Client.Core/Interface/Game/EntityPanel/EntityBox.cs @@ -4,10 +4,8 @@ using Intersect.Client.Framework.File_Management; using Intersect.Client.Framework.Gwen; using Intersect.Client.Framework.Gwen.Control; -using Intersect.Client.Framework.Gwen.Control.EventArguments; using Intersect.Client.General; using Intersect.Client.Localization; -using Intersect.Client.Networking; using Intersect.Configuration; using Intersect.Enums; using Intersect.GameObjects; @@ -96,20 +94,8 @@ public partial class EntityBox public bool ShouldUpdateStatuses; - public bool IsHidden; - // Context menu - private Button _contextMenuButton; - - private Framework.Gwen.Control.Menu _contextMenu; - - private MenuItem _tradeMenuItem; - - private MenuItem _partyMenuItem; - - private MenuItem _friendMenuItem; - - private MenuItem _guildMenuItem; + private readonly Button _contextMenuButton; //Init public EntityBox(Canvas gameCanvas, EntityType entityType, Entity? myEntity, bool isPlayerBox = false) @@ -180,35 +166,10 @@ public EntityBox(Canvas gameCanvas, EntityType entityType, Entity? myEntity, boo // Target context menu with basic options. if (!_isPlayerBox) { - _contextMenu = new Framework.Gwen.Control.Menu(gameCanvas, "TargetContextMenu") - { - IsHidden = true, - IconMarginDisabled = true - }; - - _contextMenu.Children.Clear(); - - _tradeMenuItem = _contextMenu.AddItem(Strings.EntityBox.Trade); - _tradeMenuItem.Clicked += tradeRequest_Clicked; - - _partyMenuItem = _contextMenu.AddItem(Strings.EntityBox.Party); - _partyMenuItem.Clicked += invite_Clicked; - - _friendMenuItem = _contextMenu.AddItem(Strings.EntityBox.Friend); - _friendMenuItem.Clicked += friendRequest_Clicked; - - _guildMenuItem = _contextMenu.AddItem(Strings.Guilds.Guild); - _guildMenuItem.Clicked += guildRequest_Clicked; - - _contextMenu.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); - _contextMenuButton = new Button(EntityInfoPanel, "ContextMenuButton"); - _contextMenuButton.Clicked += (sender, e) => + _contextMenuButton.Clicked += (_, _) => { - _contextMenu.SizeToChildren(); - _contextMenu.Open(Pos.None); - _contextMenu.SetPosition(_contextMenuButton.LocalPosToCanvas(new Point(0, 0)).X, - _contextMenuButton.LocalPosToCanvas(new Point(0, 0)).Y + _contextMenuButton.Height); + Interface.GameUi.TargetContextMenu.ToggleHidden(_contextMenuButton); }; EntityStatusWindow = new ImagePanel(EntityWindow, "EntityStatusWindow"); @@ -283,7 +244,6 @@ public void ShowAllElements() if (!_isPlayerBox) { - TryShowGuildButton(); _contextMenuButton.Show(); EventDesc.Show(); } @@ -417,7 +377,6 @@ public void Update() //Update the event/entity face. UpdateImage(); - IsHidden = true; if (EntityType != EntityType.Event) { EntityName.SetText(MyEntity.Name); @@ -425,7 +384,6 @@ public void Update() UpdateMap(); UpdateHpBar(elapsedTime); UpdateMpBar(elapsedTime); - IsHidden = false; } else { @@ -449,7 +407,6 @@ public void Update() } else if (_contextMenuButton.IsHidden && !_isPlayerBox) { - TryShowGuildButton(); _contextMenuButton.Show(); } } @@ -938,108 +895,6 @@ public void Dispose() EntityWindow.Dispose(); } - //Input Handlers - void invite_Clicked(Base sender, ClickedEventArgs arguments) - { - if (Globals.Me.TargetIndex != Guid.Empty && Globals.Me.TargetIndex != Globals.Me.Id) - { - if (Globals.Me.CombatTimer < Timing.Global.Milliseconds) - { - PacketSender.SendPartyInvite(Globals.Me.TargetIndex); - } - else - { - PacketSender.SendChatMsg(Strings.Parties.InFight.ToString(), 4); - } - } - } - - //Input Handlers - void tradeRequest_Clicked(Base sender, ClickedEventArgs arguments) - { - if (Globals.Me.TargetIndex != Guid.Empty && Globals.Me.TargetIndex != Globals.Me.Id) - { - if (Globals.Me.CombatTimer < Timing.Global.Milliseconds) - { - PacketSender.SendTradeRequest(Globals.Me.TargetIndex); - } - else - { - PacketSender.SendChatMsg(Strings.Trading.InFight.ToString(), 4); - } - } - } - - //Input Handlers - void friendRequest_Clicked(Base sender, ClickedEventArgs arguments) - { - if (Globals.Me.TargetIndex != Guid.Empty && Globals.Me.TargetIndex != Globals.Me.Id) - { - if (Globals.Me.CombatTimer < Timing.Global.Milliseconds) - { - PacketSender.SendAddFriend(MyEntity.Name); - } - else - { - PacketSender.SendChatMsg(Strings.Friends.InFight.ToString(), 4); - } - } - } - - - void guildRequest_Clicked(Base sender, ClickedEventArgs arguments) - { - if (MyEntity is Player plyr && MyEntity != Globals.Me) - { - if (string.IsNullOrWhiteSpace(plyr.Guild)) - { - if (Globals.Me?.GuildRank?.Permissions?.Invite ?? false) - { - if (Globals.Me.CombatTimer < Timing.Global.Milliseconds) - { - PacketSender.SendInviteGuild(MyEntity.Name); - } - else - { - PacketSender.SendChatMsg(Strings.Friends.InFight.ToString(), 4); - } - } - } - else - { - Chat.ChatboxMsg.AddMessage(new Chat.ChatboxMsg(Strings.Guilds.InviteAlreadyInGuild, Color.Red, ChatMessageType.Guild)); - } - } - } - - void TryShowGuildButton() - { - var shouldShow = false; - if (MyEntity is Player plyr && MyEntity != Globals.Me && string.IsNullOrWhiteSpace(plyr.Guild)) - { - if (Globals.Me?.GuildRank?.Permissions?.Invite ?? false) - { - shouldShow = true; - } - } - - if (shouldShow) - { - if (!_contextMenu.Children.Contains(_guildMenuItem)) - { - _contextMenu.Children.Add(_guildMenuItem); - } - } - else - { - if (_contextMenu.Children.Contains(_guildMenuItem)) - { - _contextMenu.Children.Remove(_guildMenuItem); - } - } - } - - public void Hide() { EntityWindow.Hide(); diff --git a/Intersect.Client.Core/Interface/Game/GameInterface.cs b/Intersect.Client.Core/Interface/Game/GameInterface.cs index a59008ce9a..35fe9101e4 100644 --- a/Intersect.Client.Core/Interface/Game/GameInterface.cs +++ b/Intersect.Client.Core/Interface/Game/GameInterface.cs @@ -94,6 +94,7 @@ public GameInterface(Canvas canvas) : base(canvas) GameCanvas = canvas; EscapeMenu = new EscapeMenu(GameCanvas) {IsHidden = true}; SimplifiedEscapeMenu = new SimplifiedEscapeMenu(GameCanvas) {IsHidden = true}; + TargetContextMenu = new TargetContextMenu(GameCanvas) {IsHidden = true}; AnnouncementWindow = new AnnouncementWindow(GameCanvas) { IsHidden = true }; InitGameGui(); @@ -102,9 +103,11 @@ public GameInterface(Canvas canvas) : base(canvas) public Canvas GameCanvas { get; } public EscapeMenu EscapeMenu { get; } - + public SimplifiedEscapeMenu SimplifiedEscapeMenu { get; } + public TargetContextMenu TargetContextMenu { get; } + public AnnouncementWindow AnnouncementWindow { get; } public Menu GameMenu { get; private set; } diff --git a/Intersect.Client.Core/Interface/Game/TargetContextMenu.cs b/Intersect.Client.Core/Interface/Game/TargetContextMenu.cs new file mode 100644 index 0000000000..7c9e3a0a46 --- /dev/null +++ b/Intersect.Client.Core/Interface/Game/TargetContextMenu.cs @@ -0,0 +1,235 @@ +using Intersect.Client.Core; +using Intersect.Client.Entities; +using Intersect.Client.Framework.File_Management; +using Intersect.Client.Framework.Gwen; +using Intersect.Client.Framework.Gwen.Control; +using Intersect.Client.Framework.Gwen.Control.EventArguments; +using Intersect.Client.Framework.Gwen.Input; +using Intersect.Client.Framework.Input; +using Intersect.Client.General; +using Intersect.Client.Localization; +using Intersect.Client.Networking; +using Intersect.Enums; +using Intersect.Utilities; + +namespace Intersect.Client.Interface.Game; + +/// +/// The GUI class for the Target Context Menu that pop up on-screen during gameplay. +/// +public sealed partial class TargetContextMenu : Framework.Gwen.Control.Menu +{ + private readonly MenuItem _tradeMenuItem; + private readonly MenuItem _partyMenuItem; + private readonly MenuItem _friendMenuItem; + private readonly MenuItem _guildMenuItem; + private readonly MenuItem _privateMessageMenuItem; + private readonly Player? _me; + private Entity? _entity; + + public TargetContextMenu(Canvas gameCanvas) : base(gameCanvas, nameof(TargetContextMenu)) + { + IsHidden = true; + IconMarginDisabled = true; + Children.Clear(); + + _me = Globals.Me; + + _tradeMenuItem = AddItem(Strings.EntityContextMenu.Trade); + _tradeMenuItem.Clicked += tradeRequest_Clicked; + + _partyMenuItem = AddItem(Strings.EntityContextMenu.InviteToParty); + _partyMenuItem.Clicked += invite_Clicked; + + _friendMenuItem = AddItem(Strings.EntityContextMenu.AddFriend); + _friendMenuItem.Clicked += friendRequest_Clicked; + + _guildMenuItem = AddItem(Strings.EntityContextMenu.InviteToGuild); + _guildMenuItem.Clicked += guildRequest_Clicked; + + _privateMessageMenuItem = AddItem(Strings.EntityContextMenu.PrivateMessage); + _privateMessageMenuItem.Clicked += privateMessageRequest_Clicked; + + LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer?.GetResolutionString()); + } + + public void ToggleHidden(object? target) + { + if (target == null || _me == null) + { + return; + } + + float posX, posY, newX, newY; + + switch (target) + { + case Button button: + _entity = _me.TargetBox?.MyEntity; + posX = button.LocalPosToCanvas(Point.Empty).X; + posY = button.LocalPosToCanvas(Point.Empty).Y; + newX = posX; + newY = posY + button.Height; + break; + + case Player player when player != _me: + var mousePos = Graphics.ConvertToWorldPoint(Globals.InputManager.MousePosition); + if (!player.WorldPos.Contains(mousePos.X, mousePos.Y)) + { + return; + } + + _entity = player; + posX = InputHandler.MousePosition.X; + posY = InputHandler.MousePosition.Y; + newX = posX; + newY = posY; + break; + + default: + return; + } + + if (Canvas is { } canvas) + { + if (newX + Width >= canvas.Width) + { + newX = posX - Width + (target is Button button ? button.Width : 0); + } + + if (newY + Height >= canvas.Height) + { + newY = posY - Height + (target is Button button ? button.Height : 0); + } + } + + if (IsHidden) + { + TryShowGuildButton(); + SizeToChildren(); + Open(Pos.None); + SetPosition(newX, newY); + } + else if (!Globals.InputManager.MouseButtonDown(MouseButtons.Right)) + { + Close(); + } + } + + void invite_Clicked(Base sender, ClickedEventArgs arguments) + { + if (_me == null || _entity is not Player || _entity == _me) + { + return; + } + + if (_me.CombatTimer < Timing.Global.Milliseconds) + { + PacketSender.SendPartyInvite(_entity.Id); + } + else + { + PacketSender.SendChatMsg(Strings.Parties.InFight.ToString(), 4); + } + } + + void tradeRequest_Clicked(Base sender, ClickedEventArgs arguments) + { + if (_me == null || _entity is not Player || _entity == _me) + { + return; + } + + if (_me.CombatTimer < Timing.Global.Milliseconds) + { + PacketSender.SendTradeRequest(_entity.Id); + } + else + { + PacketSender.SendChatMsg(Strings.Trading.InFight.ToString(), 4); + } + } + + void friendRequest_Clicked(Base sender, ClickedEventArgs arguments) + { + if (_me == null || _entity is not Player || _entity == _me) + { + return; + } + + if (_me.CombatTimer < Timing.Global.Milliseconds) + { + PacketSender.SendAddFriend(_entity.Name); + } + else + { + PacketSender.SendChatMsg(Strings.Friends.InFight.ToString(), 4); + } + } + + void guildRequest_Clicked(Base sender, ClickedEventArgs arguments) + { + if (_me == null || _entity is not Player plyr || _entity == _me) + { + return; + } + + if (string.IsNullOrWhiteSpace(plyr.Guild)) + { + if (_me?.GuildRank?.Permissions?.Invite ?? false) + { + if (_me.CombatTimer < Timing.Global.Milliseconds) + { + PacketSender.SendInviteGuild(_entity.Name); + } + else + { + PacketSender.SendChatMsg(Strings.Friends.InFight.ToString(), 4); + } + } + } + else + { + Chat.ChatboxMsg.AddMessage( + new Chat.ChatboxMsg(Strings.Guilds.InviteAlreadyInGuild, Color.Red, ChatMessageType.Guild) + ); + } + } + + void privateMessageRequest_Clicked(Base sender, ClickedEventArgs arguments) + { + if (_me == null || _entity is not Player || _entity == _me) + { + return; + } + + Interface.GameUi.SetChatboxText($"/pm {_entity.Name} "); + } + + void TryShowGuildButton() + { + var shouldShow = false; + if (_entity is Player plyr && _entity != _me && string.IsNullOrWhiteSpace(plyr.Guild)) + { + if (_me?.GuildRank?.Permissions?.Invite ?? false) + { + shouldShow = true; + } + } + + if (shouldShow) + { + if (!Children.Contains(_guildMenuItem)) + { + Children.Add(_guildMenuItem); + } + } + else + { + if (Children.Contains(_guildMenuItem)) + { + Children.Remove(_guildMenuItem); + } + } + } +} \ No newline at end of file diff --git a/Intersect.Client.Core/Localization/Strings.cs b/Intersect.Client.Core/Localization/Strings.cs index eac7c18ee9..6521434679 100644 --- a/Intersect.Client.Core/Localization/Strings.cs +++ b/Intersect.Client.Core/Localization/Strings.cs @@ -919,9 +919,6 @@ public partial struct EntityBox [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public static LocalizedString ExpValue = @"{00} / {01}"; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public static LocalizedString Friend = "Befriend"; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public static LocalizedString Level = @"Lv. {00}"; @@ -934,12 +931,6 @@ public partial struct EntityBox [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public static LocalizedString NameAndLevel = @"{00} {01}"; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public static LocalizedString Party = @"Party"; - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public static LocalizedString Trade = @"Trade"; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public static LocalizedString Vital0 = @"HP:"; @@ -1285,6 +1276,24 @@ public partial struct Inventory public static LocalizedString Title = @"Inventory"; } + public partial struct EntityContextMenu + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public static LocalizedString AddFriend = @"Add Friend"; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public static LocalizedString InviteToGuild = @"Invite to Guild"; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public static LocalizedString InviteToParty = @"Invite to Party"; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public static LocalizedString PrivateMessage = @"Private Message"; + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public static LocalizedString Trade = @"Trade"; + } + public partial struct ItemContextMenu { [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]